This commit is contained in:
zyzf 2023-12-04 15:39:21 +04:00
parent ef95904c6f
commit 702d8972bd
12 changed files with 313 additions and 152 deletions

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@ -75,6 +75,8 @@ dependencies {
implementation("androidx.compose.ui:ui-graphics:1.6.0-beta02")
implementation("androidx.compose.ui:ui-tooling-preview:1.6.0-beta02")
implementation("androidx.compose.material3:material3:1.1.2")
implementation("androidx.compose.material:material:1.5.4")
implementation("androidx.paging:paging-compose:3.2.1")
// Room
val room_version = "2.6.1"

View File

@ -27,5 +27,6 @@ class AppDataContainer(private val context: Context) : AppContainer {
companion object {
const val TIMEOUT = 5000L
const val LIMIT = 10
}
}

View File

@ -1,5 +1,6 @@
package com.zyzf.coffeepreorder.database.dao
import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Query
@ -10,10 +11,10 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface CoffeeDao {
@Query("select * from coffee order by name collate nocase asc")
fun getAll(): Flow<List<Coffee>>
fun getAll(): PagingSource<Int, Coffee>
@Query("select * from coffee where cart_id is not null and count > 0 order by name collate nocase asc")
fun getAllInCart(): Flow<List<Coffee>>
fun getAllInCart(): PagingSource<Int, Coffee>
@Query("select sum(cost) from coffee where cart_id is not null and count > 0")
fun getSumInCart(): Double

View File

@ -17,7 +17,7 @@ import androidx.room.PrimaryKey
])
data class Coffee(
@PrimaryKey(autoGenerate = true)
val uid: Int?,
val uid: Int = 0,
@ColumnInfo(name = "name")
var name: String,
@ColumnInfo(name = "cost")
@ -36,7 +36,7 @@ data class Coffee(
ingredients: String,
cartId: Int?,
count: Int?
) : this(null, name, cost, ingredients, null, 0)
) : this(0, name, cost, ingredients, null, 0)
companion object {
fun getCoffee(index: Int = 0): Coffee {

View File

@ -1,12 +1,13 @@
package com.zyzf.coffeepreorder.database.repository
import androidx.paging.PagingData
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.database.model.CoffeeWithCart
import kotlinx.coroutines.flow.Flow
interface CoffeeRepository {
fun getAll(): Flow<List<Coffee>>
fun getAllInCart(): Flow<List<Coffee>>
fun getAll(): Flow<PagingData<Coffee>>
fun getAllInCart(): Flow<PagingData<Coffee>>
fun getSumInCart(): Double
suspend fun getByUid(uid: Int): CoffeeWithCart?
suspend fun insert(name: String, cost: Double, ingredients: String): Long

View File

@ -1,13 +1,29 @@
package com.zyzf.coffeepreorder.database.repository
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.zyzf.coffeepreorder.database.AppDataContainer
import com.zyzf.coffeepreorder.database.dao.CoffeeDao
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.database.model.CoffeeWithCart
import kotlinx.coroutines.flow.Flow
class OfflineCoffeeRepository(private val coffeeDao: CoffeeDao) : CoffeeRepository {
override fun getAll(): Flow<List<Coffee>> = coffeeDao.getAll()
override fun getAllInCart(): Flow<List<Coffee>> = coffeeDao.getAllInCart()
override fun getAll(): Flow<PagingData<Coffee>> = Pager(
config = PagingConfig(
pageSize = AppDataContainer.LIMIT,
enablePlaceholders = false
),
pagingSourceFactory = coffeeDao::getAll
).flow
override fun getAllInCart(): Flow<PagingData<Coffee>> = Pager(
config = PagingConfig(
pageSize = AppDataContainer.LIMIT,
enablePlaceholders = false
),
pagingSourceFactory = coffeeDao::getAllInCart
).flow
override fun getSumInCart(): Double = coffeeDao.getSumInCart()
override suspend fun getByUid(uid: Int): CoffeeWithCart? = coffeeDao.getByUid(uid)
override suspend fun insert(name: String, cost: Double, ingredients: String): Long = coffeeDao.insert(name, cost, ingredients)

View File

@ -5,6 +5,7 @@ import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.zyzf.coffeepreorder.CoffeeApplication
import com.zyzf.coffeepreorder.ui.cart.CartViewModel
import com.zyzf.coffeepreorder.ui.coffee.CoffeeListViewModel
object AppViewModelProvider {
@ -12,6 +13,9 @@ object AppViewModelProvider {
initializer {
CoffeeListViewModel(coffeeApplication().container.coffeeRepository, coffeeApplication().container.cartRepository)
}
initializer {
CartViewModel(coffeeApplication().container.coffeeRepository, coffeeApplication().container.cartRepository)
}
}
}

View File

@ -1,5 +1,6 @@
package com.zyzf.coffeepreorder.ui.cart
import android.content.Context
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -15,24 +16,32 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -43,12 +52,21 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.database.AppDatabase
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.ui.AppViewModelProvider
import com.zyzf.coffeepreorder.ui.coffee.CoffeeList
import com.zyzf.coffeepreorder.ui.coffee.CoffeeListViewModel
import com.zyzf.coffeepreorder.ui.navigation.Screen
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
import kotlinx.coroutines.DelicateCoroutinesApi
@ -57,88 +75,153 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@OptIn(DelicateCoroutinesApi::class)
@OptIn(DelicateCoroutinesApi::class, ExperimentalMaterialApi::class)
@Composable
fun Cart(navController: NavController?) {
fun Cart(
navController: NavController?,
viewModel: CartViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val coroutineScope = rememberCoroutineScope()
val coffeeListUiState = viewModel.coffeeListUiState.collectAsLazyPagingItems()
val openDialog = remember { mutableStateOf(false) }
var coffee by remember { mutableStateOf(Coffee("", 0.0, "", null, 0)) }
val context = LocalContext.current
val itemsList = remember { mutableStateListOf<Coffee>() }
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).coffeeDao().getAllInCart().collect { data ->
itemsList.clear()
itemsList.addAll(data)
val coffee = remember { mutableStateOf(Coffee.getCoffee()) }
var refreshing by remember { mutableStateOf(false) }
fun refresh() = coroutineScope.launch {
refreshing = true
coffeeListUiState.refresh()
refreshing = false
}
val state = rememberPullRefreshState(refreshing, ::refresh)
Scaffold(
topBar = {},
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = { navController?.navigate(Screen.Order.route) },
icon = { Icon(Icons.Filled.Add, "Сделать заказ") },
text = { Text(text = "Сделать заказ") },
modifier = Modifier
.padding(all = 20.dp),
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
}
) { innerPadding ->
PullRefreshIndicator(
refreshing, state,
Modifier
.zIndex(100f)
)
CartList(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
coffeeList = coffeeListUiState,
onDeleteFromCartClick = {currentCoffee: Coffee ->
coffee.value = currentCoffee
openDialog.value = true
}
)
}
DeleteFromCartAlertDialog(
openDialog = openDialog,
onConfirmClick = {
coroutineScope.launch {
viewModel.deleteCoffeeFromCart(coffee.value)
}
}
)
}
@Composable
private fun CartList(
modifier: Modifier = Modifier,
coffeeList: LazyPagingItems<Coffee>,
onDeleteFromCartClick: (coffee: Coffee) -> Unit
) {
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally) {
items(
count = coffeeList.itemCount,
key = coffeeList.itemKey(),
contentType = coffeeList.itemContentType()
) {index ->
val coffee = coffeeList[index]
coffee?.let {
CartListItem(
coffee = coffee,
onDeleteFromCartClick = onDeleteFromCartClick
)
}
}
}
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally) {
items(itemsList) { currentCoffee ->
Row(modifier = Modifier
.fillMaxWidth()
.heightIn(max = 140.dp)
.padding(bottom = 10.dp, top = 10.dp),
horizontalArrangement = Arrangement.SpaceAround) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current).data("https://zyzf.space/s/zXgFRTmbR4KMxMH/download?path=&files=coffee_image_" + currentCoffee.uid +".png")
.crossfade(true).build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = "Кофе",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(100.dp)
.clip(RoundedCornerShape(50.dp))
)
Column(
Modifier
.weight(2f)
.padding(start = 20.dp)) {
val currentCoffeeName: String = if (currentCoffee.count > 1) {
currentCoffee.name + " x" + currentCoffee.count.toString()
} else {
currentCoffee.name
}
Text(text = currentCoffeeName, fontSize = 25.sp)
Text(text = String.format("%.2f", currentCoffee.cost), fontSize = 20.sp)
Text(text = currentCoffee.ingredients, fontSize = 15.sp)
Row(
Modifier
.fillMaxWidth()
.padding(top = 5.dp)) {
Button(
onClick = { coffee = currentCoffee; openDialog.value = true },
shape = CircleShape,
modifier = Modifier.padding(start = 10.dp, end = 10.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
)
) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Удалить из корзины")
}
}
}
@Composable
private fun CartListItem (
coffee: Coffee,
modifier: Modifier = Modifier,
onDeleteFromCartClick: (coffee: Coffee) -> Unit
) {
Row(modifier = Modifier
.fillMaxWidth()
.heightIn(max = 140.dp)
.padding(bottom = 10.dp, top = 10.dp),
horizontalArrangement = Arrangement.SpaceAround) {
AsyncImage(
model = ImageRequest.Builder(context = LocalContext.current).data("https://zyzf.space/s/zXgFRTmbR4KMxMH/download?path=&files=coffee_image_" + coffee.uid +".png")
.crossfade(true).build(),
error = painterResource(R.drawable.ic_broken_image),
placeholder = painterResource(R.drawable.loading_img),
contentDescription = "Кофе",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(100.dp)
.clip(RoundedCornerShape(50.dp))
)
Column(
Modifier
.weight(2f)
.padding(start = 20.dp)) {
val currentCoffeeName: String = if (coffee.count > 1) {
coffee.name + " x" + coffee.count.toString()
} else {
coffee.name
}
Text(text = currentCoffeeName, fontSize = 25.sp)
Text(text = String.format("%.2f", coffee.cost), fontSize = 20.sp)
Text(text = coffee.ingredients, fontSize = 15.sp)
Row(
Modifier
.fillMaxWidth()
.padding(top = 5.dp)) {
Button(
onClick = { onDeleteFromCartClick(coffee) },
shape = CircleShape,
modifier = Modifier.padding(start = 10.dp, end = 10.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
contentColor = MaterialTheme.colorScheme.error
)
) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = "Favorite",
modifier = Modifier.size(20.dp)
)
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text(text = "Удалить из корзины")
}
}
}
}
Box(modifier = Modifier.fillMaxSize()) {
ExtendedFloatingActionButton(
onClick = { navController?.navigate(Screen.Order.route) },
icon = { Icon(Icons.Filled.Add, "Сделать заказ") },
text = { Text(text = "Сделать заказ") },
modifier = Modifier.align(alignment = Alignment.BottomEnd).padding(all = 20.dp),
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.primary
)
}
}
@Composable
private fun DeleteFromCartAlertDialog(
modifier: Modifier = Modifier,
openDialog: MutableState<Boolean>,
onConfirmClick: () -> Unit
) {
if (openDialog.value) {
AlertDialog(
icon = {
@ -156,12 +239,7 @@ fun Cart(navController: NavController?) {
confirmButton = {
TextButton(
onClick = {
GlobalScope.launch (Dispatchers.Main) {
coffee.uid?.let {
AppDatabase.getInstance(context).cartDao().deleteCoffee(it, 1)
}
}
onConfirmClick()
openDialog.value = false
}
) {

View File

@ -0,0 +1,19 @@
package com.zyzf.coffeepreorder.ui.cart
import androidx.lifecycle.ViewModel
import androidx.paging.PagingData
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.database.repository.CartRepository
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
import kotlinx.coroutines.flow.Flow
class CartViewModel(
private val coffeeRepository: CoffeeRepository,
private val cartRepository: CartRepository
) : ViewModel() {
val coffeeListUiState: Flow<PagingData<Coffee>> = coffeeRepository.getAllInCart()
suspend fun deleteCoffeeFromCart(coffee: Coffee) {
cartRepository.deleteCoffee(coffee.uid, 1)
}
}

View File

@ -21,12 +21,17 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.outlined.Create
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
@ -51,6 +56,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
@ -61,31 +67,46 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.paging.PagingData
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.ui.AppViewModelProvider
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
@Composable
fun CoffeeList(
viewModel: CoffeeListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
val coroutineScope = rememberCoroutineScope()
val coffeeListUiState = viewModel.coffeeListUiState.collectAsState()
val coffeeListUiState = viewModel.coffeeListUiState.collectAsLazyPagingItems()
val sheetState = rememberModalBottomSheetState()
val openDialog = remember { mutableStateOf(false) }
val coffee = remember { mutableStateOf(Coffee.getCoffee()) }
var imageUri: Any? by remember { mutableStateOf(R.drawable.img) }
var refreshing by remember { mutableStateOf(false) }
fun refresh() = coroutineScope.launch {
refreshing = true
coffeeListUiState.refresh()
refreshing = false
}
val state = rememberPullRefreshState(refreshing, ::refresh)
val photoPicker = rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia()
) {
if (it != null) {
Log.d("PhotoPicker", "Selected URI: $it")
viewModel.imageUri = it
imageUri = it
} else {
Log.d("PhotoPicker", "No media selected")
}
@ -111,48 +132,51 @@ fun CoffeeList(
}
}
) { innerPadding ->
coffeeListUiState.value.coffeeList.let {
CoffeeList(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
coffeeList = it,
onAddToCartClick = { coffeeUid: Int ->
coroutineScope.launch {
viewModel.addCoffeeToCart(coffeeUid = coffeeUid)
}
},
onEditClick = { curcoffee: Coffee ->
coroutineScope.launch {
coffee.value = curcoffee
openDialog.value = true
}
}
)
}
AddEditModalBottomSheet(
coffee = coffee,
sheetState = sheetState,
openDialog = openDialog,
onAddClick = { coffee: Coffee, context: Context ->
PullRefreshIndicator(
refreshing, state,
Modifier
.zIndex(100f)
)
CoffeeList(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
coffeeList = coffeeListUiState,
onAddToCartClick = { coffeeUid: Int ->
coroutineScope.launch {
viewModel.createCoffee(coffee, context)
viewModel.addCoffeeToCart(coffeeUid = coffeeUid)
}
},
onEditClick = { coffee: Coffee, context: Context ->
onEditClick = { curcoffee: Coffee ->
coroutineScope.launch {
viewModel.editCoffee(coffee, context)
coffee.value = curcoffee
openDialog.value = true
}
},
onDeleteClick = { coffee: Coffee ->
coroutineScope.launch {
viewModel.deleteCoffee(coffee)
}
},
photoPicker = photoPicker,
imageUri = viewModel.imageUri
}
)
}
AddEditModalBottomSheet(
coffee = coffee,
sheetState = sheetState,
openDialog = openDialog,
onAddClick = { coffee: Coffee, context: Context ->
coroutineScope.launch {
viewModel.createCoffee(coffee, imageUri as Uri, context)
}
},
onEditClick = { coffee: Coffee, context: Context ->
coroutineScope.launch {
viewModel.editCoffee(coffee, imageUri as Uri, context)
}
},
onDeleteClick = { coffee: Coffee ->
coroutineScope.launch {
viewModel.deleteCoffee(coffee)
}
},
photoPicker = photoPicker,
imageUri = imageUri
)
}
@OptIn(ExperimentalMaterial3Api::class)
@ -269,14 +293,21 @@ private fun AddEditModalBottomSheet(
@Composable
private fun CoffeeList(
modifier: Modifier = Modifier,
coffeeList: List<Coffee>,
coffeeList: LazyPagingItems<Coffee>,
onAddToCartClick: (coffeeUid: Int) -> Unit,
onEditClick: (coffee: Coffee) -> Unit
) {
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally) {
items(items = coffeeList, key = { it.uid!! }) { coffee ->
CoffeeListItem(coffee = coffee, onAddToCartClick = onAddToCartClick, onEditClick = onEditClick)
items(
count = coffeeList.itemCount,
key = coffeeList.itemKey(),
contentType = coffeeList.itemContentType()
) {index ->
val coffee = coffeeList[index]
coffee?.let {
CoffeeListItem(coffee = coffee, onAddToCartClick = onAddToCartClick, onEditClick = onEditClick)
}
}
}
}
@ -319,7 +350,7 @@ private fun CoffeeListItem(
.padding(top = 5.dp)) {
Button(
onClick = {
coffee.uid?.let { onAddToCartClick(it) }
coffee.uid.let { onAddToCartClick(it) }
},
shape = CircleShape,
modifier = Modifier.fillMaxWidth(fraction = 0.75f)
@ -350,6 +381,7 @@ private fun CoffeeListItem(
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
@ -359,7 +391,29 @@ fun CoffeeListPreview() {
color = MaterialTheme.colorScheme.background
) {
CoffeeList(
coffeeList = (1..20).map { i -> Coffee.getCoffee(i) },
coffeeList = MutableStateFlow(
PagingData.from((1..20).map { i -> Coffee.getCoffee(i) })
).collectAsLazyPagingItems(),
onAddToCartClick = {},
onEditClick = {}
)
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun CoffeeEmptyListPreview() {
CoffeePreorderTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
CoffeeList(
coffeeList = MutableStateFlow(
PagingData.empty<Coffee>()
).collectAsLazyPagingItems(),
onAddToCartClick = {},
onEditClick = {}
)

View File

@ -6,24 +6,19 @@ import android.graphics.BitmapFactory
import android.net.Uri
import android.os.StrictMode
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.jcraft.jsch.Channel
import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.JSch
import com.jcraft.jsch.JSchException
import com.jcraft.jsch.Session
import com.jcraft.jsch.SftpException
import com.zyzf.coffeepreorder.R
import com.zyzf.coffeepreorder.database.AppDataContainer
import com.zyzf.coffeepreorder.database.model.Cart
import com.zyzf.coffeepreorder.database.model.Coffee
import com.zyzf.coffeepreorder.database.repository.CartRepository
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.File
@ -34,22 +29,15 @@ class CoffeeListViewModel(
private val coffeeRepository: CoffeeRepository,
private val cartRepository: CartRepository
) : ViewModel() {
val coffeeListUiState: StateFlow<CoffeeListUiState> = coffeeRepository.getAll().map {
CoffeeListUiState(it)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
initialValue = CoffeeListUiState()
)
var imageUri: Any? = R.drawable.img
val coffeeListUiState: Flow<PagingData<Coffee>> = coffeeRepository.getAll()
suspend fun addCoffeeToCart(coffeeUid: Int) {
val cart: Cart = cartRepository.get()
cart.uid?.let { cartRepository.insertCoffee(it, coffeeUid, 1) }
}
suspend fun createCoffee(coffee: Coffee, context: Context) {
suspend fun createCoffee(coffee: Coffee, imageUri: Uri, context: Context) {
val newCoffee: Long = coffeeRepository.insert(coffee.name, coffee.cost, coffee.ingredients)
val inputStream = context.contentResolver.openInputStream(imageUri as Uri)
val inputStream = context.contentResolver.openInputStream(imageUri)
val bitmap = BitmapFactory.decodeStream(inputStream)
val f = File(context.cacheDir, "coffee_image_$newCoffee.png")
@ -66,9 +54,9 @@ class CoffeeListViewModel(
copyFileToSftp(f, "/mnt/nextcloud/data/Zyzf/files/Images")
}
suspend fun editCoffee(coffee: Coffee, context: Context) {
suspend fun editCoffee(coffee: Coffee, imageUri: Uri, context: Context) {
val editedCoffee: Int = coffeeRepository.update(coffee.uid!!, coffee.name, coffee.cost, coffee.ingredients, coffee.cartId, coffee.count)!!
val inputStream = context.contentResolver.openInputStream(imageUri as Uri)
val inputStream = context.contentResolver.openInputStream(imageUri)
val bitmap = BitmapFactory.decodeStream(inputStream)
val f = File(context.cacheDir, "coffee_image_$editedCoffee.png")
@ -89,8 +77,6 @@ class CoffeeListViewModel(
}
}
data class CoffeeListUiState(val coffeeList: List<Coffee> = listOf())
const val REMOTE_HOST = "109.197.199.134"
const val USERNAME = "zyzf"
const val PASSWORD = "250303Zyzf-d-grad"