Чё-то делается
This commit is contained in:
parent
178d0953d3
commit
9fea8e3bc4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8
compose/.idea/modules/app/pmu-demo.app.iml
generated
8
compose/.idea/modules/app/pmu-demo.app.iml
generated
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="ModuleClassLoaderOverlays">
|
||||
<paths>
|
||||
<option value="C:\Users\egore\AppData\Local\Temp\overlay16197097467506260191" />
|
||||
</paths>
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,11 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api
|
||||
|
||||
object ApiRoutes {
|
||||
const val BASE = "http://10.0.2.2:8079/"
|
||||
const val USER = "users"
|
||||
const val LEVEL = "level"
|
||||
const val NATION = "nation"
|
||||
const val TANK = "TANK"
|
||||
const val USER_TANK = "userTanks"
|
||||
const val NOT_USER_TANK = "notUserTanks"
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api
|
||||
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.LevelRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.NationRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.TankRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.TankWithNationAndLevelRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.UserRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.UserTankCrossRefRemote
|
||||
|
||||
interface ServerService {
|
||||
// :[USER]
|
||||
|
||||
@GET(ApiRoutes.USER)
|
||||
suspend fun getUserByEmail(
|
||||
@Query("email") email: String
|
||||
): UserRemote
|
||||
|
||||
@POST(ApiRoutes.USER)
|
||||
suspend fun insertUser(
|
||||
@Body user: UserRemote
|
||||
): UserRemote
|
||||
|
||||
@PUT("${ApiRoutes.USER}/{id}")
|
||||
suspend fun updateUser(
|
||||
@Path("id") id: Long,
|
||||
@Body user: UserRemote
|
||||
): UserRemote
|
||||
|
||||
|
||||
// ![USER]
|
||||
|
||||
// :[LEVEL]
|
||||
|
||||
@GET(ApiRoutes.LEVEL)
|
||||
suspend fun getLevels(): List<LevelRemote>
|
||||
|
||||
@GET("${ApiRoutes.LEVEL}/{id}")
|
||||
suspend fun getLevel(
|
||||
@Path("id") id: Long
|
||||
): LevelRemote
|
||||
|
||||
@POST(ApiRoutes.LEVEL)
|
||||
suspend fun insertLevel(
|
||||
@Body level: LevelRemote
|
||||
): LevelRemote
|
||||
|
||||
@PUT("${ApiRoutes.LEVEL}/{id}")
|
||||
suspend fun updateLevel(
|
||||
@Path("id") id: Long,
|
||||
@Body level: LevelRemote
|
||||
): LevelRemote
|
||||
|
||||
@DELETE("${ApiRoutes.LEVEL}/{id}")
|
||||
suspend fun deleteLevel(
|
||||
@Path("id") id: Long
|
||||
): LevelRemote
|
||||
|
||||
// ![LEVEL]
|
||||
|
||||
// :[NATION]
|
||||
|
||||
@GET(ApiRoutes.NATION)
|
||||
suspend fun getNations(
|
||||
@Query("_page") page: Int,
|
||||
@Query("_limit") limit: Int
|
||||
): List<NationRemote>
|
||||
|
||||
@GET("${ApiRoutes.NATION}/{id}")
|
||||
suspend fun getNation(
|
||||
@Path("id") id: Long
|
||||
): NationRemote
|
||||
|
||||
@POST(ApiRoutes.NATION)
|
||||
suspend fun insertNation(
|
||||
@Body product: NationRemote
|
||||
): NationRemote
|
||||
|
||||
@PUT("${ApiRoutes.NATION}/{id}")
|
||||
suspend fun updateNation(
|
||||
@Path("id") id: Long,
|
||||
@Body product: NationRemote
|
||||
): NationRemote
|
||||
|
||||
@DELETE("${ApiRoutes.NATION}/{id}")
|
||||
suspend fun deleteNation(
|
||||
@Path("id") id: Long
|
||||
): NationRemote
|
||||
|
||||
// ![NATION]
|
||||
|
||||
// :[TANK]
|
||||
|
||||
@GET(ApiRoutes.TANK)
|
||||
suspend fun getTanks(): List<TankRemote>
|
||||
|
||||
@GET("${ApiRoutes.TANK}/{id}")
|
||||
suspend fun getTank(
|
||||
@Path("id") id: Long
|
||||
): TankRemote
|
||||
|
||||
@GET("${ApiRoutes.TANK}/forPurchase")
|
||||
suspend fun getTanksForPurchase(
|
||||
@Path("id") userId: Long
|
||||
): List<TankRemote>
|
||||
|
||||
@GET("${ApiRoutes.TANK}/myHangar")
|
||||
suspend fun getTanksFromHangar(
|
||||
@Path("id") userId: Long
|
||||
): List<TankWithNationAndLevelRemote>
|
||||
|
||||
@POST(ApiRoutes.TANK)
|
||||
suspend fun insertTank(
|
||||
@Body tank: TankRemote
|
||||
): TankRemote
|
||||
|
||||
@PUT("${ApiRoutes.TANK}/{id}")
|
||||
suspend fun updateTank(
|
||||
@Path("id") id: Long,
|
||||
@Body tank: TankRemote
|
||||
): TankRemote
|
||||
|
||||
@DELETE("${ApiRoutes.TANK}/{id}")
|
||||
suspend fun deleteTank(
|
||||
@Path("id") id: Long
|
||||
): TankRemote
|
||||
|
||||
// ![TANK]
|
||||
|
||||
// :[USER_TANK_CROSS_REF]
|
||||
|
||||
@GET("${ApiRoutes.USER_TANK}?_hangar={userId}")
|
||||
suspend fun getUserTankCrossRef(
|
||||
@Path("userId") userId: Long,
|
||||
): List<UserTankCrossRefRemote>
|
||||
|
||||
@POST(ApiRoutes.USER_TANK)
|
||||
suspend fun insertUserTankCrossRef(
|
||||
@Body tank: UserTankCrossRefRemote
|
||||
) : UserTankCrossRefRemote
|
||||
|
||||
@DELETE("${ApiRoutes.USER_TANK}/deleteMyTank")
|
||||
suspend fun deleteUserTankCrossRef(
|
||||
@Body tank: UserTankCrossRefRemote
|
||||
): UserTankCrossRefRemote
|
||||
|
||||
// ![USER_TANK_CROSS_REF]
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = ApiRoutes.BASE
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: ServerService? = null
|
||||
|
||||
fun getInstance(): ServerService {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val logger = HttpLoggingInterceptor()
|
||||
logger.level = HttpLoggingInterceptor.Level.BASIC
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(logger)
|
||||
.build()
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
.create(ServerService::class.java)
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.mediator
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import retrofit2.HttpException
|
||||
import ru.ulstu.`is`.pmu.tank.api.ServerService
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toLevel
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toNation
|
||||
import ru.ulstu.`is`.pmu.tank.database.AppDatabase
|
||||
import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeyType
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeys
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineNationRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineRemoteKeyRepository
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class NationRemoteMediator(
|
||||
private val service: ServerService,
|
||||
private val dbNationRepository: OfflineNationRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : RemoteMediator<Int, Nation>() {
|
||||
|
||||
override suspend fun initialize(): InitializeAction {
|
||||
return InitializeAction.LAUNCH_INITIAL_REFRESH
|
||||
}
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Nation>
|
||||
): MediatorResult {
|
||||
val page = when (loadType) {
|
||||
LoadType.REFRESH -> {
|
||||
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
|
||||
remoteKeys?.nextKey?.minus(1) ?: 1
|
||||
}
|
||||
|
||||
LoadType.PREPEND -> {
|
||||
val remoteKeys = getRemoteKeyForFirstItem(state)
|
||||
remoteKeys?.prevKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
|
||||
LoadType.APPEND -> {
|
||||
val remoteKeys = getRemoteKeyForLastItem(state)
|
||||
remoteKeys?.nextKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val nations = service.getNations(page, state.config.pageSize).map { it.toNation() }
|
||||
val endOfPaginationReached = nations.isEmpty()
|
||||
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.NATION)
|
||||
dbNationRepository.deleteNations()
|
||||
}
|
||||
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
val keys = nations.map {
|
||||
RemoteKeys(
|
||||
entityId = it.uid!!.toInt(),
|
||||
type = RemoteKeyType.NATION,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
dbNationRepository.insertNations(nations)
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
} catch (exception: IOException) {
|
||||
return MediatorResult.Error(exception)
|
||||
} catch (exception: HttpException) {
|
||||
return MediatorResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Nation>): RemoteKeys? {
|
||||
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
|
||||
?.let { nation ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(nation.uid!!.toInt(), RemoteKeyType.NATION)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Nation>): RemoteKeys? {
|
||||
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
|
||||
?.let { nation ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(nation.uid!!.toInt(), RemoteKeyType.NATION)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyClosestToCurrentPosition(
|
||||
state: PagingState<Int, Nation>
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.uid?.let { nationUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(nationUid.toInt(), RemoteKeyType.NATION)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import kotlinx.serialization.Serializable
|
||||
import ru.ulstu.`is`.pmu.tank.model.Level
|
||||
import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
|
||||
@Serializable
|
||||
data class LevelRemote (
|
||||
val uid: Long = 0,
|
||||
val level: Int = 0
|
||||
)
|
||||
|
||||
fun LevelRemote.toLevel(): Level = Level(
|
||||
uid,
|
||||
level
|
||||
)
|
||||
|
||||
fun Level.toRemote(): LevelRemote = LevelRemote(
|
||||
uid!!,
|
||||
level
|
||||
)
|
@ -0,0 +1,20 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
|
||||
@Serializable
|
||||
data class NationRemote(
|
||||
val uid: Long = 0,
|
||||
val nationName: String = ""
|
||||
)
|
||||
|
||||
fun NationRemote.toNation(): Nation = Nation(
|
||||
uid,
|
||||
nationName
|
||||
)
|
||||
|
||||
fun Nation.toRemote(): NationRemote = NationRemote(
|
||||
uid!!,
|
||||
nationName
|
||||
)
|
@ -0,0 +1,38 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.model
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.application.ui.toBase64
|
||||
import com.application.ui.toBitmap
|
||||
import kotlinx.serialization.Serializable
|
||||
import ru.ulstu.`is`.pmu.tank.model.Tank
|
||||
|
||||
@Serializable
|
||||
data class TankRemote(
|
||||
val tankId: Long = 0,
|
||||
val name: String = "",
|
||||
val price: Int = 0,
|
||||
val miniature: String = "",
|
||||
val imageId: Long = 0,
|
||||
val levelId: Long = 0,
|
||||
val nationId: Long = 0,
|
||||
)
|
||||
|
||||
fun TankRemote.toTank(): Tank = Tank(
|
||||
tankId = tankId,
|
||||
name = name,
|
||||
price = price,
|
||||
miniature = miniature.toBitmap(),
|
||||
imageId = imageId,
|
||||
levelId = levelId,
|
||||
nationId = nationId
|
||||
)
|
||||
|
||||
fun Tank.toRemote(): TankRemote = TankRemote(
|
||||
tankId = tankId!!,
|
||||
name = name,
|
||||
price = price,
|
||||
miniature = miniature.toBase64(),
|
||||
imageId = imageId,
|
||||
levelId = levelId!!,
|
||||
nationId = nationId!!
|
||||
)
|
@ -0,0 +1,34 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.model
|
||||
|
||||
import com.application.ui.toBase64
|
||||
import com.application.ui.toBitmap
|
||||
import kotlinx.serialization.Serializable
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
|
||||
@Serializable
|
||||
data class TankWithNationAndLevelRemote(
|
||||
val tankId: Long,
|
||||
val name: String,
|
||||
val price: Int,
|
||||
val image: String,
|
||||
val level: Int,
|
||||
val nationName: String
|
||||
)
|
||||
|
||||
fun TankWithNationAndLevelRemote.toTankWithNationAndLevel(): TankWithNationAndLevel = TankWithNationAndLevel(
|
||||
tankId = tankId,
|
||||
name = name,
|
||||
price = price,
|
||||
image = image.toBitmap(),
|
||||
level = level,
|
||||
nationName = nationName
|
||||
)
|
||||
|
||||
fun TankWithNationAndLevel.toRemote(): TankWithNationAndLevelRemote = TankWithNationAndLevelRemote(
|
||||
tankId = tankId!!,
|
||||
name = name,
|
||||
price = price,
|
||||
image = image.toBase64(),
|
||||
level = level,
|
||||
nationName = nationName
|
||||
)
|
@ -0,0 +1,33 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import ru.ulstu.`is`.pmu.tank.model.User
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserRole
|
||||
|
||||
@Serializable
|
||||
data class UserRemote (
|
||||
val id: Long = 0,
|
||||
val nickname: String = "",
|
||||
val email: String = " ",
|
||||
val role: Int = -1,
|
||||
val password: String = "",
|
||||
val balance: Int = 0
|
||||
)
|
||||
|
||||
fun UserRemote.toUser(): User = User(
|
||||
userId = id,
|
||||
nickname = nickname,
|
||||
email = email,
|
||||
password = password,
|
||||
role = enumValues<UserRole>()[role],
|
||||
balance = balance
|
||||
)
|
||||
|
||||
fun User.toRemote(): UserRemote = UserRemote(
|
||||
id = userId,
|
||||
nickname = nickname,
|
||||
email = email,
|
||||
password = password,
|
||||
role = role.ordinal,
|
||||
balance = balance
|
||||
)
|
@ -0,0 +1,9 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserTankCrossRefRemote (
|
||||
val userId: Long = 0,
|
||||
val tankId: Long = 0
|
||||
)
|
@ -0,0 +1,51 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.repository
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.ulstu.`is`.pmu.tank.api.ServerService
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toLevel
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toRemote
|
||||
import ru.ulstu.`is`.pmu.tank.model.Level
|
||||
import ru.ulstu.`is`.pmu.tank.model.LevelWithTanks
|
||||
import ru.ulstu.`is`.pmu.tank.repository.LevelRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineLevelRepository
|
||||
|
||||
class RestLevelRepository(
|
||||
private val service: ServerService,
|
||||
private val dbLevelRepository: OfflineLevelRepository,
|
||||
) : LevelRepository {
|
||||
override suspend fun getAllLevels(): List<Level> {
|
||||
dbLevelRepository.deleteAll()
|
||||
val levels = service.getLevels().map { it.toLevel() }
|
||||
dbLevelRepository.insertMany(levels)
|
||||
return levels
|
||||
}
|
||||
|
||||
override suspend fun getSimpleLevel(uid: Long): Level {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getFullLevel(uid: Long): Flow<LevelWithTanks?> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun insertLevel(level: Level) {
|
||||
service.insertLevel(level.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun insertMany(levels: List<Level>) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun updateLevel(level: Level) {
|
||||
service.updateLevel(level.uid!!, level.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun deleteLevel(level: Level) {
|
||||
service.deleteLevel(level.uid!!)
|
||||
dbLevelRepository.deleteLevel(level)
|
||||
}
|
||||
|
||||
override suspend fun deleteAll() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.repository
|
||||
|
||||
import android.util.Log
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.map
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import ru.ulstu.`is`.pmu.tank.api.ServerService
|
||||
import ru.ulstu.`is`.pmu.tank.api.mediator.NationRemoteMediator
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.NationRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toNation
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toRemote
|
||||
import ru.ulstu.`is`.pmu.tank.database.AppContainer
|
||||
import ru.ulstu.`is`.pmu.tank.database.AppDatabase
|
||||
import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
import ru.ulstu.`is`.pmu.tank.model.NationWithTanks
|
||||
import ru.ulstu.`is`.pmu.tank.repository.NationRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineNationRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineRemoteKeyRepository
|
||||
|
||||
class RestNationRepository(
|
||||
private val service: ServerService,
|
||||
private val dbNationRepository: OfflineNationRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : NationRepository {
|
||||
override suspend fun getAllNations(): List<Nation> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun getAll(): Flow<PagingData<Nation>> {
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = 10,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = NationRemoteMediator(
|
||||
service = service,
|
||||
dbNationRepository = dbNationRepository,
|
||||
dbRemoteKeyRepository = dbRemoteKeyRepository,
|
||||
database = database,
|
||||
),
|
||||
) {
|
||||
dbNationRepository.pagingSource()
|
||||
}.flow
|
||||
}
|
||||
|
||||
override fun getSimpleNation(uid: Long): Flow<Nation?> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getFullNation(uid: Long): Flow<NationWithTanks?> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun pagingSource(): PagingSource<Int, Nation> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun insertNation(nation: Nation) {
|
||||
service.insertNation(nation.toRemote()).toNation()
|
||||
}
|
||||
|
||||
override suspend fun insertNations(nations: List<Nation>) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun updateNation(nation: Nation) {
|
||||
service.updateNation(nation.uid!!, nation.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun deleteNation(nation: Nation) {
|
||||
service.deleteNation(nation.uid!!)
|
||||
}
|
||||
|
||||
override suspend fun deleteNations() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.repository
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.ulstu.`is`.pmu.tank.api.ServerService
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toLevel
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toTank
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toTankWithNationAndLevel
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toUser
|
||||
import ru.ulstu.`is`.pmu.tank.model.Tank
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
import ru.ulstu.`is`.pmu.tank.model.User
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineTankRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineUserRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.TankRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.UserRepository
|
||||
|
||||
class RestTankReppository (
|
||||
private val service: ServerService,
|
||||
private val dbTankRepository: OfflineTankRepository,
|
||||
) : TankRepository {
|
||||
override suspend fun getAll(): List<Tank> {
|
||||
dbTankRepository.deleteAll()
|
||||
val tanks = service.getTanks().map { it.toTank() }
|
||||
dbTankRepository.insertMany(tanks)
|
||||
return tanks
|
||||
}
|
||||
|
||||
override suspend fun getForUserAll(userId: Long): List<Tank> {
|
||||
return service.getTanksForPurchase(userId).map { it.toTank() }
|
||||
}
|
||||
|
||||
override suspend fun getTank(uid: Long): Tank {
|
||||
return service.getTank(uid).toTank()
|
||||
}
|
||||
|
||||
override suspend fun getUserTanks(uid: Long): List<TankWithNationAndLevel> {
|
||||
return service.getTanksFromHangar(uid).map { it.toTankWithNationAndLevel() }
|
||||
}
|
||||
|
||||
override suspend fun insertTank(tank: Tank, image: Bitmap) {
|
||||
service.insertTank(tank.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun insertMany(tankList: List<Tank>) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun updateTank(tank: Tank, image: Bitmap) {
|
||||
service.updateTank(tank.tankId!!, tank.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun deleteTank(tank: Tank) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun delete(tankId: Long) {
|
||||
service.deleteTank(tankId)
|
||||
dbTankRepository.delete(tankId)
|
||||
}
|
||||
|
||||
override suspend fun deleteAll() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package ru.ulstu.`is`.pmu.tank.api.repository
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.ulstu.`is`.pmu.tank.api.ServerService
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toLevel
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toRemote
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.toUser
|
||||
import ru.ulstu.`is`.pmu.tank.model.Level
|
||||
import ru.ulstu.`is`.pmu.tank.model.LevelWithTanks
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
import ru.ulstu.`is`.pmu.tank.model.User
|
||||
import ru.ulstu.`is`.pmu.tank.repository.LevelRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineLevelRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.OfflineUserRepository
|
||||
import ru.ulstu.`is`.pmu.tank.repository.UserRepository
|
||||
|
||||
class RestUserRepository(
|
||||
private val service: ServerService,
|
||||
private val dbUserRepository: OfflineUserRepository,
|
||||
) : UserRepository {
|
||||
override fun getAllUsers(): Flow<List<User>> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun getSimpleUser(email: String): User {
|
||||
return service.getUserByEmail(email).toUser()
|
||||
}
|
||||
|
||||
override fun getFullUser(uid: Long): Flow<Map<User, List<TankWithNationAndLevel>>> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun insertUser(user: User) {
|
||||
service.insertUser(user.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun updateUser(user: User) {
|
||||
service.updateUser(user.userId, user.toRemote())
|
||||
}
|
||||
|
||||
override suspend fun deleteUser(user: User) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
@ -73,13 +73,11 @@ fun TankList(
|
||||
viewModel: TankListViewModel = viewModel(factory = AppViewModelProvider.Factory),
|
||||
listNations: NationDropDownViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val tankListUiState by viewModel.tankListUiState.collectAsState()
|
||||
|
||||
// Lazy Column, Pass the numbers array
|
||||
if (navController != null) {
|
||||
TankList(
|
||||
nations = listNations.nationsListUiState,
|
||||
listTanks = tankListUiState.tankList
|
||||
listTanks = viewModel.tankListUiState.tankList
|
||||
) { uid: Long ->
|
||||
val route = Screen.Constructor.route.replace("{id}", uid.toString())
|
||||
navController.navigate(route)
|
||||
|
@ -33,8 +33,6 @@ class TankEditViewModel(
|
||||
viewModelScope.launch {
|
||||
if (tankUid > 0) {
|
||||
tankUiState = tankRepository.getTank(tankUid)
|
||||
.filterNotNull()
|
||||
.first()
|
||||
.toUiState(true)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.ulstu.`is`.pmu.tank.model.User
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserRole
|
||||
import ru.ulstu.`is`.pmu.tank.repository.UserRepository
|
||||
|
||||
class UserEditViewModel(
|
||||
@ -22,14 +23,12 @@ class UserEditViewModel(
|
||||
|
||||
//private val userUid: Long = checkNotNull(savedStateHandle["id"])
|
||||
|
||||
private val userUid: Long = 100L
|
||||
private val userEmail: String = "egor@mail.ru"
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
if (userUid > 0) {
|
||||
userUiState = userRepository.getSimpleUser(userUid)
|
||||
.filterNotNull()
|
||||
.first()
|
||||
if (userEmail.length > 0) {
|
||||
userUiState = userRepository.getSimpleUser(userEmail)
|
||||
.toUiState(true)
|
||||
}
|
||||
}
|
||||
@ -44,8 +43,8 @@ class UserEditViewModel(
|
||||
|
||||
suspend fun saveUser() {
|
||||
if (validateInput()) {
|
||||
if (userUid > 0) {
|
||||
userRepository.updateUser(userUiState.userDetails.toUser(userUid))
|
||||
if (userEmail.length > 0) {
|
||||
userRepository.updateUser(userUiState.userDetails.toUser(100L))
|
||||
} else {
|
||||
userRepository.insertUser(userUiState.userDetails.toUser())
|
||||
}
|
||||
@ -57,6 +56,7 @@ class UserEditViewModel(
|
||||
nickname.isNotBlank()
|
||||
&& email.isNotBlank()
|
||||
&& password.isNotBlank()
|
||||
&& role.value > -1
|
||||
&& balance > 0
|
||||
}
|
||||
}
|
||||
@ -71,6 +71,7 @@ data class UserDetails(
|
||||
val nickname: String = "",
|
||||
val email: String = "",
|
||||
val password: String = "",
|
||||
val role: UserRole = UserRole.USER,
|
||||
val balance: Int = 0,
|
||||
)
|
||||
|
||||
@ -79,6 +80,7 @@ fun UserDetails.toUser(uid: Long = 0): User = User(
|
||||
nickname = nickname,
|
||||
email = email,
|
||||
password = password,
|
||||
role = role,
|
||||
balance = balance
|
||||
)
|
||||
|
||||
@ -86,6 +88,7 @@ fun User.toDetails(): UserDetails = UserDetails(
|
||||
nickname = nickname,
|
||||
email = email,
|
||||
password = password,
|
||||
role = role,
|
||||
balance = balance
|
||||
)
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
package ru.ulstu.`is`.pmu.tank.composeui.list
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@ -15,21 +18,11 @@ class TankListViewModel(
|
||||
private val tankRepository: TankRepository,
|
||||
private var userId: Long = 100L
|
||||
) : ViewModel() {
|
||||
val tankListUiState: StateFlow<TankListUiState> = tankRepository.getForUserAll(userId).map {
|
||||
TankListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = TankListUiState()
|
||||
)
|
||||
var tankListUiState by mutableStateOf(TankListUiState())
|
||||
private set
|
||||
|
||||
val usersTanksUiState: StateFlow<UserTankListUiState> = tankRepository.getUserTanks(userId).map {
|
||||
UserTankListUiState(it)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
|
||||
initialValue = UserTankListUiState()
|
||||
)
|
||||
var usersTanksUiState by mutableStateOf(UserTankListUiState())
|
||||
private set
|
||||
|
||||
suspend fun deleteTank(tank: Tank) {
|
||||
tankRepository.deleteTank(tank)
|
||||
|
@ -30,14 +30,21 @@ interface LevelDao {
|
||||
@Query(
|
||||
"SELECT level FROM levels where levels.uid = :uid"
|
||||
)
|
||||
open fun getSimpleLevelUid(uid: Long): Flow<Level?>
|
||||
open fun getSimpleLevelUid(uid: Long): Level
|
||||
|
||||
@Insert
|
||||
suspend fun insert(level: Level)
|
||||
|
||||
@Insert
|
||||
suspend fun insertMany(level: List<Level>)
|
||||
|
||||
|
||||
@Update
|
||||
suspend fun update(level: Level)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(level: Level)
|
||||
|
||||
@Query("DELETE FROM levels")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -23,24 +23,33 @@ interface NationDao {
|
||||
suspend fun getNationsWithTanks(): List<NationWithTanks>
|
||||
|
||||
//получить конкретную нацию
|
||||
@Transaction
|
||||
@Query("select * from nations where nations.uid = :uid")
|
||||
fun getNationUid(uid: Long): Flow<NationWithTanks?>
|
||||
|
||||
//получить нацию без списка танков
|
||||
@Transaction
|
||||
@Query(
|
||||
"SELECT nationName FROM nations where nations.uid = :uid"
|
||||
)
|
||||
open fun getSimpleNationUid(uid: Long): Flow<Nation?>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM nations")
|
||||
fun pagingSource(): PagingSource<Int, Nation>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(nation: Nation)
|
||||
|
||||
@Insert
|
||||
suspend fun insertMany(nations: List<Nation>)
|
||||
|
||||
@Update
|
||||
suspend fun update(nation: Nation)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(nation: Nation)
|
||||
|
||||
@Query("DELETE FROM nations")
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package ru.ulstu.`is`.pmu.tank.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeyType
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeys
|
||||
|
||||
@Dao
|
||||
interface RemoteKeysDao {
|
||||
@Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type")
|
||||
suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(remoteKey: List<RemoteKeys>)
|
||||
|
||||
@Query("DELETE FROM remote_keys WHERE type = :type")
|
||||
suspend fun clearRemoteKeys(type: RemoteKeyType)
|
||||
}
|
@ -16,33 +16,36 @@ import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
@Dao
|
||||
interface TankDao {
|
||||
@Query("select * from tanks GROUP BY nationId, levelId ORDER BY nationId")
|
||||
fun getAll(): Flow<List<Tank>>
|
||||
fun getAll(): List<Tank>
|
||||
|
||||
//получить конкретный танк
|
||||
@Query("select t.*, ti.data from tanks AS t " +
|
||||
"LEFT JOIN tank_images as ti on t.image_id = ti.image_id " +
|
||||
"where t.tankId = :uid")
|
||||
fun getTankUid(uid: Long): Flow<Tank?>
|
||||
fun getTankUid(uid: Long): Tank
|
||||
|
||||
//получаем все танки пользователя по его Id
|
||||
@Query(
|
||||
"SELECT t.tankId, t.name, t.price, t.image_id, l.level, n.nationName, ti.data AS image FROM UserTankCrossRef AS ut " +
|
||||
"SELECT t.tankId, t.name, t.price, t.image_id, l.level, n.nationName, ti.data AS image FROM users_tanks AS ut " +
|
||||
"LEFT JOIN tanks as t on ut.tankId = t.tankId " +
|
||||
"LEFT JOIN tank_images as ti on t.image_id = ti.image_id " +
|
||||
"LEFT JOIN levels as l on t.levelId = l.uid " +
|
||||
"LEFT JOIN nations as n on t.nationId = n.uid " +
|
||||
"WHERE ut.userId = :uid GROUP BY t.nationId, t.levelId ORDER BY t.nationId"
|
||||
)
|
||||
fun getUserTanks(uid: Long): Flow<List<TankWithNationAndLevel>>
|
||||
fun getUserTanks(uid: Long): List<TankWithNationAndLevel>
|
||||
|
||||
@Query(
|
||||
"SELECT t.* FROM tanks AS t WHERE t.tankId NOT IN (SELECT ut.tankId FROM UserTankCrossRef AS ut WHERE ut.userId = :uid)"
|
||||
"SELECT t.* FROM tanks AS t WHERE t.tankId NOT IN (SELECT ut.tankId FROM users_tanks AS ut WHERE ut.userId = :uid)"
|
||||
)
|
||||
fun getNotUserTank(uid: Long): Flow<List<Tank>>
|
||||
fun getNotUserTank(uid: Long): List<Tank>
|
||||
|
||||
@Insert
|
||||
suspend fun insert(tank: Tank)
|
||||
|
||||
@Insert
|
||||
suspend fun insertMany(tankList: List<Tank>)
|
||||
|
||||
@Update
|
||||
suspend fun update(tank: Tank)
|
||||
|
||||
@ -51,4 +54,7 @@ interface TankDao {
|
||||
|
||||
@Query("DELETE FROM tanks WHERE tankId = :id")
|
||||
suspend fun delete(id: Long)
|
||||
|
||||
@Query("DELETE FROM tanks")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -11,7 +11,6 @@ import ru.ulstu.`is`.pmu.tank.model.Tank
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
import ru.ulstu.`is`.pmu.tank.model.User
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserTankCrossRef
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserWithTanks
|
||||
|
||||
@Dao
|
||||
interface UserDao {
|
||||
@ -21,7 +20,7 @@ interface UserDao {
|
||||
//получить конкретного пользователя
|
||||
@Query(
|
||||
"SELECT u.*, t.*, l.level, n.nationName, ti.data AS image FROM users AS u " +
|
||||
"LEFT JOIN UserTankCrossRef as ut on u.userId = ut.userId " +
|
||||
"LEFT JOIN users_tanks as ut on u.userId = ut.userId " +
|
||||
"LEFT JOIN tanks as t on ut.tankId = t.tankId " +
|
||||
"LEFT JOIN tank_images as ti on ut.tankId = ti.image_id " +
|
||||
"LEFT JOIN levels as l on t.levelId = l.uid " +
|
||||
@ -30,8 +29,8 @@ interface UserDao {
|
||||
)
|
||||
fun getUserUid(uid: Long): Flow<Map<User, List<TankWithNationAndLevel>>>
|
||||
|
||||
@Query("select * from users where users.userId = :uid")
|
||||
fun getSimpleUserUid(uid: Long): Flow<User?>
|
||||
@Query("select * from users where users.email = :email")
|
||||
fun getSimpleUserUid(email: String): User
|
||||
|
||||
//добавить танк в ангар пользователя
|
||||
@Insert
|
||||
|
@ -20,8 +20,8 @@ import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
import ru.ulstu.`is`.pmu.tank.model.Tank
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankImage
|
||||
import ru.ulstu.`is`.pmu.tank.model.User
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserRole
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserTankCrossRef
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserWithTanks
|
||||
|
||||
//тут, собственно говоря, всё и мутится с БД :)))
|
||||
@Database(entities = [Nation::class, Level::class, Tank::class, User::class, UserTankCrossRef::class, TankImage::class], version = 1, exportSchema = false)
|
||||
@ -34,7 +34,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun tankImageDao() : TankImageDao
|
||||
|
||||
companion object {
|
||||
private const val DB_NAME: String = "19-db"
|
||||
private const val DB_NAME: String = "20-db"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: AppDatabase? = null
|
||||
@ -129,7 +129,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
//Users
|
||||
val userDao = database.userDao()
|
||||
val user = User(100L,"3tankista73", "egor@mail.ru", "12032003", 10000000)
|
||||
val user = User(100L,"3tankista73", "egor@mail.ru", "12032003", UserRole.ADMIN, 10000000)
|
||||
|
||||
userDao.insert(user)
|
||||
|
||||
@ -148,14 +148,14 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
AppDatabase::class.java,
|
||||
DB_NAME
|
||||
)
|
||||
.addCallback(object : Callback() {
|
||||
override fun onCreate(db: SupportSQLiteDatabase) {
|
||||
super.onCreate(db)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
populateDatabase(appContext)
|
||||
}
|
||||
}
|
||||
})
|
||||
// .addCallback(object : Callback() {
|
||||
// override fun onCreate(db: SupportSQLiteDatabase) {
|
||||
// super.onCreate(db)
|
||||
// CoroutineScope(Dispatchers.IO).launch {
|
||||
// populateDatabase(appContext)
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
.build()
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
package ru.ulstu.`is`.pmu.tank.model
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverter
|
||||
import androidx.room.TypeConverters
|
||||
|
||||
enum class RemoteKeyType(private val type: String) {
|
||||
NATION(Nation::class.simpleName ?: "Nation");
|
||||
|
||||
@TypeConverter
|
||||
fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value }
|
||||
|
||||
@TypeConverter
|
||||
fun fromRemoteKeyType(value: RemoteKeyType) = value.type
|
||||
}
|
||||
|
||||
@Entity(tableName = "remote_keys")
|
||||
data class RemoteKeys(
|
||||
@PrimaryKey val entityId: Int,
|
||||
@TypeConverters(RemoteKeyType::class)
|
||||
val type: RemoteKeyType,
|
||||
val prevKey: Int?,
|
||||
val nextKey: Int?
|
||||
)
|
@ -17,6 +17,8 @@ data class User (
|
||||
val email: String,
|
||||
@ColumnInfo(name = "password")
|
||||
val password: String,
|
||||
@ColumnInfo(name = "role")
|
||||
val role: UserRole,
|
||||
@ColumnInfo(name = "balance")
|
||||
val balance: Int
|
||||
){
|
||||
@ -25,8 +27,9 @@ data class User (
|
||||
nickname: String,
|
||||
email: String,
|
||||
password: String,
|
||||
role: UserRole,
|
||||
balance: Int
|
||||
) : this(0L, nickname, email, password, balance)
|
||||
) : this(0L, nickname, email, password, UserRole.ADMIN, balance)
|
||||
|
||||
companion object {
|
||||
fun getUser(index: Long = 0L): User {
|
||||
@ -35,6 +38,7 @@ data class User (
|
||||
"3tankista73",
|
||||
"egor@mail.ru",
|
||||
"1234567890!",
|
||||
UserRole.USER,
|
||||
10000000
|
||||
)
|
||||
}
|
||||
@ -50,6 +54,7 @@ data class User (
|
||||
if (nickname != other.nickname) return false
|
||||
if (email != other.email) return false
|
||||
if (password != other.password) return false
|
||||
if (role != other.role) return false
|
||||
if (balance != other.balance) return false
|
||||
|
||||
return true
|
||||
@ -60,6 +65,7 @@ data class User (
|
||||
result = 31 * result + nickname.hashCode()
|
||||
result = 31 * result + email.hashCode()
|
||||
result = 31 * result + password.hashCode()
|
||||
result = 31 * result + role.hashCode()
|
||||
result = 31 * result + balance
|
||||
return result
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
package ru.ulstu.`is`.pmu.tank.model
|
||||
|
||||
enum class UserRole(val value: Int) {
|
||||
USER(0),
|
||||
ADMIN(1)
|
||||
}
|
@ -8,7 +8,10 @@ import androidx.room.PrimaryKey
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
//many to many for user and tank
|
||||
@Entity(primaryKeys = ["userId", "tankId"])
|
||||
@Entity(
|
||||
tableName = "users_tanks",
|
||||
primaryKeys = ["userId", "tankId"]
|
||||
)
|
||||
data class UserTankCrossRef(
|
||||
val userId: Long,
|
||||
val tankId: Long
|
||||
|
@ -6,9 +6,11 @@ import ru.ulstu.`is`.pmu.tank.model.LevelWithTanks
|
||||
|
||||
interface LevelRepository {
|
||||
suspend fun getAllLevels(): List<Level>
|
||||
fun getSimpleLevel(uid: Long): Flow<Level?>
|
||||
suspend fun getSimpleLevel(uid: Long): Level
|
||||
fun getFullLevel(uid: Long): Flow<LevelWithTanks?>
|
||||
suspend fun insertLevel(level: Level)
|
||||
suspend fun insertMany(levels: List<Level>)
|
||||
suspend fun updateLevel(level: Level)
|
||||
suspend fun deleteLevel(level: Level)
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
|
@ -1,16 +1,21 @@
|
||||
package ru.ulstu.`is`.pmu.tank.repository
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.ulstu.`is`.pmu.tank.api.model.NationRemote
|
||||
import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
import ru.ulstu.`is`.pmu.tank.model.NationWithTanks
|
||||
|
||||
interface NationRepository {
|
||||
suspend fun getAllNations(): List<Nation>
|
||||
suspend fun getAll(): Flow<PagingData<Nation>>
|
||||
fun getSimpleNation(uid: Long): Flow<Nation?>
|
||||
fun getFullNation(uid: Long): Flow<NationWithTanks?>
|
||||
fun pagingSource(): PagingSource<Int, Nation>
|
||||
suspend fun insertNation(nation: Nation)
|
||||
suspend fun insertNations(nations: List<Nation>)
|
||||
suspend fun updateNation(nation: Nation)
|
||||
suspend fun deleteNation(nation: Nation)
|
||||
suspend fun deleteNations()
|
||||
}
|
@ -8,13 +8,16 @@ import ru.ulstu.`is`.pmu.tank.model.LevelWithTanks
|
||||
class OfflineLevelRepository(private val levelDao: LevelDao) : LevelRepository {
|
||||
override suspend fun getAllLevels(): List<Level> = levelDao.getAll()
|
||||
|
||||
override fun getSimpleLevel(uid: Long): Flow<Level?> = levelDao.getSimpleLevelUid(uid)
|
||||
override suspend fun getSimpleLevel(uid: Long): Level = levelDao.getSimpleLevelUid(uid)
|
||||
|
||||
override fun getFullLevel(uid: Long): Flow<LevelWithTanks?> = levelDao.getLevelUid(uid)
|
||||
|
||||
override suspend fun insertLevel(level: Level) = levelDao.insert(level)
|
||||
override suspend fun insertMany(levels: List<Level>) = levelDao.insertMany(levels)
|
||||
|
||||
override suspend fun updateLevel(level: Level) = levelDao.update(level)
|
||||
|
||||
override suspend fun deleteLevel(level: Level) = levelDao.delete(level)
|
||||
|
||||
override suspend fun deleteAll() = levelDao.deleteAll()
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package ru.ulstu.`is`.pmu.tank.repository
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import ru.ulstu.`is`.pmu.tank.dao.NationDao
|
||||
@ -8,16 +9,25 @@ import ru.ulstu.`is`.pmu.tank.model.NationWithTanks
|
||||
|
||||
class OfflineNationRepository(private val nationDao: NationDao) : NationRepository {
|
||||
override suspend fun getAllNations(): List<Nation> = nationDao.getAll()
|
||||
override suspend fun getAll(): Flow<PagingData<Nation>> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getSimpleNation(uid: Long): Flow<Nation?> = nationDao.getSimpleNationUid(uid)
|
||||
|
||||
override fun getFullNation(uid: Long): Flow<NationWithTanks?> = nationDao.getNationUid(uid)
|
||||
|
||||
override fun pagingSource(): PagingSource<Int, Nation> = nationDao.pagingSource()
|
||||
override fun pagingSource(): PagingSource<Int, Nation> {
|
||||
return nationDao.pagingSource()
|
||||
}
|
||||
|
||||
override suspend fun insertNation(nation: Nation) = nationDao.insert(nation)
|
||||
|
||||
override suspend fun updateNation(nation: Nation) = nationDao.update(nation)
|
||||
|
||||
override suspend fun deleteNation(nation: Nation) = nationDao.delete(nation)
|
||||
|
||||
override suspend fun insertNations(nations: List<Nation>) = nationDao.insertMany(nations)
|
||||
|
||||
override suspend fun deleteNations() = nationDao.deleteAll()
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package ru.ulstu.`is`.pmu.tank.repository
|
||||
|
||||
import ru.ulstu.`is`.pmu.tank.dao.RemoteKeysDao
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeyType
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeys
|
||||
|
||||
class OfflineRemoteKeyRepository(private val remoteKeysDao: RemoteKeysDao) : RemoteKeyRepository {
|
||||
override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
|
||||
remoteKeysDao.getRemoteKeys(id, type)
|
||||
|
||||
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
|
||||
remoteKeysDao.insertAll(remoteKeys)
|
||||
|
||||
override suspend fun deleteRemoteKey(type: RemoteKeyType) =
|
||||
remoteKeysDao.clearRemoteKeys(type)
|
||||
}
|
@ -13,13 +13,13 @@ class OfflineTankRepository(
|
||||
private val tankDao: TankDao,
|
||||
private val tankImageDao: TankImageDao
|
||||
) : TankRepository {
|
||||
override fun getAll(): Flow<List<Tank>> = tankDao.getAll()
|
||||
override suspend fun getAll(): List<Tank> = tankDao.getAll()
|
||||
|
||||
override fun getForUserAll(userId: Long): Flow<List<Tank>> = tankDao.getNotUserTank(userId)
|
||||
override suspend fun getForUserAll(userId: Long): List<Tank> = tankDao.getNotUserTank(userId)
|
||||
|
||||
override fun getTank(uid: Long): Flow<Tank?> = tankDao.getTankUid(uid)
|
||||
override suspend fun getTank(uid: Long): Tank = tankDao.getTankUid(uid)
|
||||
|
||||
override fun getUserTanks(uid: Long): Flow<List<TankWithNationAndLevel>> = tankDao.getUserTanks(uid)
|
||||
override suspend fun getUserTanks(uid: Long): List<TankWithNationAndLevel> = tankDao.getUserTanks(uid)
|
||||
|
||||
override suspend fun insertTank(tank: Tank, image: Bitmap) {
|
||||
val imageId = tankImageDao.insert(
|
||||
@ -32,6 +32,10 @@ class OfflineTankRepository(
|
||||
tankDao.insert(tank.copy(imageId = imageId))
|
||||
}
|
||||
|
||||
override suspend fun insertMany(tankList: List<Tank>) {
|
||||
tankDao.insertMany(tankList)
|
||||
}
|
||||
|
||||
override suspend fun updateTank(tank: Tank, image: Bitmap) {
|
||||
val imageId = tankImageDao.insert(
|
||||
TankImage(
|
||||
@ -49,4 +53,8 @@ class OfflineTankRepository(
|
||||
override suspend fun delete(tankId: Long) {
|
||||
tankDao.delete(tankId)
|
||||
}
|
||||
|
||||
override suspend fun deleteAll() {
|
||||
tankDao.deleteAll()
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import ru.ulstu.`is`.pmu.tank.model.User
|
||||
class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
|
||||
override fun getAllUsers(): Flow<List<User>> = userDao.getAll()
|
||||
|
||||
override fun getSimpleUser(uid: Long): Flow<User?> = userDao.getSimpleUserUid(uid)
|
||||
override suspend fun getSimpleUser(email: String): User = userDao.getSimpleUserUid(email)
|
||||
|
||||
override fun getFullUser(uid: Long): Flow<Map<User, List<TankWithNationAndLevel>>> = userDao.getUserUid(uid)
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
package ru.ulstu.`is`.pmu.tank.repository
|
||||
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeyType
|
||||
import ru.ulstu.`is`.pmu.tank.model.RemoteKeys
|
||||
|
||||
interface RemoteKeyRepository {
|
||||
suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys?
|
||||
suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>)
|
||||
suspend fun deleteRemoteKey(type: RemoteKeyType)
|
||||
}
|
@ -7,12 +7,14 @@ import ru.ulstu.`is`.pmu.tank.model.TankExtra
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
|
||||
interface TankRepository {
|
||||
fun getAll(): Flow<List<Tank>>
|
||||
fun getForUserAll(userId: Long): Flow<List<Tank>>
|
||||
fun getTank(uid: Long): Flow<Tank?>
|
||||
fun getUserTanks(uid: Long): Flow<List<TankWithNationAndLevel>>
|
||||
suspend fun getAll(): List<Tank>
|
||||
suspend fun getForUserAll(userId: Long): List<Tank>
|
||||
suspend fun getTank(uid: Long): Tank
|
||||
suspend fun getUserTanks(uid: Long): List<TankWithNationAndLevel>
|
||||
suspend fun insertTank(tank: Tank, image: Bitmap)
|
||||
suspend fun insertMany(tankList: List<Tank>)
|
||||
suspend fun updateTank(tank: Tank, image: Bitmap)
|
||||
suspend fun deleteTank(tank: Tank)
|
||||
suspend fun delete(tankId: Long)
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -6,7 +6,7 @@ import ru.ulstu.`is`.pmu.tank.model.User
|
||||
|
||||
interface UserRepository {
|
||||
fun getAllUsers(): Flow<List<User>>
|
||||
fun getSimpleUser(uid: Long): Flow<User?>
|
||||
suspend fun getSimpleUser(email: String): User
|
||||
fun getFullUser(uid: Long): Flow<Map<User, List<TankWithNationAndLevel>>>
|
||||
suspend fun insertUser(user: User)
|
||||
suspend fun updateUser(user: User)
|
||||
|
@ -1,14 +1,11 @@
|
||||
package ru.ulstu.`is`.pmu.tanks.composeui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@ -20,20 +17,12 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
@ -41,23 +30,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.ulstu.`is`.pmu.R
|
||||
import ru.ulstu.`is`.pmu.composeui.navigation.Screen
|
||||
import ru.ulstu.`is`.pmu.tank.composeui.list.TankListViewModel
|
||||
import ru.ulstu.`is`.pmu.tank.database.AppDatabase
|
||||
import ru.ulstu.`is`.pmu.tank.model.Level
|
||||
import ru.ulstu.`is`.pmu.tank.model.Nation
|
||||
import ru.ulstu.`is`.pmu.tank.model.Tank
|
||||
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
|
||||
import ru.ulstu.`is`.pmu.tank.model.UserWithTanks
|
||||
import ru.ulstu.`is`.pmu.tanks.composeui.image.CuteImage
|
||||
import ru.ulstu.`is`.pmu.tanks.composeui.image.Dimensions
|
||||
import ru.ulstu.`is`.pmu.tanks.composeui.image.RoundedCorderImage
|
||||
import ru.ulstu.`is`.pmu.ui.AppViewModelProvider
|
||||
@ -71,10 +45,9 @@ fun Hangar(
|
||||
viewModel: TankListViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
){
|
||||
viewModel.setUserId(100L)
|
||||
val userTankListUiState by viewModel.usersTanksUiState.collectAsState()
|
||||
|
||||
//новый вызов основного списка
|
||||
Hangar(tankList = userTankListUiState.userTankList )
|
||||
Hangar(tankList = viewModel.usersTanksUiState.userTankList )
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.application.ui
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.util.Base64
|
||||
import java.io.ByteArrayOutputStream
|
||||
import kotlin.math.sqrt
|
||||
|
||||
const val miniatureBound: Int = 250
|
||||
@ -24,3 +27,21 @@ fun Bitmap.resize(bound: Int): Bitmap {
|
||||
val newHeight: Int = (height / factor).toInt()
|
||||
return Bitmap.createScaledBitmap(this, newWidth, newHeight, false)
|
||||
}
|
||||
|
||||
fun Bitmap.toByteArray(): ByteArray {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
this.compress(Bitmap.CompressFormat.PNG, 1, outputStream)
|
||||
return outputStream.toByteArray()
|
||||
}
|
||||
|
||||
fun Bitmap.toBase64(): String {
|
||||
return Base64.encodeToString(this.toByteArray(), Base64.DEFAULT)
|
||||
}
|
||||
|
||||
fun ByteArray.toBitmap(): Bitmap {
|
||||
return BitmapFactory.decodeByteArray(this, 0, this.size)
|
||||
}
|
||||
|
||||
fun String.toBitmap(): Bitmap {
|
||||
return Base64.decode(this, Base64.DEFAULT).toBitmap()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user