Complete lab 5

This commit is contained in:
andrew 2023-12-20 11:21:54 +04:00
parent 9dcc14add5
commit 702cf2d259
43 changed files with 670 additions and 265 deletions

View File

@ -8,7 +8,7 @@ import androidx.activity.viewModels
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.testapp.designElem.SharedViewModel import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.graphs.RootNavigationGraph import com.example.testapp.graphs.RootNavigationGraph
import com.example.testapp.ui.theme.TestAppTheme import com.example.testapp.ui.theme.TestAppTheme
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider

View File

@ -63,7 +63,7 @@ interface DealRequests {
@DELETE("deals/{id}") @DELETE("deals/{id}")
suspend fun deleteDeal(@Path("id") id: Int): DealRemote suspend fun deleteDeal(@Path("id") id: Int): DealRemote
@GET("p_deals") @GET("deals")
suspend fun pagingDeals( suspend fun pagingDeals(
@Query("_page") page: Int, @Query("_page") page: Int,
@Query("_limit") limit: Int @Query("_limit") limit: Int
@ -81,7 +81,7 @@ interface CoinRequests {
/** /**
* <i>Coin Request interface</i> * <i>Coin Request interface</i>
*/ */
@GET("") @GET("coins")
suspend fun getCoins(): List<CoinRemote> suspend fun getCoins(): List<CoinRemote>
} }
@ -95,13 +95,13 @@ interface WalletItemRequests {
@POST("wal_item") @POST("wal_item")
suspend fun insert(@Body obj: WalletItemRemote): WalletItemRemote suspend fun insert(@Body obj: WalletItemRemote): WalletItemRemote
@PUT("wal_item") @PUT("wal_item/{id}")
suspend fun update(@Body obj: WalletItemRemote): WalletItemRemote suspend fun update(@Path("id") id: Int, @Body obj: WalletItemRemote): WalletItemRemote
@DELETE("wal_item/{id}") @DELETE("wal_item/{id}")
suspend fun deleteWalletItem(@Path("id") id: Int): WalletItemRemote suspend fun deleteWalletItem(@Path("id") id: Int): WalletItemRemote
@GET("p_wal_item") @GET("wal_item")
suspend fun pagingWalletItems( suspend fun pagingWalletItems(
@Query("_page") page: Int, @Query("_page") page: Int,
@Query("_limit") limit: Int @Query("_limit") limit: Int
@ -110,7 +110,7 @@ interface WalletItemRequests {
interface CryptoDealService : UserRequests, DealRequests, CoinRequests, WalletItemRequests { interface CryptoDealService : UserRequests, DealRequests, CoinRequests, WalletItemRequests {
companion object { companion object {
private const val BASE_URL = "http://10.0.2.2:8079/" private const val BASE_URL = "http://172.20.10.13:8079/"
@Volatile @Volatile
private var INSTANCE: CryptoDealService? = null private var INSTANCE: CryptoDealService? = null

View File

@ -49,8 +49,8 @@ class DealRemoteMediator(
} }
try { try {
val articles = service.pagingDeals(page, state.config.pageSize).map { it.toDeal() } val deals = service.pagingDeals(page, state.config.pageSize).map { it.toDeal() }
val endOfPaginationReached = articles.isEmpty() val endOfPaginationReached = deals.isEmpty()
database.withTransaction { database.withTransaction {
if (loadType == LoadType.REFRESH) { if (loadType == LoadType.REFRESH) {
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.DEAL) dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.DEAL)
@ -58,18 +58,16 @@ class DealRemoteMediator(
} }
val prevKey = if (page == 1) null else page - 1 val prevKey = if (page == 1) null else page - 1
val nextKey = if (endOfPaginationReached) null else page + 1 val nextKey = if (endOfPaginationReached) null else page + 1
val keys = articles.map { val keys = deals.map {
it.id?.let { it1 ->
RemoteKeys( RemoteKeys(
entityId = it1, entityId = it.id!!,
type = RemoteKeyType.DEAL, type = RemoteKeyType.DEAL,
prevKey = prevKey, prevKey = prevKey,
nextKey = nextKey nextKey = nextKey
) )
} }
}
dbRemoteKeyRepository.createRemoteKeys(keys) dbRemoteKeyRepository.createRemoteKeys(keys)
dbDealRepository.insert(articles) dbDealRepository.insert(deals)
} }
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached) return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (exception: IOException) { } catch (exception: IOException) {

View File

@ -59,15 +59,13 @@ class WalletItemRemoteMediator(
val prevKey = if (page == 1) null else page - 1 val prevKey = if (page == 1) null else page - 1
val nextKey = if (endOfPaginationReached) null else page + 1 val nextKey = if (endOfPaginationReached) null else page + 1
val keys = articles.map { val keys = articles.map {
it.id?.let { it1 ->
RemoteKeys( RemoteKeys(
entityId = it1, entityId = it.id!!,
type = RemoteKeyType.WALLETITEM, type = RemoteKeyType.WALLETITEM,
prevKey = prevKey, prevKey = prevKey,
nextKey = nextKey nextKey = nextKey
) )
} }
}
dbRemoteKeyRepository.createRemoteKeys(keys) dbRemoteKeyRepository.createRemoteKeys(keys)
dbWalletItemRepository.insert(articles) dbWalletItemRepository.insert(articles)
} }
@ -81,15 +79,15 @@ class WalletItemRemoteMediator(
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, WalletItem>): RemoteKeys? { private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, WalletItem>): RemoteKeys? {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull() return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { art -> ?.let { item ->
art.id?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.WALLETITEM) } item.id!!.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.WALLETITEM) }
} }
} }
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, WalletItem>): RemoteKeys? { private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, WalletItem>): RemoteKeys? {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull() return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { art -> ?.let { item ->
art.id?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.WALLETITEM) } item.id!!.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.WALLETITEM) }
} }
} }
@ -97,8 +95,8 @@ class WalletItemRemoteMediator(
state: PagingState<Int, WalletItem> state: PagingState<Int, WalletItem>
): RemoteKeys? { ): RemoteKeys? {
return state.anchorPosition?.let { position -> return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.id?.let { artid -> state.closestItemToPosition(position)?.id?.let { itemId ->
dbRemoteKeyRepository.getAllRemoteKeys(artid, RemoteKeyType.WALLETITEM) dbRemoteKeyRepository.getAllRemoteKeys(itemId, RemoteKeyType.WALLETITEM)
} }
} }
} }

View File

@ -5,11 +5,11 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
data class WalletItemRemote( data class WalletItemRemote(
val id: Int?, val id: Int,
val coinId: Int, val coinId: Int,
val userId: Int, val userId: Int,
var count: Float, var count: Float,
) )
fun WalletItemRemote.toWalletItem(): WalletItem = WalletItem(id, coinId, userId, count) fun WalletItemRemote.toWalletItem(): WalletItem = WalletItem(id, coinId, userId, count)
fun WalletItem.toRemote(): WalletItemRemote = WalletItemRemote(id, coinId, userId, count) fun WalletItem.toRemote(): WalletItemRemote = WalletItemRemote(id!!, coinId, userId, count)

