Compare commits

..

3 Commits
l4 ... l5

Author SHA1 Message Date
cf49e1750b Upload reports 2023-12-20 11:58:06 +04:00
702cf2d259 Complete lab 5 2023-12-20 11:21:54 +04:00
9dcc14add5 add rest reps and mediators 2023-12-14 11:49:24 +04:00
83 changed files with 1761 additions and 541 deletions

View File

@ -1,8 +1,8 @@
package com.example.testapp
import android.app.Application
import com.example.testapp.room.AppContainer
import com.example.testapp.room.AppDataContainer
import com.example.testapp.data.room.AppContainer
import com.example.testapp.data.room.AppDataContainer
class CryptoDealApplication : Application() {
lateinit var container: AppContainer

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

@ -0,0 +1,135 @@
package com.example.testapp.data.api
import com.example.testapp.data.api.model.CoinRemote
import com.example.testapp.data.api.model.DealRemote
import com.example.testapp.data.api.model.UserRemote
import com.example.testapp.data.api.model.WalletItemRemote
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
interface UserRequests {
/**
* <i>User Request interface</i>
* */
@GET("users")
suspend fun getUsers(): List<UserRemote>
@GET("users/{id}")
suspend fun getUserById(@Path("id") id: Int): UserRemote
@POST("users")
suspend fun insert(@Body obj: UserRemote): UserRemote
@PUT("users/{id}")
suspend fun update(@Path("id") id: Int, @Body obj: UserRemote): UserRemote
@DELETE("users/{id}")
suspend fun deleteUser(@Path("id") id: Int): UserRemote
@GET("user_wallet/{id}")
suspend fun getUserWallet(@Path("id") id: Int): List<WalletItemRemote>
@GET("user_deal/{id}")
suspend fun getUserDeal(@Path("id") id: Int): List<DealRemote>
}
interface DealRequests {
/**
* <i>Deal Request interface</i>
*/
@GET("deals")
suspend fun getDeals(): List<DealRemote>
@GET("deals/{id}")
suspend fun getDealById(@Path("id") id: Int): DealRemote
@POST("deals")
suspend fun insert(@Body obj: DealRemote): DealRemote
@PUT("deals/{id}")
suspend fun update(@Path("id") id: Int, @Body obj: DealRemote): DealRemote
@DELETE("deals/{id}")
suspend fun deleteDeal(@Path("id") id: Int): DealRemote
@GET("deals")
suspend fun pagingDeals(
@Query("_page") page: Int,
@Query("_limit") limit: Int
): List<DealRemote>
@POST("complete_deal}")
suspend fun completeDeal(
@Query("dealId") dealId: Int,
@Query("sellerId")sellerId: Int,
@Query("buyerId") buyerId: Int,
): Boolean
}
interface CoinRequests {
/**
* <i>Coin Request interface</i>
*/
@GET("coins")
suspend fun getCoins(): List<CoinRemote>
}
interface WalletItemRequests {
/**
* <i>Wallet Item Request interface</i>
*/
@GET("wal_item")
suspend fun getWalletItems(): List<WalletItemRemote>
@POST("wal_item")
suspend fun insert(@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("wal_item")
suspend fun pagingWalletItems(
@Query("_page") page: Int,
@Query("_limit") limit: Int
): List<WalletItemRemote>
}
interface CryptoDealService : UserRequests, DealRequests, CoinRequests, WalletItemRequests {
companion object {
private const val BASE_URL = "http://172.20.10.13:8079/"
@Volatile
private var INSTANCE: CryptoDealService? = null
fun getInstance(): CryptoDealService {
return INSTANCE ?: synchronized(this) {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
.build()
.create(CryptoDealService::class.java)
.also { INSTANCE = it }
}
}
}
}

View File

@ -0,0 +1,103 @@
package com.example.testapp.data.api.mediator
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.model.toDeal
import com.example.testapp.data.room.database.CryptoDealDb
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.RemoteKeyType
import com.example.testapp.data.room.models.RemoteKeys
import com.example.testapp.data.room.repository.offline.OfflineDealRepository
import com.example.testapp.data.room.repository.offline.OfflineRemoteKeyRepository
import okio.IOException
import retrofit2.HttpException
@OptIn(ExperimentalPagingApi::class)
class DealRemoteMediator(
private val service: CryptoDealService,
private val dbDealRepository: OfflineDealRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: CryptoDealDb
) : RemoteMediator<Int, Deal>() {
override suspend fun initialize(): InitializeAction {
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
override suspend fun load(loadType: LoadType, state: PagingState<Int, Deal>): MediatorResult {
val page = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
remoteKeys?.nextKey?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
remoteKeys?.prevKey
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastItem(state)
remoteKeys?.nextKey
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
}
try {
val deals = service.pagingDeals(page, state.config.pageSize).map { it.toDeal() }
val endOfPaginationReached = deals.isEmpty()
database.withTransaction {
if (loadType == LoadType.REFRESH) {
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.DEAL)
dbDealRepository.clearData()
}
val prevKey = if (page == 1) null else page - 1
val nextKey = if (endOfPaginationReached) null else page + 1
val keys = deals.map {
RemoteKeys(
entityId = it.id!!,
type = RemoteKeyType.DEAL,
prevKey = prevKey,
nextKey = nextKey
)
}
dbRemoteKeyRepository.createRemoteKeys(keys)
dbDealRepository.insert(deals)
}
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (exception: IOException) {
return MediatorResult.Error(exception)
} catch (exception: HttpException) {
return MediatorResult.Error(exception)
}
}
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Deal>): RemoteKeys? {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { art ->
art.id?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.DEAL) }
}
}
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Deal>): RemoteKeys? {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { art ->
art.id?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.DEAL) }
}
}
private suspend fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, Deal>
): RemoteKeys? {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.id?.let { artid ->
dbRemoteKeyRepository.getAllRemoteKeys(artid, RemoteKeyType.DEAL)
}
}
}
}

