diff --git a/compose/.gradle/8.0/executionHistory/executionHistory.bin b/compose/.gradle/8.0/executionHistory/executionHistory.bin
index 91fe15c..67eba2a 100644
Binary files a/compose/.gradle/8.0/executionHistory/executionHistory.bin and b/compose/.gradle/8.0/executionHistory/executionHistory.bin differ
diff --git a/compose/.gradle/8.0/executionHistory/executionHistory.lock b/compose/.gradle/8.0/executionHistory/executionHistory.lock
index e0b3315..50757f9 100644
Binary files a/compose/.gradle/8.0/executionHistory/executionHistory.lock and b/compose/.gradle/8.0/executionHistory/executionHistory.lock differ
diff --git a/compose/.gradle/8.0/fileHashes/fileHashes.bin b/compose/.gradle/8.0/fileHashes/fileHashes.bin
index 206b3cc..f3e92c1 100644
Binary files a/compose/.gradle/8.0/fileHashes/fileHashes.bin and b/compose/.gradle/8.0/fileHashes/fileHashes.bin differ
diff --git a/compose/.gradle/8.0/fileHashes/fileHashes.lock b/compose/.gradle/8.0/fileHashes/fileHashes.lock
index 01a6d6a..b33bc8d 100644
Binary files a/compose/.gradle/8.0/fileHashes/fileHashes.lock and b/compose/.gradle/8.0/fileHashes/fileHashes.lock differ
diff --git a/compose/.gradle/8.0/fileHashes/resourceHashesCache.bin b/compose/.gradle/8.0/fileHashes/resourceHashesCache.bin
index 5c6347e..09e3077 100644
Binary files a/compose/.gradle/8.0/fileHashes/resourceHashesCache.bin and b/compose/.gradle/8.0/fileHashes/resourceHashesCache.bin differ
diff --git a/compose/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/compose/.gradle/buildOutputCleanup/buildOutputCleanup.lock
index cc1cf6f..9d44cfa 100644
Binary files a/compose/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/compose/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ
diff --git a/compose/.gradle/buildOutputCleanup/outputFiles.bin b/compose/.gradle/buildOutputCleanup/outputFiles.bin
index 967e65c..2eadbbb 100644
Binary files a/compose/.gradle/buildOutputCleanup/outputFiles.bin and b/compose/.gradle/buildOutputCleanup/outputFiles.bin differ
diff --git a/compose/.gradle/file-system.probe b/compose/.gradle/file-system.probe
index 14f5211..8323b79 100644
Binary files a/compose/.gradle/file-system.probe and b/compose/.gradle/file-system.probe differ
diff --git a/compose/.idea/modules/app/pmu-demo.app.iml b/compose/.idea/modules/app/pmu-demo.app.iml
deleted file mode 100644
index 349119f..0000000
--- a/compose/.idea/modules/app/pmu-demo.app.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/ApiRoutes.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/ApiRoutes.kt
new file mode 100644
index 0000000..7594d0b
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/ApiRoutes.kt
@@ -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"
+}
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/ServerService.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/ServerService.kt
new file mode 100644
index 0000000..6fa34cd
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/ServerService.kt
@@ -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
+
+ @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
+
+ @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
+
+ @GET("${ApiRoutes.TANK}/{id}")
+ suspend fun getTank(
+ @Path("id") id: Long
+ ): TankRemote
+
+ @GET("${ApiRoutes.TANK}/forPurchase")
+ suspend fun getTanksForPurchase(
+ @Path("id") userId: Long
+ ): List
+
+ @GET("${ApiRoutes.TANK}/myHangar")
+ suspend fun getTanksFromHangar(
+ @Path("id") userId: Long
+ ): List
+
+ @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
+
+ @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 }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/NationRemoteMediator.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/NationRemoteMediator.kt
new file mode 100644
index 0000000..2191b48
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/NationRemoteMediator.kt
@@ -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() {
+
+ override suspend fun initialize(): InitializeAction {
+ return InitializeAction.LAUNCH_INITIAL_REFRESH
+ }
+
+ override suspend fun load(
+ loadType: LoadType,
+ state: PagingState
+ ): 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): 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): 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
+ ): RemoteKeys? {
+ return state.anchorPosition?.let { position ->
+ state.closestItemToPosition(position)?.uid?.let { nationUid ->
+ dbRemoteKeyRepository.getAllRemoteKeys(nationUid.toInt(), RemoteKeyType.NATION)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/LevelRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/LevelRemote.kt
new file mode 100644
index 0000000..c5cd2c3
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/LevelRemote.kt
@@ -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
+)
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/NationRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/NationRemote.kt
new file mode 100644
index 0000000..7bc7271
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/NationRemote.kt
@@ -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
+)
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/TankRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/TankRemote.kt
new file mode 100644
index 0000000..992c151
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/TankRemote.kt
@@ -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!!
+)
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/TankWithNationAndLevelRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/TankWithNationAndLevelRemote.kt
new file mode 100644
index 0000000..5f6fd73
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/TankWithNationAndLevelRemote.kt
@@ -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
+)
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserRemote.kt
new file mode 100644
index 0000000..9e8feb6
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserRemote.kt
@@ -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()[role],
+ balance = balance
+)
+
+fun User.toRemote(): UserRemote = UserRemote(
+ id = userId,
+ nickname = nickname,
+ email = email,
+ password = password,
+ role = role.ordinal,
+ balance = balance
+)
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt
new file mode 100644
index 0000000..10ee79a
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt
@@ -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
+)
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestLevelRepository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestLevelRepository.kt
new file mode 100644
index 0000000..af69586
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestLevelRepository.kt
@@ -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 {
+ 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 {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun insertLevel(level: Level) {
+ service.insertLevel(level.toRemote())
+ }
+
+ override suspend fun insertMany(levels: List) {
+ 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")
+ }
+}
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestNationRepository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestNationRepository.kt
new file mode 100644
index 0000000..5b0f4ee
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestNationRepository.kt
@@ -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 {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun getAll(): Flow> {
+ @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 {
+ TODO("Not yet implemented")
+ }
+
+ override fun getFullNation(uid: Long): Flow {
+ TODO("Not yet implemented")
+ }
+
+ override fun pagingSource(): PagingSource {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun insertNation(nation: Nation) {
+ service.insertNation(nation.toRemote()).toNation()
+ }
+
+ override suspend fun insertNations(nations: List) {
+ 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")
+ }
+}
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankReppository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankReppository.kt
new file mode 100644
index 0000000..3f7b5ec
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankReppository.kt
@@ -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 {
+ dbTankRepository.deleteAll()
+ val tanks = service.getTanks().map { it.toTank() }
+ dbTankRepository.insertMany(tanks)
+ return tanks
+ }
+
+ override suspend fun getForUserAll(userId: Long): List {
+ 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 {
+ 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) {
+ 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")
+ }
+}
\ No newline at end of file
diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestUserRepository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestUserRepository.kt
new file mode 100644
index 0000000..12f376e
--- /dev/null
+++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestUserRepository.kt
@@ -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> {
+ TODO("Not yet implemented")
+ }
+
+ override suspend fun getSimpleUser(email: String): User {
+ return service.getUserByEmail(email).toUser()
+ }
+
+ override fun getFullUser(uid: Long): Flow