View File

@ -10,7 +10,7 @@ class CoinRestRepository(
private val service: CryptoDealService, private val service: CryptoDealService,
private val dbCoinRepository: OfflineCoinRepository private val dbCoinRepository: OfflineCoinRepository
) : CoinRepository { ) : CoinRepository {
override suspend fun insert(x: Coin) { override suspend fun insert(vararg x: Coin) {
TODO("Not yet implemented") TODO("Not yet implemented")
} }

View File

@ -46,6 +46,10 @@ class DealRestRepository(
return service.completeDeal(deal.id!!, sellerId, buyerId) return service.completeDeal(deal.id!!, sellerId, buyerId)
} }
override suspend fun clearData() {
TODO("Not yet implemented")
}
override fun pagingData(): Flow<PagingData<Deal>> { override fun pagingData(): Flow<PagingData<Deal>> {
val pagingSourceFactory = { dbDealRepository.getAllPagingData() } val pagingSourceFactory = { dbDealRepository.getAllPagingData() }
@ -69,8 +73,8 @@ class DealRestRepository(
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override suspend fun insert(x: Deal) { override suspend fun insert(vararg x: Deal) {
service.insert(x.toRemote()) x.forEach {y -> service.insert(y.toRemote()) }
} }
override suspend fun update(x: Deal) { override suspend fun update(x: Deal) {

View File

@ -61,8 +61,10 @@ class UserRestRepository(
return existArticles.map { it.value }.sortedBy { it.id } return existArticles.map { it.value }.sortedBy { it.id }
} }
override suspend fun insert(x: User) { override suspend fun insert(vararg x: User) {
service.insert(x.toRemote()) x.forEach { user ->
service.insert(user.toRemote())
}
} }
override suspend fun update(x: User) { override suspend fun update(x: User) {

View File

@ -24,7 +24,7 @@ class WalletItemRestRepository(
private val database: CryptoDealDb private val database: CryptoDealDb
) : WalletItemRepository { ) : WalletItemRepository {
override fun getUserWallet(id: Int): List<WalletItem> { override fun getUserWallet(id: Int): List<WalletItem> {
TODO("Not yet implemented") return dbWalletItemRepository.getUserWallet(id)
} }
override fun pagingData(id: Int): Flow<PagingData<WalletItem>> { override fun pagingData(id: Int): Flow<PagingData<WalletItem>> {
@ -50,16 +50,20 @@ class WalletItemRestRepository(
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override suspend fun insert(x: WalletItem) { override suspend fun clearData() {
service.insert(x.toRemote()) TODO("Not yet implemented")
}
override suspend fun insert(vararg x: WalletItem) {
x.forEach {y -> service.insert(y.toRemote()) }
} }
override suspend fun update(x: WalletItem) { override suspend fun update(x: WalletItem) {
service.update(x.toRemote()) service.update(x.id!!, x.toRemote())
} }
override suspend fun delete(x: WalletItem) { override suspend fun delete(x: WalletItem) {
x.id?.let { service.deleteWalletItem(it) } x.id.let { service.deleteWalletItem(it!!) }
} }
override suspend fun getById(id: Int): WalletItem { override suspend fun getById(id: Int): WalletItem {

View File

@ -1,6 +1,11 @@
package com.example.testapp.data.room package com.example.testapp.data.room
import android.content.Context import android.content.Context
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.repository.CoinRestRepository
import com.example.testapp.data.api.repository.DealRestRepository
import com.example.testapp.data.api.repository.UserRestRepository
import com.example.testapp.data.api.repository.WalletItemRestRepository
import com.example.testapp.data.room.database.CryptoDealDb import com.example.testapp.data.room.database.CryptoDealDb
import com.example.testapp.data.room.repository.basic.CoinRepository import com.example.testapp.data.room.repository.basic.CoinRepository
import com.example.testapp.data.room.repository.basic.DealRepository import com.example.testapp.data.room.repository.basic.DealRepository
@ -8,6 +13,7 @@ import com.example.testapp.data.room.repository.basic.UserRepository
import com.example.testapp.data.room.repository.basic.WalletItemRepository import com.example.testapp.data.room.repository.basic.WalletItemRepository
import com.example.testapp.data.room.repository.offline.OfflineCoinRepository import com.example.testapp.data.room.repository.offline.OfflineCoinRepository
import com.example.testapp.data.room.repository.offline.OfflineDealRepository import com.example.testapp.data.room.repository.offline.OfflineDealRepository
import com.example.testapp.data.room.repository.offline.OfflineRemoteKeyRepository
import com.example.testapp.data.room.repository.offline.OfflineUserRepository import com.example.testapp.data.room.repository.offline.OfflineUserRepository
import com.example.testapp.data.room.repository.offline.OfflineWalletItemRepository import com.example.testapp.data.room.repository.offline.OfflineWalletItemRepository
@ -17,6 +23,11 @@ interface AppContainer {
val coinRepository: CoinRepository val coinRepository: CoinRepository
val walletItemRepository: WalletItemRepository val walletItemRepository: WalletItemRepository
val coinRestRepository: CoinRestRepository
val dealRestRepository: DealRestRepository
val userRestRepository: UserRestRepository
val walletItemRestRepository: WalletItemRestRepository
companion object { companion object {
const val TIMEOUT = 5000L const val TIMEOUT = 5000L
const val LIMIT = 10 const val LIMIT = 10
@ -26,6 +37,9 @@ interface AppContainer {
class AppDataContainer( class AppDataContainer(
private val context: Context private val context: Context
) : AppContainer { ) : AppContainer {
private val remoteKeyRepository: OfflineRemoteKeyRepository by lazy {
OfflineRemoteKeyRepository(CryptoDealDb.getInstance(context).remoteKeysDao())
}
override val userRepository: UserRepository by lazy { override val userRepository: UserRepository by lazy {
OfflineUserRepository(CryptoDealDb.getInstance(context).userDao()) OfflineUserRepository(CryptoDealDb.getInstance(context).userDao())
} }
@ -38,4 +52,34 @@ class AppDataContainer(
override val walletItemRepository: WalletItemRepository by lazy { override val walletItemRepository: WalletItemRepository by lazy {
OfflineWalletItemRepository(CryptoDealDb.getInstance(context).walletItemDao()) OfflineWalletItemRepository(CryptoDealDb.getInstance(context).walletItemDao())
} }
override val userRestRepository: UserRestRepository by lazy {
UserRestRepository(
CryptoDealService.getInstance(),
userRepository as OfflineUserRepository,
dealRepository as OfflineDealRepository,
walletItemRepository
)
}
override val coinRestRepository: CoinRestRepository by lazy {
CoinRestRepository(
CryptoDealService.getInstance(),
coinRepository as OfflineCoinRepository
)
}
override val dealRestRepository: DealRestRepository by lazy {
DealRestRepository(
CryptoDealService.getInstance(),
dealRepository as OfflineDealRepository,
remoteKeyRepository,
CryptoDealDb.getInstance(context)
)
}
override val walletItemRestRepository: WalletItemRestRepository by lazy {
WalletItemRestRepository(
CryptoDealService.getInstance(),
walletItemRepository as OfflineWalletItemRepository,
remoteKeyRepository,
CryptoDealDb.getInstance(context)
)
}
} }

View File

@ -20,7 +20,10 @@ interface DealDao : IDao<Deal> {
@Query("select * from deal where deal.buyerId = :idUser OR deal.sellerId = :idUser") @Query("select * from deal where deal.buyerId = :idUser OR deal.sellerId = :idUser")
fun getUserDeals(idUser: Int): Flow<List<Deal>> fun getUserDeals(idUser: Int): Flow<List<Deal>>
@Query("SELECT * FROM deal where deal.date IS NULL ORDER BY id ASC") @Query("SELECT * FROM deal WHERE deal.buyerId = :idUser AND deal.date IS NULL OR deal.sellerId = :idUser")
fun getUserDealsPaging(idUser: Int): PagingSource<Int, Deal>
@Query("SELECT * FROM deal ORDER BY id ASC")
fun getDeals(): PagingSource<Int, Deal> fun getDeals(): PagingSource<Int, Deal>
@Query("DELETE FROM deal") @Query("DELETE FROM deal")

View File

@ -1,17 +1,19 @@
package com.example.testapp.data.room.dao package com.example.testapp.data.room.dao
import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import com.example.testapp.data.room.models.RemoteKeyType import com.example.testapp.data.room.models.RemoteKeyType
import com.example.testapp.data.room.models.RemoteKeys import com.example.testapp.data.room.models.RemoteKeys
interface RemoteKeysDao { @Dao
interface RemoteKeysDao: IDao<RemoteKeys> {
@Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type") @Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type")
suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys? suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys?
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(remoteKey: List<RemoteKeys?>) suspend fun insertAll(remoteKey: List<RemoteKeys>)
@Query("DELETE FROM remote_keys WHERE type = :type") @Query("DELETE FROM remote_keys WHERE type = :type")
suspend fun clearRemoteKeys(type: RemoteKeyType) suspend fun clearRemoteKeys(type: RemoteKeyType)

View File

@ -5,19 +5,18 @@ import androidx.room.Query
import com.example.testapp.data.room.models.Deal import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.User import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.models.WalletItem import com.example.testapp.data.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface UserDao : IDao<User> { interface UserDao : IDao<User> {
@Query("select * from user") @Query("select * from user")
fun getAll(): Flow<List<User>> fun getAll(): List<User>
@Query("select * from user where user.id = :idUser") @Query("select * from user where user.id = :idUser")
fun getUserById(idUser: Int): User fun getUserById(idUser: Int): User
@Query("select * from walletitem where walletitem.userId = :idUser") @Query("select * from walletitem where walletitem.userId = :idUser")
fun getUserWallet(idUser: Int): Flow<List<WalletItem>> fun getUserWallet(idUser: Int): List<WalletItem>
@Query("select * from deal where deal.buyerId = :idUser OR deal.sellerId = :idUser") @Query("select * from deal where deal.buyerId = :idUser OR deal.sellerId = :idUser")
fun getUserDeals(idUser: Int): Flow<List<Deal>> fun getUserDeals(idUser: Int): List<Deal>
} }

View File

@ -17,7 +17,7 @@ interface WalletItemDao : IDao<WalletItem> {
fun getUserWallet(id: Int): List<WalletItem> fun getUserWallet(id: Int): List<WalletItem>
@Query("SELECT * FROM walletitem where walletitem.userId = :id ORDER BY walletitem.coinId ASC") @Query("SELECT * FROM walletitem where walletitem.userId = :id ORDER BY walletitem.coinId ASC")
fun getDeals(id: Int): PagingSource<Int, WalletItem> fun getWallet(id: Int): PagingSource<Int, WalletItem>
@Query("DELETE FROM walletitem") @Query("DELETE FROM walletitem")
suspend fun deleteAll() suspend fun deleteAll()

View File

@ -24,10 +24,10 @@ abstract class CryptoDealDb: RoomDatabase() {
abstract fun coinDao(): CoinDao; abstract fun coinDao(): CoinDao;
abstract fun dealDao(): DealDao; abstract fun dealDao(): DealDao;
abstract fun walletItemDao(): WalletItemDao; abstract fun walletItemDao(): WalletItemDao;
abstract fun RemoteKeysDao(): RemoteKeysDao; abstract fun remoteKeysDao(): RemoteKeysDao;
companion object { companion object {
private const val DB_NAME: String = "crypto-deal7" private const val DB_NAME: String = "crypto-deal13"
@Volatile @Volatile
private var INSTANCE: CryptoDealDb? = null private var INSTANCE: CryptoDealDb? = null
@ -57,25 +57,25 @@ abstract class CryptoDealDb: RoomDatabase() {
coinDao.insert(c6) coinDao.insert(c6)
coinDao.insert(c7) coinDao.insert(c7)
val walletItemDao = database.walletItemDao(); // val walletItemDao = database.walletItemDao();
val wi1 = WalletItem(0, 0, 0.5f); // val wi1 = WalletItem(0, 0, 0.5f);
val wi2 = WalletItem(1, 0, 0.6f); // val wi2 = WalletItem(1, 0, 0.6f);
val wi3 = WalletItem(3, 0, 0.7f); // val wi3 = WalletItem(3, 0, 0.7f);
val wi4 = WalletItem(0, 1, 1000f); // val wi4 = WalletItem(0, 1, 1000f);
val wi5 = WalletItem(3, 1, 10f); // val wi5 = WalletItem(3, 1, 10f);
val wi6 = WalletItem(2, 1, 1f); // val wi6 = WalletItem(2, 1, 1f);
val wi7 = WalletItem(4, 0, 1.1f); // val wi7 = WalletItem(4, 0, 1.1f);
val wi8 = WalletItem(5, 0, 1.1f); // val wi8 = WalletItem(5, 0, 1.1f);
val wi9 = WalletItem(6, 0, 1.1f); // val wi9 = WalletItem(6, 0, 1.1f);
walletItemDao.insert(wi1); // walletItemDao.insert(wi1);
walletItemDao.insert(wi2); // walletItemDao.insert(wi2);
walletItemDao.insert(wi3); // walletItemDao.insert(wi3);
walletItemDao.insert(wi4); // walletItemDao.insert(wi4);
walletItemDao.insert(wi5); // walletItemDao.insert(wi5);
walletItemDao.insert(wi6); // walletItemDao.insert(wi6);
walletItemDao.insert(wi7); // walletItemDao.insert(wi7);
walletItemDao.insert(wi8); // walletItemDao.insert(wi8);
walletItemDao.insert(wi9); // walletItemDao.insert(wi9);
val dealDao = database.dealDao(); val dealDao = database.dealDao();
val d1 = Deal(0, null, 0, 2, 0, 0.1f, 0.2f, "Buy", null, "TEST1") val d1 = Deal(0, null, 0, 2, 0, 0.1f, 0.2f, "Buy", null, "TEST1")

View File

@ -17,5 +17,11 @@ class Deal (
var date: Long?, var date: Long?,
val tip: String, val tip: String,
) { ) {
override fun equals(other: Any?): Boolean {
return (other as Deal).id == this.id
}
override fun hashCode(): Int {
return id ?: -1
}
} }

View File

@ -2,20 +2,28 @@ package com.example.testapp.data.room.models
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
@Entity( @Entity(
primaryKeys = ["coinId", "userId"],
foreignKeys = [ foreignKeys = [
ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"], onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE), ForeignKey(entity = User::class, parentColumns = ["id"], childColumns = ["userId"], onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE),
ForeignKey(entity = Coin::class, parentColumns = ["id"], childColumns = ["coinId"], onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE) ForeignKey(entity = Coin::class, parentColumns = ["id"], childColumns = ["coinId"], onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE)
] ],
indices = [Index(value = ["coinId", "userId"])]
) )
class WalletItem ( class WalletItem (
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true) val id: Int?,
val id: Int?,
val coinId: Int, val coinId: Int,
val userId: Int, val userId: Int,
var count: Float, var count: Float,
// val freeze: Float ) {
) override fun equals(other: Any?): Boolean {
other as WalletItem
return other.coinId == this.coinId && other.userId == this.userId
}
override fun hashCode(): Int {
return id!!
}
}

View File

@ -5,6 +5,6 @@ import com.example.testapp.data.room.models.RemoteKeys
interface RemoteKeyRepository { interface RemoteKeyRepository {
suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys? suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys?
suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys?>) suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>)
suspend fun deleteRemoteKey(type: RemoteKeyType) suspend fun deleteRemoteKey(type: RemoteKeyType)
} }

View File

@ -9,7 +9,7 @@ class OfflineRemoteKeyRepository(private val remoteKeysDao: RemoteKeysDao) : Rem
override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) = override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
remoteKeysDao.getRemoteKeys(id, type) remoteKeysDao.getRemoteKeys(id, type)
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys?>) = override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
remoteKeysDao.insertAll(remoteKeys) remoteKeysDao.insertAll(remoteKeys)
override suspend fun deleteRemoteKey(type: RemoteKeyType) = override suspend fun deleteRemoteKey(type: RemoteKeyType) =

View File

@ -5,13 +5,12 @@ import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.User import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.models.WalletItem import com.example.testapp.data.room.models.WalletItem
import com.example.testapp.data.room.repository.basic.UserRepository import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.Flow
class OfflineUserRepository( class OfflineUserRepository(
private val userDao: UserDao private val userDao: UserDao
) : OfflineRepository<User>(userDao), UserRepository { ) : OfflineRepository<User>(userDao), UserRepository {
override suspend fun getAll(): Flow<List<User>> = userDao.getAll() override suspend fun getAll(): List<User> = userDao.getAll()
override suspend fun getById(id: Int): User = userDao.getUserById(id) override suspend fun getById(id: Int): User = userDao.getUserById(id)
override suspend fun getUserWallet(id: Int): Flow<List<WalletItem>> = userDao.getUserWallet(id) override suspend fun getUserWallet(id: Int): List<WalletItem> = userDao.getUserWallet(id)
override suspend fun getUserDeals(id: Int): Flow<List<Deal>> = userDao.getUserDeals(id) override suspend fun getUserDeals(id: Int): List<Deal> = userDao.getUserDeals(id)
} }

View File

@ -21,7 +21,7 @@ class OfflineWalletItemRepository(
pageSize = 10, jumpThreshold = 10, initialLoadSize = 10 pageSize = 10, jumpThreshold = 10, initialLoadSize = 10
), pagingSourceFactory = { WalletPagination(walletItemDao, id) }, initialKey = 1).flow ), pagingSourceFactory = { WalletPagination(walletItemDao, id) }, initialKey = 1).flow
override fun getWalletItemsPaging(id: Int): PagingSource<Int, WalletItem> = walletItemDao.getDeals(id) override fun getWalletItemsPaging(id: Int): PagingSource<Int, WalletItem> = walletItemDao.getWallet(id)
override suspend fun clearData() = walletItemDao.deleteAll() override suspend fun clearData() = walletItemDao.deleteAll()
suspend fun insert(list: List<WalletItem>) = walletItemDao.insert(*list.toTypedArray()) suspend fun insert(list: List<WalletItem>) = walletItemDao.insert(*list.toTypedArray())
} }

View File

@ -1,7 +1,6 @@
package com.example.pmulabs.designElem package com.example.pmulabs.designElem
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -11,7 +10,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidth import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -21,7 +19,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.toUpperCase
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
@ -30,7 +27,6 @@ import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import com.example.testapp.navigate.BottomBarScreen import com.example.testapp.navigate.BottomBarScreen
import java.util.Locale
@Composable @Composable
fun NavBar(navController: NavHostController){ fun NavBar(navController: NavHostController){
@ -84,7 +80,7 @@ fun AddItem(
.clickable(onClick = { .clickable(onClick = {
navController.navigate(screen.route) { navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = false launchSingleTop = true
} }
}) })
.clip(shape = RoundedCornerShape(10.dp)) .clip(shape = RoundedCornerShape(10.dp))

View File

@ -1,24 +0,0 @@
package com.example.testapp.designElem
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class SharedViewModel : ViewModel() {
val argument = mutableStateOf<String?>(null)
val argument_edit = mutableStateOf<Any?>(null)
val argument_add_f = mutableStateOf<Any?>(null)
val argument_add_c = mutableStateOf<Any?>(null)
fun setArgumentAdd(arg1: Any, arg2: Any) {
argument_add_f.value = arg1
argument_add_c.value = arg2
}
fun setArgumentEdit(arg: Any?) {
argument_edit.value = arg
}
fun setArgument(arg: String) {
argument.value = arg
}
}

View File

@ -6,18 +6,20 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.screensMobile.AccountPage import com.example.testapp.screensMobile.AccountPage
import com.example.testapp.screensMobile.CreateDeal import com.example.testapp.screensMobile.CreateDeal
import com.example.testapp.screensMobile.DealList import com.example.testapp.screensMobile.DealList
import com.example.testapp.screensMobile.History import com.example.testapp.screensMobile.History
import com.example.testapp.screensMobile.ReportScreen
import com.example.testapp.screensMobile.Wallet import com.example.testapp.screensMobile.Wallet
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.HistoryViewModel import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.ReportViewModel
import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.viewModels.WalletViewModel import com.example.testapp.viewModels.WalletViewModel
@RequiresApi(34) @RequiresApi(34)
@ -29,6 +31,7 @@ fun HomeNavGraph(
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory), dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory), historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory), walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory),
reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory),
sharedViewModel: SharedViewModel sharedViewModel: SharedViewModel
) { ) {
NavHost( NavHost(
@ -72,5 +75,12 @@ fun HomeNavGraph(
historyViewModel = historyViewModel historyViewModel = historyViewModel
) )
} }
composable(route = BottomBarScreen.Report.route) {
ReportScreen(
navController = navController,
currentUserViewModel = currentUserViewModel,
reportViewModel = reportViewModel
)
}
} }
} }

View File

@ -8,7 +8,6 @@ import androidx.navigation.NavType
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.screensMobile.LoadScreen import com.example.testapp.screensMobile.LoadScreen
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel import com.example.testapp.viewModels.CurrentUserViewModel
@ -17,6 +16,8 @@ import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.EntryScreenViewModel import com.example.testapp.viewModels.EntryScreenViewModel
import com.example.testapp.viewModels.HistoryViewModel import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.RegistrationScreenViewModel import com.example.testapp.viewModels.RegistrationScreenViewModel
import com.example.testapp.viewModels.ReportViewModel
import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.viewModels.WalletViewModel import com.example.testapp.viewModels.WalletViewModel
const val USERID_ARGUMENT = "userId" const val USERID_ARGUMENT = "userId"
@ -32,6 +33,7 @@ fun RootNavigationGraph(
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory), historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
registrationScreenViewModel: RegistrationScreenViewModel = viewModel(factory = AppViewModelProvider.Factory), registrationScreenViewModel: RegistrationScreenViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory), walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory),
reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory),
sharedViewModel: SharedViewModel sharedViewModel: SharedViewModel
) { ) {
NavHost( NavHost(
@ -57,7 +59,8 @@ fun RootNavigationGraph(
dealListViewModel = dealListViewModel, dealListViewModel = dealListViewModel,
historyViewModel = historyViewModel, historyViewModel = historyViewModel,
walletViewModel = walletViewModel, walletViewModel = walletViewModel,
sharedViewModel = sharedViewModel sharedViewModel = sharedViewModel,
reportViewModel = reportViewModel
) )
} }
} }