View File

@ -0,0 +1,103 @@
package com.example.testapp.data.api.mediator
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.model.toWalletItem
import com.example.testapp.data.room.database.CryptoDealDb
import com.example.testapp.data.room.models.RemoteKeyType
import com.example.testapp.data.room.models.RemoteKeys
import com.example.testapp.data.room.models.WalletItem
import com.example.testapp.data.room.repository.offline.OfflineRemoteKeyRepository
import com.example.testapp.data.room.repository.offline.OfflineWalletItemRepository
import okio.IOException
import retrofit2.HttpException
@OptIn(ExperimentalPagingApi::class)
class WalletItemRemoteMediator(
private val service: CryptoDealService,
private val dbWalletItemRepository: OfflineWalletItemRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: CryptoDealDb
) : RemoteMediator<Int, WalletItem>() {
override suspend fun initialize(): InitializeAction {
return InitializeAction.LAUNCH_INITIAL_REFRESH
}
override suspend fun load(loadType: LoadType, state: PagingState<Int, WalletItem>): MediatorResult {
val page = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
remoteKeys?.nextKey?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
remoteKeys?.prevKey
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastItem(state)
remoteKeys?.nextKey
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
}
try {
val articles = service.pagingWalletItems(page, state.config.pageSize).map { it.toWalletItem() }
val endOfPaginationReached = articles.isEmpty()
database.withTransaction {
if (loadType == LoadType.REFRESH) {
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.WALLETITEM)
dbWalletItemRepository.clearData()
}
val prevKey = if (page == 1) null else page - 1
val nextKey = if (endOfPaginationReached) null else page + 1
val keys = articles.map {
RemoteKeys(
entityId = it.id!!,
type = RemoteKeyType.WALLETITEM,
prevKey = prevKey,
nextKey = nextKey
)
}
dbRemoteKeyRepository.createRemoteKeys(keys)
dbWalletItemRepository.insert(articles)
}
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
} catch (exception: IOException) {
return MediatorResult.Error(exception)
} catch (exception: HttpException) {
return MediatorResult.Error(exception)
}
}
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, WalletItem>): RemoteKeys? {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.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 { item ->
item.id!!.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.WALLETITEM) }
}
}
private suspend fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, WalletItem>
): RemoteKeys? {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.id?.let { itemId ->
dbRemoteKeyRepository.getAllRemoteKeys(itemId, RemoteKeyType.WALLETITEM)
}
}
}
}

View File

@ -0,0 +1,13 @@
package com.example.testapp.data.api.model
import com.example.testapp.data.room.models.Coin
import kotlinx.serialization.Serializable
@Serializable
data class CoinRemote(
val id: Int?,
val name: String
)
fun CoinRemote.toCoin(): Coin = Coin(id, name)
fun Coin.toRemote(): CoinRemote = CoinRemote(id, name)

View File

@ -0,0 +1,44 @@
package com.example.testapp.data.api.model
import com.example.testapp.data.room.models.Deal
import kotlinx.serialization.Serializable
@Serializable
data class DealRemote(
val id: Int?,
var sellerId: Int?,
val buyerId: Int?,
val sellerCoinId: Int,
val buyerCoinId: Int,
val countSell: Float,
val countBuy: Float,
val operation: String,
var date: Long?,
val tip: String
)
fun DealRemote.toDeal(): Deal = Deal(
id,
sellerId,
buyerId,
sellerCoinId,
buyerCoinId,
countSell,
countBuy,
operation,
date,
tip
)
fun Deal.toRemote(): DealRemote = DealRemote(
id,
sellerId,
buyerId,
sellerCoinId,
buyerCoinId,
countSell,
countBuy,
operation,
date,
tip
)

View File

@ -0,0 +1,14 @@
package com.example.testapp.data.api.model
import com.example.testapp.data.room.models.User
import kotlinx.serialization.Serializable
@Serializable
data class UserRemote(
val id: Int? = 0,
var email: String = "",
var password: String = ""
)
fun UserRemote.toUser(): User = User(id, email, password)
fun User.toRemote(): UserRemote = UserRemote(id, email, password)

View File

@ -0,0 +1,15 @@
package com.example.testapp.data.api.model
import com.example.testapp.data.room.models.WalletItem
import kotlinx.serialization.Serializable
@Serializable
data class WalletItemRemote(
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)

View File

