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.lifecycle.viewmodel.compose.viewModel
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.ui.theme.TestAppTheme
import com.example.testapp.viewModels.AppViewModelProvider

View File

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

View File

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

View File

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

View File

@ -5,11 +5,11 @@ import kotlinx.serialization.Serializable
@Serializable
data class WalletItemRemote(
val id: Int?,
val id: Int,
val coinId: Int,
val userId: Int,
var count: Float,
)
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 dbCoinRepository: OfflineCoinRepository
) : CoinRepository {
override suspend fun insert(x: Coin) {
override suspend fun insert(vararg x: Coin) {
TODO("Not yet implemented")
}

View File

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

View File

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

View File

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

View File

@ -1,6 +1,11 @@
package com.example.testapp.data.room
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.repository.basic.CoinRepository
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.offline.OfflineCoinRepository
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.OfflineWalletItemRepository
@ -17,6 +23,11 @@ interface AppContainer {
val coinRepository: CoinRepository
val walletItemRepository: WalletItemRepository
val coinRestRepository: CoinRestRepository
val dealRestRepository: DealRestRepository
val userRestRepository: UserRestRepository
val walletItemRestRepository: WalletItemRestRepository
companion object {
const val TIMEOUT = 5000L
const val LIMIT = 10
@ -26,6 +37,9 @@ interface AppContainer {
class AppDataContainer(
private val context: Context
) : AppContainer {
private val remoteKeyRepository: OfflineRemoteKeyRepository by lazy {
OfflineRemoteKeyRepository(CryptoDealDb.getInstance(context).remoteKeysDao())
}
override val userRepository: UserRepository by lazy {
OfflineUserRepository(CryptoDealDb.getInstance(context).userDao())
}
@ -38,4 +52,34 @@ class AppDataContainer(
override val walletItemRepository: WalletItemRepository by lazy {
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")
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>
@Query("DELETE FROM deal")

View File

@ -1,17 +1,19 @@
package com.example.testapp.data.room.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.example.testapp.data.room.models.RemoteKeyType
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")
suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(remoteKey: List<RemoteKeys?>)
suspend fun insertAll(remoteKey: List<RemoteKeys>)
@Query("DELETE FROM remote_keys WHERE type = :type")
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.User
import com.example.testapp.data.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
@Dao
interface UserDao : IDao<User> {
@Query("select * from user")
fun getAll(): Flow<List<User>>
fun getAll(): List<User>
@Query("select * from user where user.id = :idUser")
fun getUserById(idUser: Int): User
@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")
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>
@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")
suspend fun deleteAll()

View File

@ -24,10 +24,10 @@ abstract class CryptoDealDb: RoomDatabase() {
abstract fun coinDao(): CoinDao;
abstract fun dealDao(): DealDao;
abstract fun walletItemDao(): WalletItemDao;
abstract fun RemoteKeysDao(): RemoteKeysDao;
abstract fun remoteKeysDao(): RemoteKeysDao;
companion object {
private const val DB_NAME: String = "crypto-deal7"
private const val DB_NAME: String = "crypto-deal13"
@Volatile
private var INSTANCE: CryptoDealDb? = null
@ -57,25 +57,25 @@ abstract class CryptoDealDb: RoomDatabase() {
coinDao.insert(c6)
coinDao.insert(c7)
val walletItemDao = database.walletItemDao();
val wi1 = WalletItem(0, 0, 0.5f);
val wi2 = WalletItem(1, 0, 0.6f);
val wi3 = WalletItem(3, 0, 0.7f);
val wi4 = WalletItem(0, 1, 1000f);
val wi5 = WalletItem(3, 1, 10f);
val wi6 = WalletItem(2, 1, 1f);
val wi7 = WalletItem(4, 0, 1.1f);
val wi8 = WalletItem(5, 0, 1.1f);
val wi9 = WalletItem(6, 0, 1.1f);
walletItemDao.insert(wi1);
walletItemDao.insert(wi2);
walletItemDao.insert(wi3);
walletItemDao.insert(wi4);
walletItemDao.insert(wi5);
walletItemDao.insert(wi6);
walletItemDao.insert(wi7);
walletItemDao.insert(wi8);
walletItemDao.insert(wi9);
// val walletItemDao = database.walletItemDao();
// val wi1 = WalletItem(0, 0, 0.5f);
// val wi2 = WalletItem(1, 0, 0.6f);
// val wi3 = WalletItem(3, 0, 0.7f);
// val wi4 = WalletItem(0, 1, 1000f);
// val wi5 = WalletItem(3, 1, 10f);
// val wi6 = WalletItem(2, 1, 1f);
// val wi7 = WalletItem(4, 0, 1.1f);
// val wi8 = WalletItem(5, 0, 1.1f);
// val wi9 = WalletItem(6, 0, 1.1f);
// walletItemDao.insert(wi1);
// walletItemDao.insert(wi2);
// walletItemDao.insert(wi3);
// walletItemDao.insert(wi4);
// walletItemDao.insert(wi5);
// walletItemDao.insert(wi6);
// walletItemDao.insert(wi7);
// walletItemDao.insert(wi8);
// walletItemDao.insert(wi9);
val dealDao = database.dealDao();
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?,
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.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(
primaryKeys = ["coinId", "userId"],
foreignKeys = [
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)
]
],
indices = [Index(value = ["coinId", "userId"])]
)
class WalletItem (
@PrimaryKey(autoGenerate = true)
val id: Int?,
@PrimaryKey(autoGenerate = true) val id: Int?,
val coinId: Int,
val userId: Int,
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 {
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)
}

View File

@ -9,7 +9,7 @@ class OfflineRemoteKeyRepository(private val remoteKeysDao: RemoteKeysDao) : Rem
override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
remoteKeysDao.getRemoteKeys(id, type)
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys?>) =
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
remoteKeysDao.insertAll(remoteKeys)
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.WalletItem
import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.Flow
class OfflineUserRepository(
private val userDao: UserDao
) : 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 getUserWallet(id: Int): Flow<List<WalletItem>> = userDao.getUserWallet(id)
override suspend fun getUserDeals(id: Int): Flow<List<Deal>> = userDao.getUserDeals(id)
override suspend fun getUserWallet(id: Int): List<WalletItem> = userDao.getUserWallet(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
), 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()
suspend fun insert(list: List<WalletItem>) = walletItemDao.insert(*list.toTypedArray())
}

View File

@ -1,7 +1,6 @@
package com.example.pmulabs.designElem
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.padding
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.Text
@ -21,7 +19,6 @@ 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.toUpperCase
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.NavDestination
@ -30,7 +27,6 @@ import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.example.testapp.navigate.BottomBarScreen
import java.util.Locale
@Composable
fun NavBar(navController: NavHostController){
@ -84,7 +80,7 @@ fun AddItem(
.clickable(onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = false
launchSingleTop = true
}
})
.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.compose.NavHost
import androidx.navigation.compose.composable
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.screensMobile.AccountPage
import com.example.testapp.screensMobile.CreateDeal
import com.example.testapp.screensMobile.DealList
import com.example.testapp.screensMobile.History
import com.example.testapp.screensMobile.ReportScreen
import com.example.testapp.screensMobile.Wallet
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.DealListViewModel
import com.example.testapp.viewModels.HistoryViewModel
import com.example.testapp.viewModels.ReportViewModel
import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.viewModels.WalletViewModel
@RequiresApi(34)
@ -29,6 +31,7 @@ fun HomeNavGraph(
dealListViewModel: DealListViewModel = viewModel(factory = AppViewModelProvider.Factory),
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory),
reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory),
sharedViewModel: SharedViewModel
) {
NavHost(
@ -72,5 +75,12 @@ fun HomeNavGraph(
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.composable
import androidx.navigation.navArgument
import com.example.testapp.designElem.SharedViewModel
import com.example.testapp.screensMobile.LoadScreen
import com.example.testapp.viewModels.AppViewModelProvider
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.HistoryViewModel
import com.example.testapp.viewModels.RegistrationScreenViewModel
import com.example.testapp.viewModels.ReportViewModel
import com.example.testapp.viewModels.SharedViewModel
import com.example.testapp.viewModels.WalletViewModel
const val USERID_ARGUMENT = "userId"
@ -32,6 +33,7 @@ fun RootNavigationGraph(
historyViewModel: HistoryViewModel = viewModel(factory = AppViewModelProvider.Factory),
registrationScreenViewModel: RegistrationScreenViewModel = viewModel(factory = AppViewModelProvider.Factory),
walletViewModel: WalletViewModel = viewModel(factory = AppViewModelProvider.Factory),
reportViewModel: ReportViewModel = viewModel(factory = AppViewModelProvider.Factory),
sharedViewModel: SharedViewModel
) {
NavHost(
@ -57,7 +59,8 @@ fun RootNavigationGraph(
dealListViewModel = dealListViewModel,
historyViewModel = historyViewModel,
walletViewModel = walletViewModel,
sharedViewModel = sharedViewModel
sharedViewModel = sharedViewModel,
reportViewModel = reportViewModel
)
}
}

View File

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

View File

@ -1,6 +1,8 @@
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
@ -17,17 +19,18 @@ import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape
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.runtime.Composable
import androidx.compose.runtime.collectAsState
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.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
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.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import com.example.testapp.graphs.AuthScreen
import com.example.testapp.R
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
@RequiresApi(Build.VERSION_CODES.O)
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun AccountPage(
@ -122,8 +126,7 @@ fun AccountPage(
y = 204.dp
)
) {
Property1Switch(modifier = Modifier.padding(vertical = 5.dp))
Property1Arrow(modifier = Modifier.padding(vertical = 5.dp))
Property1Arrow(modifier = Modifier.padding(vertical = 5.dp), navController)
}
Property1Clear(navController = navController)
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
fun Container(modifier: Modifier = Modifier, name: String) {
Column(
@ -231,7 +194,7 @@ fun Viewchecked(modifier: Modifier = Modifier) {
}
@Composable
fun Property1Arrow(modifier: Modifier = Modifier) {
fun Property1Arrow(modifier: Modifier = Modifier, navController: NavController) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically,
@ -243,19 +206,22 @@ fun Property1Arrow(modifier: Modifier = Modifier) {
top = 4.dp,
bottom = 4.dp
)
.clickable {
navController.navigate(route = BottomBarScreen.Report.route)
}
) {
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))
Icon(
Icons.Rounded.Fingerprint,
contentDescription = stringResource(id = R.string.app_name)
)
}
Text(
text = "Confirm Account",
text = "Report",
color = Color(0xff0b1f33),
lineHeight = 1.25.em,
style = TextStyle(
@ -275,12 +241,6 @@ fun Property1Clear(modifier: Modifier = Modifier, navController: NavController)
modifier = modifier
.fillMaxSize()
.clip(shape = RoundedCornerShape(10.dp))
.clickable {
navController.navigate(route = AuthScreen.Entry.route) {
popUpTo(navController.graph.findStartDestination().id)
launchSingleTop = true
}
}
.padding(
start = 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.lifecycle.viewmodel.compose.viewModel
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.Deal
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.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
import com.example.testapp.viewModels.SharedViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

View File

@ -43,7 +43,7 @@ import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.paging.LoadState
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.data.room.models.Coin
import com.example.testapp.data.room.models.Deal
@ -98,16 +98,16 @@ fun DealList(
}
deals.apply {
when{
loadState.refresh is LoadState.Loading -> {
item { CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(0.5f),
color = Color(0xff423a99)) }
}
loadState.append is LoadState.Loading -> {
item { CircularProgressIndicator(
modifier = Modifier.fillParentMaxSize(0.5f),
color = Color(0xff423a99)) }
}
// loadState.refresh is LoadState.Loading -> {
// item { CircularProgressIndicator(
// modifier = Modifier.fillParentMaxSize(0.5f),
// color = Color(0xff423a99)) }
// }
// loadState.append is LoadState.Loading -> {
// item { CircularProgressIndicator(
// modifier = Modifier.fillParentMaxSize(0.5f),
// color = Color(0xff423a99)) }
// }
loadState.refresh is LoadState.Error -> {
val err = deals.loadState.refresh as LoadState.Error
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.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
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.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
@ -34,6 +34,7 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
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.Deal
import com.example.testapp.viewModels.AppViewModelProvider
@ -53,26 +54,31 @@ fun History(
) {
val user by currentUserViewModel.user.collectAsState()
val id = user!!.id
historyViewModel.setArgument(id.toString());
val history by historyViewModel.deals.collectAsState()
historyViewModel.setArgument(id.toString())
val history = historyViewModel.deals.collectAsLazyPagingItems()
val coins by historyViewModel.coins.collectAsState()
Column(
LazyColumn(
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.Top),
horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = PaddingValues(bottom = 70.dp),
modifier = modifier
.requiredHeight(height = 720.dp)
.background(color = Color(0xfff4f7fb))
.padding(vertical = 20.dp)
.verticalScroll(rememberScrollState())
.fillMaxSize()
) {
PropertyHistory()
history.forEach { x ->
HistoryCard(
deal = x,
modifier = Modifier.padding(vertical = 5.dp, horizontal = 5.dp),
coins = coins
)
item {
PropertyHistory()
}
items(count = history.itemCount) {
val item = history[it]
if (item != null) {
HistoryCard(
deal = item,
modifier = Modifier.padding(vertical = 5.dp, horizontal = 5.dp),
coins = coins
)
}
}
}
}

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

View File

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

View File

@ -4,11 +4,12 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
class CurrentUserViewModel(private val userRepository: UserRepository) : ViewModel() {
val argument = MutableStateFlow<String?>(null)
private val argument = MutableStateFlow<String?>(null)
val id = MutableStateFlow<Int?>(null)
var user = MutableStateFlow<User?>(null)
@ -16,7 +17,7 @@ class CurrentUserViewModel(private val userRepository: UserRepository) : ViewMod
argument.value = arg
id.value = arg.toInt()
viewModelScope.launch {
viewModelScope.launch(Dispatchers.IO) {
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.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class DealCreateViewModel(
@ -36,12 +35,8 @@ class DealCreateViewModel(
init {
viewModelScope.launch(Dispatchers.IO) {
_coins.emit(
coinRepository.getAll().first()
)
_wallet.emit(
walletItemRepository.getAll().first()
)
_coins.emit(coinRepository.getAll())
_wallet.emit(walletItemRepository.getAll())
}
}

View File

@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
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.Deal
import com.example.testapp.data.room.models.WalletItem
@ -27,19 +28,20 @@ class DealListViewModel(
fun setupLists() {
viewModelScope.launch(Dispatchers.IO) {
coins.emit(coinRepository.getAll().first())
coins.emit(coinRepository.getAll())
deals.emit(dealRepository
.pagingData()
.cachedIn(viewModelScope)
.first())
.first()
.filter { it.date == null })
}
}
@RequiresApi(34)
fun submitDeal(deal: Deal, sellerId: Int, buyerId: Int) {
viewModelScope.launch {
val walletSeller: List<WalletItem> = walletItemRepository.getUserWallet(sellerId).first()
val walletBuyer: List<WalletItem> = walletItemRepository.getUserWallet(buyerId).first()
val walletSeller: List<WalletItem> = walletItemRepository.getUserWallet(sellerId)
val walletBuyer: List<WalletItem> = walletItemRepository.getUserWallet(buyerId)
val seller: WalletItem? = walletSeller.firstOrNull { x -> x.coinId == deal.sellerCoinId }
val buyer: WalletItem? = walletBuyer.firstOrNull { x -> x.coinId == deal.buyerId }
@ -54,7 +56,7 @@ class DealListViewModel(
}
// Case if need insert
else {
val item = WalletItem(deal.buyerCoinId, sellerId, deal.countBuy)
val item = WalletItem(null, deal.buyerCoinId, sellerId, deal.countBuy)
walletItemRepository.insert(item)
}
@ -67,7 +69,7 @@ class DealListViewModel(
}
// Case if need insert
else {
val item = WalletItem(deal.sellerCoinId, buyerId, deal.countSell)
val item = WalletItem(null, deal.sellerCoinId, buyerId, deal.countSell)
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.repository.basic.UserRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class EntryScreenViewModel(
@ -15,7 +14,7 @@ class EntryScreenViewModel(
fun setupList() {
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.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.Deal
import com.example.testapp.data.room.repository.basic.CoinRepository
@ -17,15 +20,26 @@ class HistoryViewModel(
) : ViewModel() {
val argument = MutableStateFlow<String?>(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())
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) {
argument.value = arg
id.value = arg.toInt()
viewModelScope.launch(Dispatchers.IO) {
deals.emit(dealRepository.getAll().first())
coins.emit(coinRepository.getAll().first())
deals.emit(dealRepository.pagingData().cachedIn(viewModelScope).first().filter {
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 com.example.testapp.data.room.models.User
import com.example.testapp.data.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class RegistrationScreenViewModel(private val userRepository: UserRepository) : ViewModel() {
@ -15,7 +14,7 @@ class RegistrationScreenViewModel(private val userRepository: UserRepository) :
fun setUserList() {
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.repository.basic.CoinRepository
import com.example.testapp.data.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
@ -17,17 +18,17 @@ class WalletViewModel(
private val walletItemRepository: WalletItemRepository,
private val coinRepository: CoinRepository
) : ViewModel() {
val argument = MutableStateFlow<String?>(null)
private val argument = MutableStateFlow<String?>(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 coins = MutableStateFlow<List<Coin>?>(emptyList())
fun setArgument(arg: String) {
argument.value = arg
id.value = arg.toInt()
viewModelScope.launch {
coins.emit(coinRepository.getAll().first())
viewModelScope.launch(Dispatchers.IO) {
coins.emit(coinRepository.getAll())
_wallet.emit(walletItemRepository
.pagingData(id.value!!)
.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>