View File

@ -20,6 +20,10 @@ sealed class BottomBarScreen(
route = "HISTORY", route = "HISTORY",
title = "History" title = "History"
) )
object Report: BottomBarScreen(
route = "REPORT",
title = "Report"
)
object CDEAL: BottomBarScreen( object CDEAL: BottomBarScreen(
route = "CDEAL", route = "CDEAL",
title = "CDEAL" title = "CDEAL"

View File

@ -1,6 +1,8 @@
package com.example.testapp.screensMobile package com.example.testapp.screensMobile
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@ -17,17 +19,18 @@ import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Fingerprint
import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -36,11 +39,12 @@ import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination import com.example.testapp.R
import com.example.testapp.graphs.AuthScreen import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel import com.example.testapp.viewModels.CurrentUserViewModel
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("CoroutineCreationDuringComposition") @SuppressLint("CoroutineCreationDuringComposition")
@Composable @Composable
fun AccountPage( fun AccountPage(
@ -122,8 +126,7 @@ fun AccountPage(
y = 204.dp y = 204.dp
) )
) { ) {
Property1Switch(modifier = Modifier.padding(vertical = 5.dp)) Property1Arrow(modifier = Modifier.padding(vertical = 5.dp), navController)
Property1Arrow(modifier = Modifier.padding(vertical = 5.dp))
} }
Property1Clear(navController = navController) Property1Clear(navController = navController)
Property1( Property1(
@ -137,46 +140,6 @@ fun AccountPage(
} }
} }
@Composable
fun Property1Switch(modifier: Modifier = Modifier) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.background(color = Color.White)
.padding(
start = 12.dp,
end = 16.dp,
top = 4.dp,
bottom = 4.dp
)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(all = 12.dp)
) {
// Icon(
// painter = painterResource(id = R.drawable.sizem),
// contentDescription = "IconFavorite",
// tint = Color(0xff002033).copy(alpha = 0.35f))
}
Text(
text = "Enable Notifications",
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp
),
modifier = Modifier
.weight(weight = 1f)
.wrapContentHeight(align = Alignment.CenterVertically)
)
Viewchecked()
}
}
@Composable @Composable
fun Container(modifier: Modifier = Modifier, name: String) { fun Container(modifier: Modifier = Modifier, name: String) {
Column( Column(
@ -231,7 +194,7 @@ fun Viewchecked(modifier: Modifier = Modifier) {
} }
@Composable @Composable
fun Property1Arrow(modifier: Modifier = Modifier) { fun Property1Arrow(modifier: Modifier = Modifier, navController: NavController) {
Row( Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally), horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@ -243,19 +206,22 @@ fun Property1Arrow(modifier: Modifier = Modifier) {
top = 4.dp, top = 4.dp,
bottom = 4.dp bottom = 4.dp
) )
.clickable {
navController.navigate(route = BottomBarScreen.Report.route)
}
) { ) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
.padding(all = 12.dp) .padding(all = 12.dp)
) { ) {
// Icon( Icon(
// painter = painterResource(id = R.drawable.sizem), Icons.Rounded.Fingerprint,
// contentDescription = "IconFavorite", contentDescription = stringResource(id = R.string.app_name)
// tint = Color(0xff002033).copy(alpha = 0.35f)) )
} }
Text( Text(
text = "Confirm Account", text = "Report",
color = Color(0xff0b1f33), color = Color(0xff0b1f33),
lineHeight = 1.25.em, lineHeight = 1.25.em,
style = TextStyle( style = TextStyle(
@ -275,12 +241,6 @@ fun Property1Clear(modifier: Modifier = Modifier, navController: NavController)
modifier = modifier modifier = modifier
.fillMaxSize() .fillMaxSize()
.clip(shape = RoundedCornerShape(10.dp)) .clip(shape = RoundedCornerShape(10.dp))
.clickable {
navController.navigate(route = AuthScreen.Entry.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
.padding( .padding(
start = 16.dp, start = 16.dp,
end = 16.dp, end = 16.dp,

View File

@ -39,16 +39,16 @@ import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.example.testapp.designElem.DropDown
import com.example.testapp.designElem.DropDownConfig
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.data.room.models.Coin import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.WalletItem import com.example.testapp.data.room.models.WalletItem
import com.example.testapp.designElem.DropDown
import com.example.testapp.designElem.DropDownConfig
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.SharedViewModel
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -43,7 +43,7 @@ import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.paging.LoadState import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import com.example.testapp.designElem.SharedViewModel import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.data.room.models.Coin import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal import com.example.testapp.data.room.models.Deal
@ -98,16 +98,16 @@ fun DealList(
} }
deals.apply { deals.apply {
when{ when{
loadState.refresh is LoadState.Loading -> { // loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator( // item { CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(0.5f), // modifier = Modifier.fillParentMaxSize(0.5f),
color = Color(0xff423a99)) } // color = Color(0xff423a99)) }
} // }
loadState.append is LoadState.Loading -> { // loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator( // item { CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(0.5f), // modifier = Modifier.fillParentMaxSize(0.5f),
color = Color(0xff423a99)) } // color = Color(0xff423a99)) }
} // }
loadState.refresh is LoadState.Error -> { loadState.refresh is LoadState.Error -> {
val err = deals.loadState.refresh as LoadState.Error val err = deals.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) } item { Text(err.error.localizedMessage) }

View File

@ -6,15 +6,15 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -34,6 +34,7 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.testapp.data.room.models.Coin import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal import com.example.testapp.data.room.models.Deal
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider
@ -53,28 +54,33 @@ fun History(
) { ) {
val user by currentUserViewModel.user.collectAsState() val user by currentUserViewModel.user.collectAsState()
val id = user!!.id val id = user!!.id
historyViewModel.setArgument(id.toString()); historyViewModel.setArgument(id.toString())
val history by historyViewModel.deals.collectAsState() val history = historyViewModel.deals.collectAsLazyPagingItems()
val coins by historyViewModel.coins.collectAsState() val coins by historyViewModel.coins.collectAsState()
Column( LazyColumn(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top), verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = PaddingValues(bottom = 70.dp),
modifier = modifier modifier = modifier
.requiredHeight(height = 720.dp)
.background(color = Color(0xfff4f7fb)) .background(color = Color(0xfff4f7fb))
.padding(vertical = 20.dp) .padding(vertical = 20.dp)
.verticalScroll(rememberScrollState()) .fillMaxSize()
) { ) {
item {
PropertyHistory() PropertyHistory()
history.forEach { x -> }
items(count = history.itemCount) {
val item = history[it]
if (item != null) {
HistoryCard( HistoryCard(
deal = x, deal = item,
modifier = Modifier.padding(vertical = 5.dp, horizontal = 5.dp), modifier = Modifier.padding(vertical = 5.dp, horizontal = 5.dp),
coins = coins coins = coins
) )
} }
} }
}
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)

View File

@ -0,0 +1,294 @@
package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.ReportViewModel
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneOffset
@RequiresApi(Build.VERSION_CODES.O)
fun longToDate(value: Long): LocalDateTime {
return LocalDateTime
.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
}
@OptIn(ExperimentalMaterial3Api::class)
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("CoroutineCreationDuringComposition", "SimpleDateFormat")
@Composable
fun ReportScreen(
modifier: Modifier = Modifier,
navController: NavController,
currentUserViewModel: CurrentUserViewModel = viewModel(factory = AppViewModelProvider.Factory),
reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
reportViewModel.clearLists()
val user by currentUserViewModel.user.collectAsState()
val deals by reportViewModel.deals.collectAsState()
val coins by reportViewModel.coins.collectAsState()
val dateStateFrom = rememberDatePickerState()
val showDialogFrom = rememberSaveable { mutableStateOf(false) }
if (showDialogFrom.value) {
DatePickerDialog(
onDismissRequest = { showDialogFrom.value = false },
confirmButton = {
TextButton(onClick = { showDialogFrom.value = false }) {
Text("Ok")
}
},
dismissButton = {
TextButton(onClick = { showDialogFrom.value = false }) {
Text("Cancel")
}
}
) {
DatePicker(state = dateStateFrom)
}
}
val dateStateTo = rememberDatePickerState()
val showDialogTo = rememberSaveable { mutableStateOf(false) }
if (showDialogTo.value) {
DatePickerDialog(
onDismissRequest = { showDialogTo.value = false },
confirmButton = {
TextButton(onClick = { showDialogTo.value = false }) {
Text("Ok")
}
},
dismissButton = {
TextButton(onClick = { showDialogTo.value = false }) {
Text("Cancel")
}
}
) {
DatePicker(state = dateStateTo)
}
}
LazyColumn(
verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
.fillMaxSize()
.background(color = Color(0xfff4f7fb))
.padding(
horizontal = 5.dp,
vertical = 1.dp
)
) {
item {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth(1f)
.requiredHeight(height = 56.dp)
.background(color = Color.White)
.padding(
horizontal = 17.dp,
vertical = 6.dp
)
) {
Text(
text = "Report",
color = Color.Black,
lineHeight = 1.14.em,
style = TextStyle(
fontSize = 14.sp,
fontWeight = FontWeight.Medium
)
)
Text(
text = "Back",
color = Color(0xFFF94B4B),
textAlign = TextAlign.Center,
lineHeight = 0.83.em,
style = TextStyle(
fontSize = 14.sp,
letterSpacing = 0.1.sp
),
modifier = Modifier
.clickable {
navController.navigate(route = BottomBarScreen.Profile.route)
}
.wrapContentHeight(align = Alignment.CenterVertically))
}
}
item {
Button(
onClick = {
showDialogFrom.value = true;
},
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff4bb2f9)),
modifier = Modifier
.fillMaxWidth()
) {
Text(
if (dateStateFrom.selectedDateMillis != null)
longToDate(dateStateFrom.selectedDateMillis!!).toLocalDate().toString() else
"Select Date"
)
}
Button(
onClick = {
showDialogTo.value = true;
},
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff4bb2f9)),
modifier = Modifier
.fillMaxWidth()
) {
Text(
if (dateStateTo.selectedDateMillis != null)
longToDate(dateStateTo.selectedDateMillis!!).toLocalDate().toString() else
"Select Date"
)
}
}
item {
Button(
onClick = {
if (dateStateTo.selectedDateMillis != null &&
dateStateFrom.selectedDateMillis != null) {
reportViewModel.setArguments(
user?.id!!,
longToDate(dateStateFrom.selectedDateMillis!!),
longToDate(dateStateTo.selectedDateMillis!!)
)
}
},
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff4bb2f9)),
modifier = Modifier
.fillMaxWidth()
) {
Text("Create")
}
}
if (deals.isNotEmpty()) {
items(items = deals) {
ReportItem(deal = it, coins = coins)
}
}
else {
item {
Text(text = "No Data")
}
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun ReportItem(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {
Column(
verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.height(40.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = Color.White)
.padding(
horizontal = 12.dp,
vertical = 5.dp
)
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(all = 2.dp)
) {
Text(
text = "-${deal.countSell} ${
coins.first { x -> x.id == deal.sellerCoinId }.shortName()
}",
color = Color(0xfff96161),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically)
)
Text(
text = "->",
color = Color(0xFF009688),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically)
)
Text(
text = "+${deal.countBuy} ${
coins.first { x -> x.id == deal.buyerCoinId }.shortName()
}",
color = Color(0xff5acb48),
lineHeight = 1.25.em,
style = TextStyle(
fontSize = 16.sp,
letterSpacing = 0.1.sp
),
modifier = Modifier
.wrapContentHeight(align = Alignment.CenterVertically)
)
}
}
}