@ -0,0 +1,46 @@
package com.example.testapp.data.api.repository
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.model.toCoin
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.repository.basic.CoinRepository
import com.example.testapp.data.room.repository.offline.OfflineCoinRepository
class CoinRestRepository(
private val service: CryptoDealService,
private val dbCoinRepository: OfflineCoinRepository
) : CoinRepository {
override suspend fun insert(vararg x: Coin) {
TODO("Not yet implemented")
}
override suspend fun update(x: Coin) {
TODO("Not yet implemented")
}
override suspend fun delete(x: Coin) {
TODO("Not yet implemented")
}
override suspend fun getById(id: Int): Coin {
TODO("Not yet implemented")
}
override suspend fun getAll(): List<Coin> {
val exists = dbCoinRepository.getAll().associateBy { it.id }.toMutableMap()
service.getCoins()
.map { it.toCoin() }
.forEach { item ->
val existUser = exists[item.id]
if (existUser == null) {
dbCoinRepository.insert(item)
} else if (existUser != item) {
dbCoinRepository.update(item)
}
exists[item.id] = item
}
return exists.map { it.value }.sortedBy { it.id }
}
}

View File

@ -0,0 +1,109 @@
package com.example.testapp.data.api.repository
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.mediator.DealRemoteMediator
import com.example.testapp.data.api.model.toDeal
import com.example.testapp.data.api.model.toRemote
import com.example.testapp.data.room.AppContainer
import com.example.testapp.data.room.database.CryptoDealDb
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.repository.basic.DealRepository
import com.example.testapp.data.room.repository.offline.OfflineDealRepository
import com.example.testapp.data.room.repository.offline.OfflineRemoteKeyRepository
import kotlinx.coroutines.flow.Flow
class DealRestRepository(
private val service: CryptoDealService,
private val dbDealRepository: OfflineDealRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: CryptoDealDb
) : DealRepository {
override suspend fun getUserDeals(id: Int): List<Deal> {
val exists = dbDealRepository.getAll().associateBy { it.id }.toMutableMap()
service.getDeals()
.map { it.toDeal() }
.forEach { item ->
val existUser = exists[item.id]
if (existUser == null) {
dbDealRepository.insert(item)
} else if (existUser != item) {
dbDealRepository.update(item)
}
exists[item.id] = item
}
return exists.map { it.value }.sortedBy { it.id }
}
override suspend fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean {
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() }
@OptIn(ExperimentalPagingApi::class)
return Pager(
config = PagingConfig(
pageSize = AppContainer.LIMIT,
enablePlaceholders = false
),
remoteMediator = DealRemoteMediator(
service,
dbDealRepository,
dbRemoteKeyRepository,
database
),
pagingSourceFactory = pagingSourceFactory
).flow
}
override fun getAllPagingData(): PagingSource<Int, Deal> {
TODO("Not yet implemented")
}
override suspend fun insert(vararg x: Deal) {
x.forEach {y -> service.insert(y.toRemote()) }
}
override suspend fun update(x: Deal) {
x.id?.let { service.update(it, x.toRemote()) }
}
override suspend fun delete(x: Deal) {
x.id?.let { service.deleteDeal(it) }
}
override suspend fun getById(id: Int): Deal {
return service.getDealById(id).toDeal()
}
override suspend fun getAll(): List<Deal> {
val exists = dbDealRepository.getAll().associateBy { it.id }.toMutableMap()
service.getDeals()
.map { it.toDeal() }
.forEach { item ->
val existUser = exists[item.id]
if (existUser == null) {
dbDealRepository.insert(item)
} else if (existUser != item) {
dbDealRepository.update(item)
}
exists[item.id] = item
}
return exists.map { it.value }.sortedBy { it.id }
}
}

View File

@ -0,0 +1,99 @@
package com.example.testapp.data.api.repository
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.model.toDeal
import com.example.testapp.data.api.model.toRemote
import com.example.testapp.data.api.model.toUser
import com.example.testapp.data.api.model.toWalletItem
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.DealRepository
import com.example.testapp.data.room.repository.basic.UserRepository
import com.example.testapp.data.room.repository.basic.WalletItemRepository
class UserRestRepository(
private val service: CryptoDealService,
private val dbUserRepository: UserRepository,
private val dbDealRepository: DealRepository,
private val dbWalletItemRepository: WalletItemRepository
) : UserRepository {
override suspend fun getUserWallet(id: Int): List<WalletItem> {
val existArticles = dbUserRepository.getUserWallet(id)
.associateBy { it.userId * 10 + it.coinId }.toMutableMap()
service.getUserWallet(id)
.map { it.toWalletItem() }
.forEach { walletItem ->
val pseudoId = walletItem.userId * 10 + walletItem.coinId
if (walletItem.userId == id) {
val existArt = existArticles[pseudoId]
if (existArt == null) {
dbWalletItemRepository.insert(walletItem)
} else if (existArt != walletItem) {
dbWalletItemRepository.update(walletItem)
}
existArticles[pseudoId] = walletItem
}
}
return existArticles.map { it.value }.sortedBy { it.count }
}
override suspend fun getUserDeals(id: Int): List<Deal> {
val existArticles = dbUserRepository.getUserDeals(id)
.associateBy { it.id }.toMutableMap()
service.getUserDeal(id)
.map { it.toDeal() }
.forEach { deal ->
if (deal.buyerId == id) {
val existArt = existArticles[deal.id]
if (existArt == null) {
dbDealRepository.insert(deal)
} else if (existArt != deal) {
dbDealRepository.update(deal)
}
existArticles[deal.id] = deal
}
}
return existArticles.map { it.value }.sortedBy { it.id }
}
override suspend fun insert(vararg x: User) {
x.forEach { user ->
service.insert(user.toRemote())
}
}
override suspend fun update(x: User) {
x.id?.let { service.update(it, x.toRemote()) }
}
override suspend fun delete(x: User) {
x.id?.let { service.deleteUser(it) }
}
override suspend fun getById(id: Int): User {
return service.getUserById(id).toUser()
}
override suspend fun getAll(): List<User> {
val existUsers = dbUserRepository.getAll().associateBy { it.id }.toMutableMap()
service.getUsers()
.map { it.toUser() }
.forEach { user ->
val existUser = existUsers[user.id]
if (existUser == null) {
dbUserRepository.insert(user)
} else if (existUser != user) {
dbUserRepository.update(user)
}
existUsers[user.id] = user
}
return existUsers.map { it.value }.sortedBy { it.id }
}
}