View File

@ -1,25 +1,21 @@
package com.example.testapp.screensMobile package com.example.testapp.screensMobile
import android.annotation.SuppressLint
import android.os.Build import android.os.Build
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -28,22 +24,22 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.paging.LoadState
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.pmulabs.designElem.NavBar import com.example.pmulabs.designElem.NavBar
import com.example.testapp.designElem.ListItem import com.example.testapp.designElem.ListItem
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.graphs.HomeNavGraph import com.example.testapp.graphs.HomeNavGraph
import com.example.testapp.viewModels.AppViewModelProvider import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.HistoryViewModel import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.ReportViewModel
import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.viewModels.WalletViewModel import com.example.testapp.viewModels.WalletViewModel
import kotlinx.coroutines.flow.first
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
@Composable @Composable
@ -83,16 +79,16 @@ fun Wallet(
} }
wallet.apply { wallet.apply {
when{ when{
loadState.refresh is LoadState.Loading -> { // loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator( // item { CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(0.5f), // modifier = Modifier.fillParentMaxSize(0.5f),
color = Color(0xff423a99)) } // color = Color(0xff423a99)) }
} // }
loadState.append is LoadState.Loading -> { // loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator( // item { CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(0.5f), // modifier = Modifier.fillParentMaxSize(0.5f),
color = Color(0xff423a99)) } // color = Color(0xff423a99)) }
} // }
loadState.refresh is LoadState.Error -> { loadState.refresh is LoadState.Error -> {
val err = wallet.loadState.refresh as LoadState.Error val err = wallet.loadState.refresh as LoadState.Error
item { Text(err.error.localizedMessage) } item { Text(err.error.localizedMessage) }
@ -116,6 +112,7 @@ fun LoadScreen(
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory), dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory), historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory), walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory),
reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory),
sharedViewModel: SharedViewModel sharedViewModel: SharedViewModel
) { ) {
Scaffold( Scaffold(
@ -130,6 +127,7 @@ fun LoadScreen(
dealListViewModel, dealListViewModel,
historyViewModel, historyViewModel,
walletViewModel, walletViewModel,
reportViewModel,
sharedViewModel sharedViewModel
) )
} }