View File

@ -0,0 +1,90 @@
package com.example.testapp.data.api.repository
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.testapp.data.api.CryptoDealService
import com.example.testapp.data.api.mediator.WalletItemRemoteMediator
import com.example.testapp.data.api.model.toRemote
import com.example.testapp.data.api.model.toWalletItem
import com.example.testapp.data.room.AppContainer
import com.example.testapp.data.room.database.CryptoDealDb
import com.example.testapp.data.room.models.WalletItem
import com.example.testapp.data.room.repository.basic.WalletItemRepository
import com.example.testapp.data.room.repository.offline.OfflineRemoteKeyRepository
import com.example.testapp.data.room.repository.offline.OfflineWalletItemRepository
import kotlinx.coroutines.flow.Flow
class WalletItemRestRepository(
private val service: CryptoDealService,
private val dbWalletItemRepository: OfflineWalletItemRepository,
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
private val database: CryptoDealDb
) : WalletItemRepository {
override fun getUserWallet(id: Int): List<WalletItem> {
return dbWalletItemRepository.getUserWallet(id)
}
override fun pagingData(id: Int): Flow<PagingData<WalletItem>> {
val pagingSourceFactory = { dbWalletItemRepository.getWalletItemsPaging(id) }
@OptIn(ExperimentalPagingApi::class)
return Pager(
config = PagingConfig(
pageSize = AppContainer.LIMIT,
enablePlaceholders = false
),
remoteMediator = WalletItemRemoteMediator(
service,
dbWalletItemRepository,
dbRemoteKeyRepository,
database
),
pagingSourceFactory = pagingSourceFactory
).flow
}
override fun getWalletItemsPaging(id: Int): PagingSource<Int, WalletItem> {
TODO("Not yet implemented")
}
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.id!!, x.toRemote())
}
override suspend fun delete(x: WalletItem) {
x.id.let { service.deleteWalletItem(it!!) }
}
override suspend fun getById(id: Int): WalletItem {
TODO("Not yet implemented")
}
override suspend fun getAll(): List<WalletItem> {
val exists = dbWalletItemRepository.getAll().associateBy { it.id }.toMutableMap()
service.getWalletItems()
.map { it.toWalletItem() }
.forEach { item ->
val existUser = exists[item.id]
if (existUser == null) {
dbWalletItemRepository.insert(item)
} else if (existUser != item) {
dbWalletItemRepository.update(item)
}
exists[item.id] = item
}
return exists.map { it.value }.sortedBy { it.id }
}
}

View File

@ -0,0 +1,85 @@
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
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
interface AppContainer {
val userRepository: UserRepository
val dealRepository: DealRepository
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
}
}
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())
}
override val dealRepository: DealRepository by lazy {
OfflineDealRepository(CryptoDealDb.getInstance(context).dealDao())
}
override val coinRepository: CoinRepository by lazy {
OfflineCoinRepository(CryptoDealDb.getInstance(context).coinDao())
}
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

@ -0,0 +1,11 @@
package com.example.testapp.data.room.dao
import androidx.room.Dao
import androidx.room.Query
import com.example.testapp.data.room.models.Coin
@Dao
interface CoinDao : IDao<Coin> {
@Query("select * from coin")
fun getAll(): List<Coin>
}

View File

@ -1,9 +1,9 @@
package com.example.testapp.room.dao
package com.example.testapp.data.room.dao
import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Query
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.data.room.models.Deal
import kotlinx.coroutines.flow.Flow
@Dao
@ -19,4 +19,13 @@ 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.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")
suspend fun deleteAll()
}

View File

@ -1,4 +1,4 @@
package com.example.testapp.room.dao
package com.example.testapp.data.room.dao
import androidx.room.Dao
import androidx.room.Delete
@ -8,7 +8,7 @@ import androidx.room.Update
@Dao
interface IDao<T> {
@Insert
suspend fun insert(obj: T)
suspend fun insert(vararg obj: T)
@Update
suspend fun update(obj: T)

View File

@ -0,0 +1,20 @@
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
@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>)
@Query("DELETE FROM remote_keys WHERE type = :type")
suspend fun clearRemoteKeys(type: RemoteKeyType)
}

View File

@ -1,23 +1,22 @@
package com.example.testapp.room.dao
package com.example.testapp.data.room.dao
import androidx.room.Dao
import androidx.room.Query
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.models.WalletItem
@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

@ -0,0 +1,24 @@
package com.example.testapp.data.room.dao
import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Query
import com.example.testapp.data.room.models.WalletItem
@Dao
interface WalletItemDao : IDao<WalletItem> {
@Query("select * from walletitem")
fun getAll(): List<WalletItem>
@Query("select * from walletitem where walletitem.userId = :id ORDER BY walletitem.coinId DESC LIMIT :limit OFFSET :offset")
fun getAll(limit: Int, offset: Int, id: Int): List<WalletItem>
@Query("select * from walletitem where walletitem.userId = :id")
fun getUserWallet(id: Int): List<WalletItem>
@Query("SELECT * FROM walletitem where walletitem.userId = :id ORDER BY walletitem.coinId ASC")
fun getWallet(id: Int): PagingSource<Int, WalletItem>
@Query("DELETE FROM walletitem")
suspend fun deleteAll()
}

View File

@ -1,18 +1,22 @@
package com.example.testapp.room.database
package com.example.testapp.data.room.database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.testapp.room.dao.*
import com.example.testapp.room.models.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import com.example.testapp.data.room.dao.CoinDao
import com.example.testapp.data.room.dao.DealDao
import com.example.testapp.data.room.dao.RemoteKeysDao
import com.example.testapp.data.room.dao.UserDao
import com.example.testapp.data.room.dao.WalletItemDao
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.RemoteKeys
import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.models.WalletItem
@Database(
entities = [User::class, Deal::class, Coin::class, WalletItem::class],
entities = [User::class, Deal::class, Coin::class, WalletItem::class, RemoteKeys::class],
version = 2,
exportSchema = false)
abstract class CryptoDealDb: RoomDatabase() {
@ -20,9 +24,10 @@ abstract class CryptoDealDb: RoomDatabase() {
abstract fun coinDao(): CoinDao;
abstract fun dealDao(): DealDao;
abstract fun walletItemDao(): WalletItemDao;
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
@ -52,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")
@ -91,14 +96,14 @@ abstract class CryptoDealDb: RoomDatabase() {
CryptoDealDb::class.java,
DB_NAME
)
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
CoroutineScope(Dispatchers.IO).launch {
populateDatabase()
}
}
})
// .addCallback(object : Callback() {
// override fun onCreate(db: SupportSQLiteDatabase) {
// super.onCreate(db)
// CoroutineScope(Dispatchers.IO).launch {
// populateDatabase()
// }
// }
// })
.allowMainThreadQueries()
.build()
.also { INSTANCE = it }

View File

@ -1,4 +1,4 @@
package com.example.testapp.room.models
package com.example.testapp.data.room.models
import androidx.room.ColumnInfo
import androidx.room.Entity

View File

@ -1,8 +1,7 @@
package com.example.testapp.room.models
package com.example.testapp.data.room.models
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.time.LocalDateTime
@Entity
class Deal (
@ -18,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

@ -0,0 +1,26 @@
package com.example.testapp.data.room.models
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverter
import androidx.room.TypeConverters
enum class RemoteKeyType(private val type: String) {
DEAL(Deal::class.simpleName ?: "Deal"),
WALLETITEM(WalletItem::class.simpleName ?: "WalletItem");
@TypeConverter
fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value }
@TypeConverter
fun fromRemoteKeyType(value: RemoteKeyType) = value.type
}
@Entity(tableName = "remote_keys")
data class RemoteKeys(
@PrimaryKey val entityId: Int,
@TypeConverters(RemoteKeyType::class)
val type: RemoteKeyType,
val prevKey: Int?,
val nextKey: Int?
)

View File

@ -1,4 +1,4 @@
package com.example.testapp.room.models
package com.example.testapp.data.room.models
import androidx.room.ColumnInfo
import androidx.room.Entity

View File

@ -1,17 +1,29 @@
package com.example.testapp.room.models
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?,
val coinId: Int,
val userId: Int,
var count: Float
)
var count: 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