View File

@ -1,5 +1,7 @@
package com.example.testapp.viewModels package com.example.testapp.viewModels
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.initializer
@ -7,39 +9,46 @@ import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.testapp.CryptoDealApplication import com.example.testapp.CryptoDealApplication
object AppViewModelProvider { object AppViewModelProvider {
@RequiresApi(Build.VERSION_CODES.O)
val Factory = viewModelFactory { val Factory = viewModelFactory {
initializer {
EntryScreenViewModel(application().container.userRestRepository)
}
initializer { initializer {
CurrentUserViewModel(application().container.userRepository) CurrentUserViewModel(application().container.userRepository)
} }
initializer {
WalletViewModel(
application().container.walletItemRestRepository,
application().container.coinRestRepository
)
}
initializer { initializer {
DealListViewModel( DealListViewModel(
application().container.dealRepository, application().container.dealRestRepository,
application().container.coinRepository, application().container.coinRestRepository,
application().container.walletItemRepository application().container.walletItemRestRepository
) )
} }
initializer { initializer {
DealCreateViewModel( DealCreateViewModel(
application().container.dealRepository, application().container.dealRestRepository,
application().container.coinRepository, application().container.coinRestRepository,
application().container.walletItemRepository application().container.walletItemRestRepository
) )
} }
initializer {
EntryScreenViewModel(application().container.userRepository)
}
initializer { initializer {
HistoryViewModel( HistoryViewModel(
application().container.dealRepository, application().container.dealRestRepository,
application().container.coinRepository application().container.coinRestRepository
) )
} }
initializer { initializer {
RegistrationScreenViewModel(application().container.userRepository) RegistrationScreenViewModel(application().container.userRestRepository)
} }
initializer { initializer {
WalletViewModel( ReportViewModel(
application().container.walletItemRepository, application().container.dealRestRepository,
application().container.coinRepository application().container.coinRepository
) )
} }

View File

@ -4,11 +4,12 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.testapp.data.room.models.User import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.repository.basic.UserRepository import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class CurrentUserViewModel(private val userRepository: UserRepository) : ViewModel() { class CurrentUserViewModel(private val userRepository: UserRepository) : ViewModel() {
val argument = MutableStateFlow<String?>(null) private val argument = MutableStateFlow<String?>(null)
val id = MutableStateFlow<Int?>(null) val id = MutableStateFlow<Int?>(null)
var user = MutableStateFlow<User?>(null) var user = MutableStateFlow<User?>(null)
@ -16,7 +17,7 @@ class CurrentUserViewModel(private val userRepository: UserRepository) : ViewMod
argument.value = arg argument.value = arg
id.value = arg.toInt() id.value = arg.toInt()
viewModelScope.launch { viewModelScope.launch(Dispatchers.IO) {
user.emit(userRepository.getById(id.value!!)) user.emit(userRepository.getById(id.value!!))
} }
} }

View File

@ -12,7 +12,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class DealCreateViewModel( class DealCreateViewModel(
@ -36,12 +35,8 @@ class DealCreateViewModel(
init { init {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
_coins.emit( _coins.emit(coinRepository.getAll())
coinRepository.getAll().first() _wallet.emit(walletItemRepository.getAll())
)
_wallet.emit(
walletItemRepository.getAll().first()
)
} }
} }

View File

@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData import androidx.paging.PagingData
import androidx.paging.cachedIn import androidx.paging.cachedIn
import androidx.paging.filter
import com.example.testapp.data.room.models.Coin import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.WalletItem import com.example.testapp.data.room.models.WalletItem
@ -27,19 +28,20 @@ class DealListViewModel(
fun setupLists() { fun setupLists() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
coins.emit(coinRepository.getAll().first()) coins.emit(coinRepository.getAll())
deals.emit(dealRepository deals.emit(dealRepository
.pagingData() .pagingData()
.cachedIn(viewModelScope) .cachedIn(viewModelScope)
.first()) .first()
.filter { it.date == null })
} }
} }
@RequiresApi(34) @RequiresApi(34)
fun submitDeal(deal: Deal, sellerId: Int, buyerId: Int) { fun submitDeal(deal: Deal, sellerId: Int, buyerId: Int) {
viewModelScope.launch { viewModelScope.launch {
val walletSeller: List<WalletItem> = walletItemRepository.getUserWallet(sellerId).first() val walletSeller: List<WalletItem> = walletItemRepository.getUserWallet(sellerId)
val walletBuyer: List<WalletItem> = walletItemRepository.getUserWallet(buyerId).first() val walletBuyer: List<WalletItem> = walletItemRepository.getUserWallet(buyerId)
val seller: WalletItem? = walletSeller.firstOrNull { x -> x.coinId == deal.sellerCoinId } val seller: WalletItem? = walletSeller.firstOrNull { x -> x.coinId == deal.sellerCoinId }
val buyer: WalletItem? = walletBuyer.firstOrNull { x -> x.coinId == deal.buyerId } val buyer: WalletItem? = walletBuyer.firstOrNull { x -> x.coinId == deal.buyerId }
@ -54,7 +56,7 @@ class DealListViewModel(
} }
// Case if need insert // Case if need insert
else { else {
val item = WalletItem(deal.buyerCoinId, sellerId, deal.countBuy) val item = WalletItem(null, deal.buyerCoinId, sellerId, deal.countBuy)
walletItemRepository.insert(item) walletItemRepository.insert(item)
} }
@ -67,7 +69,7 @@ class DealListViewModel(
} }
// Case if need insert // Case if need insert
else { else {
val item = WalletItem(deal.sellerCoinId, buyerId, deal.countSell) val item = WalletItem(null, deal.sellerCoinId, buyerId, deal.countSell)
walletItemRepository.insert(item) walletItemRepository.insert(item)
} }

View File

@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope
import com.example.testapp.data.room.models.User import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.repository.basic.UserRepository import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class EntryScreenViewModel( class EntryScreenViewModel(
@ -15,7 +14,7 @@ class EntryScreenViewModel(
fun setupList() { fun setupList() {
viewModelScope.launch { viewModelScope.launch {
userList.emit(userRepository.getAll().first()) userList.emit(userRepository.getAll())
} }
} }
} }

View File

@ -2,6 +2,9 @@ package com.example.testapp.viewModels
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.filter
import com.example.testapp.data.room.models.Coin import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.repository.basic.CoinRepository import com.example.testapp.data.room.repository.basic.CoinRepository
@ -17,15 +20,26 @@ class HistoryViewModel(
) : ViewModel() { ) : ViewModel() {
val argument = MutableStateFlow<String?>(null) val argument = MutableStateFlow<String?>(null)
private val id = MutableStateFlow<Int?>(null) private val id = MutableStateFlow<Int?>(null)
var deals = MutableStateFlow<List<Deal>>(emptyList()) var deals = MutableStateFlow<PagingData<Deal>>(PagingData.empty())
var coins = MutableStateFlow<List<Coin>>(emptyList()) var coins = MutableStateFlow<List<Coin>>(emptyList())
init {
viewModelScope.launch(Dispatchers.IO) {
deals.emit(dealRepository.pagingData().cachedIn(viewModelScope).first().filter {
x -> x.date == null
})
coins.emit(coinRepository.getAll())
}
}
fun setArgument(arg: String) { fun setArgument(arg: String) {
argument.value = arg argument.value = arg
id.value = arg.toInt() id.value = arg.toInt()
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
deals.emit(dealRepository.getAll().first()) deals.emit(dealRepository.pagingData().cachedIn(viewModelScope).first().filter {
coins.emit(coinRepository.getAll().first()) x -> (x.buyerId == arg.toInt() || x.sellerId == arg.toInt())
})
coins.emit(coinRepository.getAll())
} }
} }
} }

View File

@ -6,7 +6,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.testapp.data.room.models.User import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.repository.basic.UserRepository import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class RegistrationScreenViewModel(private val userRepository: UserRepository) : ViewModel() { class RegistrationScreenViewModel(private val userRepository: UserRepository) : ViewModel() {
@ -15,7 +14,7 @@ class RegistrationScreenViewModel(private val userRepository: UserRepository) :
fun setUserList() { fun setUserList() {
viewModelScope.launch { viewModelScope.launch {
_users.value = userRepository.getAll().first() _users.value = userRepository.getAll()
} }
} }

View File

@ -0,0 +1,49 @@
package com.example.testapp.viewModels
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.repository.basic.CoinRepository
import com.example.testapp.data.room.repository.basic.DealRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.time.LocalDateTime
import java.time.ZoneOffset
@RequiresApi(Build.VERSION_CODES.O)
class ReportViewModel(
private val dealRepository: DealRepository,
private val coinRepository: CoinRepository
) : ViewModel() {
private var startDate = MutableStateFlow<LocalDateTime>(LocalDateTime.now().minusDays(1))
private var endDate = MutableStateFlow<LocalDateTime>(LocalDateTime.now())
var deals = MutableStateFlow<List<Deal>>(emptyList())
var coins = MutableStateFlow<List<Coin>>(emptyList())
fun clearLists() {
deals = MutableStateFlow(emptyList())
coins = MutableStateFlow(emptyList())
}
fun setArguments(userId: Int, from : LocalDateTime, to : LocalDateTime) {
viewModelScope.launch(Dispatchers.IO) {
startDate.emit(from)
endDate.emit(to)
val eptf = from.toEpochSecond(ZoneOffset.UTC) * 1000
val eptt = to.toEpochSecond(ZoneOffset.UTC) * 1000
deals.emit(
dealRepository.getUserDeals(userId).filter {
it.date != null &&
it.date!! >= eptf &&
it.date!! <= eptt
}
)
coins.emit(coinRepository.getAll())
}
}
}

View File

@ -0,0 +1,16 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.example.testapp.data.room.models.Deal
class SharedViewModel : ViewModel() {
var argument_edit = mutableStateOf<Deal?>(null)
fun setArgumentEdit(arg: Deal?) {
if (arg == null) {
argument_edit = mutableStateOf<Deal?>(null)
}
argument_edit.value = arg
}
}

View File

@ -8,6 +8,7 @@ import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.WalletItem import com.example.testapp.data.room.models.WalletItem
import com.example.testapp.data.room.repository.basic.CoinRepository import com.example.testapp.data.room.repository.basic.CoinRepository
import com.example.testapp.data.room.repository.basic.WalletItemRepository import com.example.testapp.data.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -17,17 +18,17 @@ class WalletViewModel(
private val walletItemRepository: WalletItemRepository, private val walletItemRepository: WalletItemRepository,
private val coinRepository: CoinRepository private val coinRepository: CoinRepository
) : ViewModel() { ) : ViewModel() {
val argument = MutableStateFlow<String?>(null) private val argument = MutableStateFlow<String?>(null)
private val id = MutableStateFlow<Int?>(null) private val id = MutableStateFlow<Int?>(null)
var _wallet = MutableStateFlow<PagingData<WalletItem>>(PagingData.empty()) private var _wallet = MutableStateFlow<PagingData<WalletItem>>(PagingData.empty())
var wallet = _wallet.asStateFlow(); var wallet = _wallet.asStateFlow();
var coins = MutableStateFlow<List<Coin>?>(emptyList()) var coins = MutableStateFlow<List<Coin>?>(emptyList())
fun setArgument(arg: String) { fun setArgument(arg: String) {
argument.value = arg argument.value = arg
id.value = arg.toInt() id.value = arg.toInt()
viewModelScope.launch { viewModelScope.launch(Dispatchers.IO) {
coins.emit(coinRepository.getAll().first()) coins.emit(coinRepository.getAll())
_wallet.emit(walletItemRepository _wallet.emit(walletItemRepository
.pagingData(id.value!!) .pagingData(id.value!!)
.cachedIn(viewModelScope) .cachedIn(viewModelScope)

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">172.20.10.13</domain>
</domain-config>
</network-security-config>