@ -1,10 +1,9 @@
package com.example.testapp.room.pagination
package com.example.testapp.data.room.pagination
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.example.testapp.room.dao.DealDao
import com.example.testapp.room.models.Deal
import com.example.testapp.data.room.dao.DealDao
import com.example.testapp.data.room.models.Deal
import kotlinx.coroutines.delay
class DealPagination(

View File

@ -1,11 +1,10 @@
package com.example.testapp.room.pagination
package com.example.testapp.data.room.pagination
import android.util.Log
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.example.testapp.room.dao.WalletItemDao
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.WalletItemRepository
import com.example.testapp.data.room.dao.WalletItemDao
import com.example.testapp.data.room.models.WalletItem
import kotlinx.coroutines.delay
class WalletPagination(

View File

@ -0,0 +1,6 @@
package com.example.testapp.data.room.repository.basic
import com.example.testapp.data.room.models.Coin
interface CoinRepository : IRepository<Coin> {
}

View File

@ -0,0 +1,14 @@
package com.example.testapp.data.room.repository.basic
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.testapp.data.room.models.Deal
import kotlinx.coroutines.flow.Flow
interface DealRepository : IRepository<Deal> {
suspend fun getUserDeals(id: Int): List<Deal>
suspend fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean
suspend fun clearData()
fun pagingData(): Flow<PagingData<Deal>>
fun getAllPagingData(): PagingSource<Int, Deal>
}

View File

@ -0,0 +1,9 @@
package com.example.testapp.data.room.repository.basic
interface IRepository<T> {
suspend fun insert(vararg x: T)
suspend fun update(x: T)
suspend fun delete(x: T)
suspend fun getById(id: Int): T
suspend fun getAll(): List<T>
}

View File

@ -0,0 +1,10 @@
package com.example.testapp.data.room.repository.basic
import com.example.testapp.data.room.models.RemoteKeyType
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 deleteRemoteKey(type: RemoteKeyType)
}

View File

@ -0,0 +1,10 @@
package com.example.testapp.data.room.repository.basic
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.models.WalletItem
interface UserRepository : IRepository<User> {
suspend fun getUserWallet(id: Int): List<WalletItem>
suspend fun getUserDeals(id: Int): List<Deal>
}

View File

@ -0,0 +1,13 @@
package com.example.testapp.data.room.repository.basic
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.testapp.data.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
interface WalletItemRepository : IRepository<WalletItem> {
fun getUserWallet(id: Int): List<WalletItem>
fun pagingData(id: Int): Flow<PagingData<WalletItem>>
fun getWalletItemsPaging(id: Int): PagingSource<Int, WalletItem>
suspend fun clearData()
}

View File

@ -0,0 +1,12 @@
package com.example.testapp.data.room.repository.offline
import com.example.testapp.data.room.dao.CoinDao
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.repository.basic.CoinRepository
class OfflineCoinRepository(
private val coinDao: CoinDao
) : OfflineRepository<Coin>(coinDao), CoinRepository {
override suspend fun getAll(): List<Coin> = coinDao.getAll()
override suspend fun getById(id: Int): Coin = throw NotImplementedError()
}

View File

@ -0,0 +1,33 @@
package com.example.testapp.data.room.repository.offline
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.testapp.data.room.dao.DealDao
import com.example.testapp.data.room.models.Deal
import com.example.testapp.data.room.pagination.DealPagination
import com.example.testapp.data.room.repository.basic.DealRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
class OfflineDealRepository(
private val dealDao: DealDao
) : OfflineRepository<Deal>(dealDao), DealRepository {
override suspend fun getAll(): List<Deal> = dealDao.getAll().first()
override suspend fun getById(id: Int): Deal = dealDao.getById(id);
override suspend fun getUserDeals(id: Int): List<Deal> = dealDao.getUserDeals(id).first()
override suspend fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean {
return true;
}
override suspend fun clearData() = dealDao.deleteAll()
override fun pagingData(): Flow<PagingData<Deal>> = Pager(config = PagingConfig(
pageSize = 4, jumpThreshold = 4, initialLoadSize = 4
), pagingSourceFactory = { DealPagination(dealDao) }, initialKey = 1).flow
override fun getAllPagingData() = dealDao.getDeals()
suspend fun insert(list: List<Deal>) = dealDao.insert(*list.toTypedArray())
}

View File

@ -0,0 +1,17 @@
package com.example.testapp.data.room.repository.offline
import com.example.testapp.data.room.dao.RemoteKeysDao
import com.example.testapp.data.room.models.RemoteKeyType
import com.example.testapp.data.room.models.RemoteKeys
import com.example.testapp.data.room.repository.basic.RemoteKeyRepository
class OfflineRemoteKeyRepository(private val remoteKeysDao: RemoteKeysDao) : RemoteKeyRepository {
override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
remoteKeysDao.getRemoteKeys(id, type)
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
remoteKeysDao.insertAll(remoteKeys)
override suspend fun deleteRemoteKey(type: RemoteKeyType) =
remoteKeysDao.clearRemoteKeys(type)
}

View File

@ -0,0 +1,12 @@
package com.example.testapp.data.room.repository.offline
import com.example.testapp.data.room.dao.IDao
import com.example.testapp.data.room.repository.basic.IRepository
abstract class OfflineRepository<T> (
private val dao: IDao<T>
) : IRepository<T> {
override suspend fun insert(vararg x: T) = dao.insert(*x)
override suspend fun update(x: T) = dao.update(x)
override suspend fun delete(x: T) = dao.delete(x)
}

View File

@ -0,0 +1,16 @@
package com.example.testapp.data.room.repository.offline
import com.example.testapp.data.room.dao.UserDao
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
class OfflineUserRepository(
private val userDao: UserDao
) : OfflineRepository<User>(userDao), UserRepository {
override suspend fun getAll(): List<User> = userDao.getAll()
override suspend fun getById(id: Int): User = userDao.getUserById(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

@ -0,0 +1,27 @@
package com.example.testapp.data.room.repository.offline
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.example.testapp.data.room.dao.WalletItemDao
import com.example.testapp.data.room.models.WalletItem
import com.example.testapp.data.room.pagination.WalletPagination
import com.example.testapp.data.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.flow.Flow
class OfflineWalletItemRepository(
private val walletItemDao: WalletItemDao
) : OfflineRepository<WalletItem>(walletItemDao), WalletItemRepository {
override fun getUserWallet(id: Int): List<WalletItem> = walletItemDao.getUserWallet(id)
override suspend fun getAll(): List<WalletItem> = walletItemDao.getAll()
override suspend fun getById(id: Int): WalletItem = throw NotImplementedError()
override fun pagingData(id: Int): Flow<PagingData<WalletItem>> = Pager(config = PagingConfig(
pageSize = 10, jumpThreshold = 10, initialLoadSize = 10
), pagingSourceFactory = { WalletPagination(walletItemDao, id) }, initialKey = 1).flow
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

@ -32,8 +32,8 @@ 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 com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal
@Composable
fun DealItem(modifier: Modifier = Modifier, deal: Deal, coins: List<Coin>) {

View File

@ -18,8 +18,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
@ -27,7 +25,7 @@ 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 com.example.testapp.room.models.Coin
import com.example.testapp.data.room.models.Coin
@Composable
fun ListItem(modifier: Modifier = Modifier, coin : Coin, count: Float) {

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,40 +0,0 @@
package com.example.testapp.room
import android.content.Context
import com.example.testapp.room.database.CryptoDealDb
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import com.example.testapp.room.repository.basic.UserRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
import com.example.testapp.room.repository.offline.OfflineCoinRepository
import com.example.testapp.room.repository.offline.OfflineDealRepository
import com.example.testapp.room.repository.offline.OfflineUserRepository
import com.example.testapp.room.repository.offline.OfflineWalletItemRepository
interface AppContainer {
val userRepository: UserRepository
val dealRepository: DealRepository
val coinRepository: CoinRepository
val walletItemRepository: WalletItemRepository
}
class AppDataContainer(
private val context: Context
) : AppContainer {
companion object {
const val TIMEOUT = 5000L
}
override val userRepository: UserRepository by lazy {
OfflineUserRepository(CryptoDealDb.getInstance(context).userDao())
}
override val dealRepository: DealRepository by lazy {
OfflineDealRepository(CryptoDealDb.getInstance(context).dealDao())
}
override val coinRepository: CoinRepository by lazy {
OfflineCoinRepository(CryptoDealDb.getInstance(context).coinDao())
}
override val walletItemRepository: WalletItemRepository by lazy {
OfflineWalletItemRepository(CryptoDealDb.getInstance(context).walletItemDao())
}
}

View File

@ -1,12 +0,0 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Query
import com.example.testapp.room.models.Coin
import kotlinx.coroutines.flow.Flow
@Dao
interface CoinDao : IDao<Coin> {
@Query("select * from coin")
fun getAll(): Flow<List<Coin>>
}

View File

@ -1,19 +0,0 @@
package com.example.testapp.room.dao
import androidx.room.Dao
import androidx.room.Query
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
@Dao
interface WalletItemDao : IDao<WalletItem> {
@Query("select * from walletitem")
fun getAll(): Flow<List<WalletItem>>
@Query("select * from walletitem where walletitem.userId = :id ORDER BY walletitem.coinId DESC LIMIT :limit OFFSET :offset")
fun getAll(limit: Int, offset: Int, id: Int): List<WalletItem>
@Query("select * from walletitem where walletitem.userId = :id")
fun getUserWallet(id: Int): Flow<List<WalletItem>>
}

View File

@ -1,6 +0,0 @@
package com.example.testapp.room.repository.basic
import com.example.testapp.room.models.Coin
interface CoinRepository : IRepository<Coin> {
}

View File

@ -1,12 +0,0 @@
package com.example.testapp.room.repository.basic
import androidx.paging.PagingData
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
interface DealRepository : IRepository<Deal> {
fun getUserDeals(id: Int): Flow<List<Deal>>
fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean
fun pagingData(): Flow<PagingData<Deal>>
}

View File

@ -1,11 +0,0 @@
package com.example.testapp.room.repository.basic
import kotlinx.coroutines.flow.Flow
interface IRepository<T> {
suspend fun insert(x: T)
suspend fun update(x: T)
suspend fun delete(x: T)
fun getById(id: Int): T
fun getAll(): Flow<List<T>>
}

View File

@ -1,11 +0,0 @@
package com.example.testapp.room.repository.basic
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.User
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
interface UserRepository : IRepository<User> {
fun getUserWallet(id: Int): Flow<List<WalletItem>>
fun getUserDeals(id: Int): Flow<List<Deal>>
}

View File

@ -1,13 +0,0 @@
package com.example.testapp.room.repository.basic
import androidx.lifecycle.LiveData
import androidx.paging.PagingData
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import kotlinx.coroutines.flow.Flow
interface WalletItemRepository : IRepository<WalletItem> {
fun getUserWallet(id: Int): Flow<List<WalletItem>>
fun pagingData(id: Int): Flow<PagingData<WalletItem>>
fun pagingDataTest(id: Int): LiveData<PagingData<WalletItem>>
}

View File

@ -1,20 +0,0 @@
package com.example.testapp.room.repository.offline
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.testapp.room.dao.CoinDao
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.pagination.DealPagination
import com.example.testapp.room.pagination.WalletPagination
import com.example.testapp.room.repository.basic.CoinRepository
import kotlinx.coroutines.flow.Flow
class OfflineCoinRepository(
private val coinDao: CoinDao
) : OfflineRepository<Coin>(coinDao), CoinRepository {
override fun getAll(): Flow<List<Coin>> = coinDao.getAll()
override fun getById(id: Int): Coin = throw NotImplementedError()
}

View File

@ -1,28 +0,0 @@
package com.example.testapp.room.repository.offline
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.testapp.room.dao.DealDao
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.pagination.DealPagination
import com.example.testapp.room.pagination.WalletPagination
import com.example.testapp.room.repository.basic.DealRepository
import kotlinx.coroutines.flow.Flow
class OfflineDealRepository(
private val dealDao: DealDao
) : OfflineRepository<Deal>(dealDao), DealRepository {
override fun getAll(): Flow<List<Deal>> = dealDao.getAll()
override fun getById(id: Int): Deal = dealDao.getById(id);
override fun getUserDeals(id: Int): Flow<List<Deal>> = dealDao.getUserDeals(id)
override fun completeDeal(deal: Deal, sellerId: Int, buyerId: Int): Boolean {
return true;
}
override fun pagingData(): Flow<PagingData<Deal>> = Pager(config = PagingConfig(
pageSize = 4, jumpThreshold = 4, initialLoadSize = 4
), pagingSourceFactory = { DealPagination(dealDao) }, initialKey = 1).flow
}

View File

@ -1,12 +0,0 @@
package com.example.testapp.room.repository.offline
import com.example.testapp.room.dao.IDao
import com.example.testapp.room.repository.basic.IRepository
abstract class OfflineRepository<T> (
private val dao: IDao<T>
) : IRepository<T> {
override suspend fun insert(x: T) = dao.insert(x)
override suspend fun update(x: T) = dao.update(x)
override suspend fun delete(x: T) = dao.delete(x)
}

View File

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

View File

@ -1,29 +0,0 @@
package com.example.testapp.room.repository.offline
import androidx.lifecycle.LiveData
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.liveData
import com.example.testapp.room.dao.WalletItemDao
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.pagination.WalletPagination
import com.example.testapp.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.flow.Flow
class OfflineWalletItemRepository(
private val walletItemDao: WalletItemDao
) : OfflineRepository<WalletItem>(walletItemDao), WalletItemRepository {
override fun getUserWallet(id: Int): Flow<List<WalletItem>> = walletItemDao.getUserWallet(id)
override fun getAll(): Flow<List<WalletItem>> = walletItemDao.getAll()
override fun getById(id: Int): WalletItem = throw NotImplementedError()
override fun pagingData(id: Int): Flow<PagingData<WalletItem>> = Pager(config = PagingConfig(
pageSize = 10, jumpThreshold = 10, initialLoadSize = 10
), pagingSourceFactory = { WalletPagination(walletItemDao, id) }, initialKey = 1).flow
override fun pagingDataTest(id: Int): LiveData<PagingData<WalletItem>> = Pager(config = PagingConfig(
pageSize = 1, jumpThreshold = 1, initialLoadSize = 1
), pagingSourceFactory = { WalletPagination(walletItemDao, id) }, initialKey = 1).liveData
}

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.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.designElem.SharedViewModel
import com.example.testapp.navigate.BottomBarScreen
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
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,10 +43,10 @@ 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.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.data.room.models.Coin
import com.example.testapp.data.room.models.Deal
import com.example.testapp.viewModels.AppViewModelProvider
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.DealCreateViewModel
@ -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,21 +6,19 @@ 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
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -36,8 +34,9 @@ import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
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
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.HistoryViewModel
@ -55,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

@ -38,7 +38,7 @@ import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.testapp.graphs.AuthScreen
import com.example.testapp.graphs.Graph
import com.example.testapp.room.models.User
import com.example.testapp.data.room.models.User
import com.example.testapp.viewModels.CurrentUserViewModel
import com.example.testapp.viewModels.RegistrationScreenViewModel
import kotlinx.coroutines.async

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

@ -1,20 +1,15 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.User
import com.example.testapp.room.repository.basic.UserRepository
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.flow.filterNotNull
import kotlinx.coroutines.flow.first
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)
@ -22,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

@ -1,24 +1,17 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
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.data.room.repository.basic.CoinRepository
import com.example.testapp.data.room.repository.basic.DealRepository
import com.example.testapp.data.room.repository.basic.WalletItemRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
class DealCreateViewModel(
@ -42,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,15 +5,15 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
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
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.WalletItemRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.util.Date
@ -28,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 }
@ -55,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)
}
@ -68,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

@ -1,14 +1,10 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.User
import com.example.testapp.room.repository.basic.UserRepository
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(
@ -18,7 +14,7 @@ class EntryScreenViewModel(
fun setupList() {
viewModelScope.launch {
userList.emit(userRepository.getAll().first())
userList.emit(userRepository.getAll())
}
}
}

View File

@ -1,14 +1,14 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.Deal
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.DealRepository
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
import com.example.testapp.data.room.repository.basic.DealRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
@ -20,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

@ -4,9 +4,8 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.testapp.room.models.User
import com.example.testapp.room.repository.basic.UserRepository
import kotlinx.coroutines.flow.first
import com.example.testapp.data.room.models.User
import com.example.testapp.data.room.repository.basic.UserRepository
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

@ -1,24 +1,16 @@
package com.example.testapp.viewModels
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.filter
import com.example.testapp.room.models.Coin
import com.example.testapp.room.models.WalletItem
import com.example.testapp.room.repository.basic.CoinRepository
import com.example.testapp.room.repository.basic.WalletItemRepository
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.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
@ -26,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>