From 3fa072ce1eee0f0fb966c1f27e902249a2592c17 Mon Sep 17 00:00:00 2001 From: Nacho Date: Thu, 13 Nov 2025 23:52:14 +0100 Subject: [PATCH] Updated the store - Items can now be purchased - Changed settings to make use of flows/stateflows from the database, which update the screen in real time after any changes. - Separated functions from files --- app/build.gradle.kts | 1 + .../github/nacabaro/vbhelper/daos/ItemDao.kt | 5 +- .../nacabaro/vbhelper/di/AppContainer.kt | 2 + .../vbhelper/di/DefaultAppContainer.kt | 10 +- .../AdventureScreenControllerImpl.kt | 2 + .../homeScreens/HomeScreenControllerImpl.kt | 2 + .../screens/itemsScreen/ItemDialog.kt | 164 ++++++++++++++++ .../screens/itemsScreen/ItemElement.kt | 175 +----------------- .../vbhelper/screens/itemsScreen/ItemIcons.kt | 40 ++++ .../screens/itemsScreen/ItemsStore.kt | 131 +++++++++---- .../vbhelper/screens/itemsScreen/MyItems.kt | 31 +--- .../vbhelper/source/CurrencyRepository.kt | 28 +++ .../vbhelper/source/ItemsRepository.kt | 6 +- gradle/libs.versions.toml | 2 +- 14 files changed, 367 insertions(+), 232 deletions(-) create mode 100644 app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt create mode 100644 app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt create mode 100644 app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a5fea01..4532721 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -91,4 +91,5 @@ dependencies { implementation("com.google.android.material:material:1.2.0") implementation(libs.protobuf.javalite) implementation("androidx.compose.material:material") + implementation("androidx.datastore:datastore-preferences:1.1.7") } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt index 1164815..076de9d 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt @@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.daos import androidx.room.Dao import androidx.room.Query import com.github.nacabaro.vbhelper.dtos.ItemDtos +import kotlinx.coroutines.flow.Flow @Dao interface ItemDao { @@ -13,7 +14,7 @@ interface ItemDao { ORDER BY Items.itemIcon ASC """ ) - suspend fun getAllItems(): List + fun getAllItems(): Flow> @Query( """ @@ -22,7 +23,7 @@ interface ItemDao { WHERE quantity > 0 """ ) - suspend fun getAllUserItems(): List + fun getAllUserItems(): Flow> @Query( """ diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt b/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt index bc447f2..2d82b95 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt @@ -1,9 +1,11 @@ package com.github.nacabaro.vbhelper.di import com.github.nacabaro.vbhelper.database.AppDatabase +import com.github.nacabaro.vbhelper.source.CurrencyRepository import com.github.nacabaro.vbhelper.source.DataStoreSecretsRepository interface AppContainer { val db: AppDatabase val dataStoreSecretsRepository: DataStoreSecretsRepository + val currencyRepository: CurrencyRepository } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt b/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt index 4724bc6..70305b2 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt @@ -1,20 +1,27 @@ import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.dataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.preferencesDataStore import androidx.room.Room import com.github.nacabaro.vbhelper.database.AppDatabase import com.github.nacabaro.vbhelper.di.AppContainer +import com.github.nacabaro.vbhelper.source.CurrencyRepository import com.github.nacabaro.vbhelper.source.DataStoreSecretsRepository import com.github.nacabaro.vbhelper.source.SecretsSerializer import com.github.nacabaro.vbhelper.source.proto.Secrets private const val SECRETS_DATA_STORE_NAME = "secrets.pb" - +private const val USER_PREFERENCES_NAME = "user_preferences" val Context.secretsStore: DataStore by dataStore( fileName = SECRETS_DATA_STORE_NAME, serializer = SecretsSerializer ) +val Context.currencyStore: DataStore by preferencesDataStore( + name = USER_PREFERENCES_NAME +) + class DefaultAppContainer(private val context: Context) : AppContainer { override val db: AppDatabase by lazy { @@ -29,5 +36,6 @@ class DefaultAppContainer(private val context: Context) : AppContainer { override val dataStoreSecretsRepository = DataStoreSecretsRepository(context.secretsStore) + override val currencyRepository = CurrencyRepository(context.currencyStore) } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt index 535d1f4..50c9605 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.lifecycleScope import com.github.nacabaro.vbhelper.di.VBHelper import com.github.nacabaro.vbhelper.dtos.ItemDtos import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlin.math.roundToInt import kotlin.random.Random @@ -77,6 +78,7 @@ class AdventureScreenControllerImpl( val randomItem = database .itemDao() .getAllItems() + .first() .random() val random = ((Random.nextFloat() * character.stage) + 3).roundToInt() diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt index 5169263..ded8422 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.lifecycleScope import com.github.cfogrady.vbnfc.vb.SpecialMission import com.github.nacabaro.vbhelper.di.VBHelper import com.github.nacabaro.vbhelper.dtos.ItemDtos +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import java.time.Instant import kotlin.math.roundToInt @@ -41,6 +42,7 @@ class HomeScreenControllerImpl( val randomItem = database .itemDao() .getAllItems() + .first() .random() val randomItemAmount = (Random.nextFloat() * 5).roundToInt() diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt new file mode 100644 index 0000000..3bd3e2d --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt @@ -0,0 +1,164 @@ +package com.github.nacabaro.vbhelper.screens.itemsScreen + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import com.github.nacabaro.vbhelper.R +import com.github.nacabaro.vbhelper.domain.items.ItemType +import com.github.nacabaro.vbhelper.dtos.ItemDtos +import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme + +@Composable +fun ItemDialog( + item: ItemDtos.ItemsWithQuantities, + onClickCancel: () -> Unit, + onClickUse: (() -> Unit)? = null, + onClickPurchase: (() -> Unit)? = null, +) { + Dialog( + onDismissRequest = onClickCancel, + properties = DialogProperties( + dismissOnBackPress = true, + dismissOnClickOutside = true + ) + ) { + Card ( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Column ( + modifier = Modifier + .padding(16.dp) + ) { + Row { + Box(modifier = Modifier) { + // Background image (full size) + Icon( + painter = painterResource(id = getIconResource(item.itemIcon)), + contentDescription = null, + modifier = Modifier + .size(96.dp) + .align(Alignment.Center) + ) + Icon( + painter = painterResource(id = getLengthResource(item.itemLength)), + contentDescription = null, + tint = MaterialTheme.colorScheme.outline, + modifier = Modifier + .size(64.dp) // Set the size of the overlay image + .align(Alignment.BottomEnd) // Align to the top end (top-right corner) + ) + } + Column ( + modifier = Modifier + .padding(16.dp) + ) { + Text( + fontSize = MaterialTheme.typography.titleLarge.fontSize, + text = item.name, + modifier = Modifier + .fillMaxWidth() + ) + } + } + Text( + textAlign = TextAlign.Center, + fontSize = MaterialTheme.typography.bodyMedium.fontSize, + fontFamily = MaterialTheme.typography.bodyMedium.fontFamily, + text = item.description, + modifier = Modifier + .fillMaxWidth() + .padding(4.dp) + ) + if (onClickPurchase != null) { + Text( + textAlign = TextAlign.Center, + fontSize = MaterialTheme.typography.bodySmall.fontSize, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + text = "Costs ${item.price} credits", + modifier = Modifier + .fillMaxWidth() + ) + } + Text( + textAlign = TextAlign.Center, + fontSize = MaterialTheme.typography.bodySmall.fontSize, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + text = "You have ${item.quantity} of this item", + modifier = Modifier + .fillMaxWidth() + ) + + Row ( + horizontalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + ) { + if (onClickUse != null) { + Button( + onClick = onClickUse + ) { + Text("Use item") + } + } + + if (onClickPurchase != null) { + Button( + onClick = onClickPurchase + ) { + Text("Purchase") + } + } + + Spacer(modifier = Modifier.size(8.dp)) + Button( + onClick = onClickCancel + ) { + Text("Cancel") + } + } + } + } + } +} + +@Composable +@Preview(showBackground = true) +fun PreviewItemDialog() { + VBHelperTheme { + ItemDialog( + item = ItemDtos.ItemsWithQuantities( + name = "AP Training x3 (60 min)", + description = "Boosts AP during training (for 60 minutes)", + itemIcon = R.drawable.baseline_attack_24, + itemLength = R.drawable.baseline_60_min_timer, + quantity = 19, + id = 1, + price = 500, + itemType = ItemType.BEITEM + ), + onClickUse = { }, + onClickCancel = { } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt index 7822bc0..cd4645c 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt @@ -1,36 +1,23 @@ package com.github.nacabaro.vbhelper.screens.itemsScreen -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.material3.Button import androidx.compose.material3.Card import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties -import com.github.nacabaro.vbhelper.R -import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme +import com.github.nacabaro.vbhelper.dtos.ItemDtos @Composable fun ItemElement( - itemIcon: Int, - lengthIcon: Int, + item: ItemDtos.ItemsWithQuantities, modifier: Modifier = Modifier, onClick: (() -> Unit) = { } ) { @@ -41,7 +28,7 @@ fun ItemElement( ) { Box(modifier = Modifier.fillMaxSize()) { Icon( - painter = painterResource(id = itemIcon), + painter = painterResource(id = getIconResource(item.itemIcon)), contentDescription = null, modifier = Modifier .size(96.dp) @@ -49,164 +36,14 @@ fun ItemElement( .padding(16.dp) ) Icon( - painter = painterResource(id = lengthIcon), + painter = painterResource(id = getLengthResource(item.itemLength)), contentDescription = null, tint = MaterialTheme.colorScheme.surfaceTint, modifier = Modifier - .size(48.dp) // Set the size of the overlay image - .align(Alignment.TopStart) // Align to the top end (top-right corner) + .size(48.dp) + .align(Alignment.TopStart) .padding(8.dp) ) } } } - -@Composable -fun ItemDialog( - name: String, - description: String, - itemIcon: Int, - lengthIcon: Int, - amount: Int, - onClickUse: () -> Unit, - onClickCancel: () -> Unit -) { - Dialog( - onDismissRequest = onClickCancel, - properties = DialogProperties( - dismissOnBackPress = true, - dismissOnClickOutside = true - ) - ) { - Card ( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { - Column ( - modifier = Modifier - .padding(16.dp) - ) { - Row { - Box(modifier = Modifier) { - // Background image (full size) - Icon( - painter = painterResource(id = itemIcon), - contentDescription = null, - modifier = Modifier - .size(96.dp) - .align(Alignment.Center) - ) - Icon( - painter = painterResource(id = lengthIcon), - contentDescription = null, - tint = MaterialTheme.colorScheme.outline, - modifier = Modifier - .size(64.dp) // Set the size of the overlay image - .align(Alignment.BottomEnd) // Align to the top end (top-right corner) - ) - } - Column ( - modifier = Modifier - .padding(16.dp) - ) { - Text( - fontSize = MaterialTheme.typography.titleLarge.fontSize, - text = name, - modifier = Modifier - .fillMaxWidth() - ) - } - } - Text( - textAlign = TextAlign.Center, - fontSize = MaterialTheme.typography.bodyMedium.fontSize, - fontFamily = MaterialTheme.typography.bodyMedium.fontFamily, - text = description, - modifier = Modifier - .fillMaxWidth() - .padding(4.dp) - ) - Text( - textAlign = TextAlign.Center, - fontSize = MaterialTheme.typography.bodySmall.fontSize, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - text = "You have $amount of this item", - modifier = Modifier - .fillMaxWidth() - .padding(8.dp) - ) - Row ( - horizontalArrangement = Arrangement.Center, - modifier = Modifier - .fillMaxWidth() - ) { - Button( - onClick = onClickUse - ) { - Text("Use item") - } - Spacer(modifier = Modifier.size(8.dp)) - Button( - onClick = onClickCancel - ) { - Text("Cancel") - } - } - } - } - } -} - -fun getIconResource(index: Int): Int { - return when (index) { - ItemsScreenControllerImpl.ItemTypes.PPTraining.id -> R.drawable.baseline_agility_24 - ItemsScreenControllerImpl.ItemTypes.APTraining.id -> R.drawable.baseline_attack_24 - ItemsScreenControllerImpl.ItemTypes.HPTraining.id -> R.drawable.baseline_shield_24 - ItemsScreenControllerImpl.ItemTypes.BPTraining.id -> R.drawable.baseline_trophy_24 - ItemsScreenControllerImpl.ItemTypes.AllTraining.id -> R.drawable.baseline_arrow_up_24 - 6 -> R.drawable.baseline_timer_24 - 7 -> R.drawable.baseline_rank_24 - 8 -> R.drawable.baseline_vitals_24 - else -> R.drawable.baseline_question_mark_24 - } -} - -fun getLengthResource(index: Int): Int { - return when (index) { - 15 -> R.drawable.baseline_15_min_timer - 30 -> R.drawable.baseline_30_min_timer - 60 -> R.drawable.baseline_60_min_timer - -60 -> R.drawable.baseline_60_min_timer - 300 -> R.drawable.baseline_5_hour_timer - 600 -> R.drawable.baseline_10_hour_timer - -720 -> R.drawable.baseline_12_hour_timer - -1440 -> R.drawable.baseline_24_hour_timer - 6000 -> R.drawable.baseline_reset_24 - 1000 -> R.drawable.baseline_single_arrow_up - 2500 -> R.drawable.baseline_double_arrow_up - 5000 -> R.drawable.baseline_triple_arrow_up - 9999 -> R.drawable.baseline_health_24 - -500 -> R.drawable.baseline_single_arrow_down - -1000 -> R.drawable.baseline_double_arrow_down - -2500 -> R.drawable.baseline_triple_arrow_down - -9999 -> R.drawable.baseline_reset_24 - else -> R.drawable.baseline_question_mark_24 - } -} - -@Composable -@Preview(showBackground = true) -fun PreviewItemDialog() { - VBHelperTheme { - ItemDialog( - name = "AP Training x3 (60 min)", - description = "Boosts AP during training (for 60 minutes)", - itemIcon = R.drawable.baseline_attack_24, - lengthIcon = R.drawable.baseline_60_min_timer, - onClickUse = { }, - onClickCancel = { }, - amount = 19 - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt new file mode 100644 index 0000000..b0d9e8a --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt @@ -0,0 +1,40 @@ +package com.github.nacabaro.vbhelper.screens.itemsScreen + +import com.github.nacabaro.vbhelper.R + +fun getIconResource(index: Int): Int { + return when (index) { + ItemsScreenControllerImpl.ItemTypes.PPTraining.id -> R.drawable.baseline_agility_24 + ItemsScreenControllerImpl.ItemTypes.APTraining.id -> R.drawable.baseline_attack_24 + ItemsScreenControllerImpl.ItemTypes.HPTraining.id -> R.drawable.baseline_shield_24 + ItemsScreenControllerImpl.ItemTypes.BPTraining.id -> R.drawable.baseline_trophy_24 + ItemsScreenControllerImpl.ItemTypes.AllTraining.id -> R.drawable.baseline_arrow_up_24 + 6 -> R.drawable.baseline_timer_24 + 7 -> R.drawable.baseline_rank_24 + 8 -> R.drawable.baseline_vitals_24 + else -> R.drawable.baseline_question_mark_24 + } +} + +fun getLengthResource(index: Int): Int { + return when (index) { + 15 -> R.drawable.baseline_15_min_timer + 30 -> R.drawable.baseline_30_min_timer + 60 -> R.drawable.baseline_60_min_timer + -60 -> R.drawable.baseline_60_min_timer + 300 -> R.drawable.baseline_5_hour_timer + 600 -> R.drawable.baseline_10_hour_timer + -720 -> R.drawable.baseline_12_hour_timer + -1440 -> R.drawable.baseline_24_hour_timer + 6000 -> R.drawable.baseline_reset_24 + 1000 -> R.drawable.baseline_single_arrow_up + 2500 -> R.drawable.baseline_double_arrow_up + 5000 -> R.drawable.baseline_triple_arrow_up + 9999 -> R.drawable.baseline_health_24 + -500 -> R.drawable.baseline_single_arrow_down + -1000 -> R.drawable.baseline_double_arrow_down + -2500 -> R.drawable.baseline_triple_arrow_down + -9999 -> R.drawable.baseline_reset_24 + else -> R.drawable.baseline_question_mark_24 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt index 032303b..4d4533c 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt @@ -1,25 +1,35 @@ package com.github.nacabaro.vbhelper.screens.itemsScreen +import android.widget.Toast +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items +import androidx.compose.material3.Card import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect +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.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import com.github.nacabaro.vbhelper.database.AppDatabase import com.github.nacabaro.vbhelper.di.VBHelper import com.github.nacabaro.vbhelper.dtos.ItemDtos +import com.github.nacabaro.vbhelper.source.CurrencyRepository import com.github.nacabaro.vbhelper.source.ItemsRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch @Composable fun ItemsStore( @@ -27,45 +37,98 @@ fun ItemsStore( ) { val application = LocalContext.current.applicationContext as VBHelper val itemsRepository = ItemsRepository(application.container.db) - val myItems = remember { mutableStateOf(emptyList()) } + val myItems by itemsRepository.getAllItems().collectAsState(emptyList()) + var selectedElementIndex by remember { mutableStateOf(null) } - LaunchedEffect(itemsRepository) { - withContext(Dispatchers.IO) { - myItems.value = itemsRepository.getAllItems() - } - } + val currencyRepository = application.container.currencyRepository + val currentCurrency = currencyRepository.currencyValue.collectAsState(0) - if (myItems.value.isEmpty()) { - Text("No items") - } else { - LazyVerticalGrid( - columns = GridCells.Fixed(3), - modifier = Modifier + val scope = rememberCoroutineScope() + + if (myItems.isEmpty()) { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxSize() ) { - items(myItems.value) { index -> - ItemElement( - itemIcon = getIconResource(index.itemIcon), - lengthIcon = getLengthResource(index.itemLength), + Text("No items") + } + } else { + Column() { + Card( + modifier = Modifier + .padding(8.dp) + .fillMaxWidth() + ) { + Text( + text = "${currentCurrency.value} credits", modifier = Modifier - .padding(8.dp), - onClick = { - selectedElementIndex = myItems.value.indexOf(index) - } + .padding(8.dp) ) } - } - if (selectedElementIndex != null) { - ItemDialog( - name = myItems.value[selectedElementIndex!!].name, - description = myItems.value[selectedElementIndex!!].description, - itemIcon = getIconResource(myItems.value[selectedElementIndex!!].itemIcon), - lengthIcon = getLengthResource(myItems.value[selectedElementIndex!!].itemLength), - amount = myItems.value[selectedElementIndex!!].quantity, - onClickUse = { }, - onClickCancel = { selectedElementIndex = null } - ) + LazyVerticalGrid( + columns = GridCells.Fixed(3), + modifier = Modifier + ) { + items(myItems) { index -> + ItemElement( + item = index, + modifier = Modifier + .padding(8.dp), + onClick = { + selectedElementIndex = myItems.indexOf(index) + } + ) + } + } } } + + + if (selectedElementIndex != null) { + ItemDialog( + item = myItems[selectedElementIndex!!], + onClickPurchase = { + scope.launch { + Toast.makeText( + application.applicationContext, + purchaseItem( + application.container.db, + myItems[selectedElementIndex!!], + currencyRepository + ), + Toast.LENGTH_SHORT + ).show( + ) + } + }, + onClickCancel = { selectedElementIndex = null } + ) + } +} + +suspend fun purchaseItem( + db: AppDatabase, + item: ItemDtos.ItemsWithQuantities, + currencyRepository: CurrencyRepository +): String { + if (currencyRepository.currencyValue.first() < item.price) { + return "Not enough credits" + } else { + db + .itemDao() + .purchaseItem( + item.id, + 1 + ) + + currencyRepository + .setCurrencyValue( + currencyRepository.currencyValue.first() - item.price + ) + + return "Purchase successful!" + } } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt index 55b835f..39479a8 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt @@ -9,7 +9,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -20,11 +20,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.navigation.NavController import com.github.nacabaro.vbhelper.di.VBHelper -import com.github.nacabaro.vbhelper.dtos.ItemDtos import com.github.nacabaro.vbhelper.navigation.NavigationItems import com.github.nacabaro.vbhelper.source.ItemsRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext @Composable fun MyItems( @@ -32,16 +29,11 @@ fun MyItems( ) { val application = LocalContext.current.applicationContext as VBHelper val itemsRepository = ItemsRepository(application.container.db) - val myItems = remember { mutableStateOf(emptyList()) } + val myItems by itemsRepository.getUserItems().collectAsState(emptyList()) + var selectedElementIndex by remember { mutableStateOf(null) } - LaunchedEffect(itemsRepository) { - withContext(Dispatchers.IO) { - myItems.value = itemsRepository.getUserItems() - } - } - - if (myItems.value.isEmpty()) { + if (myItems.isEmpty()) { Column( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, @@ -54,14 +46,13 @@ fun MyItems( columns = GridCells.Fixed(3), modifier = Modifier ) { - items(myItems.value) { index -> + items(myItems) { index -> ItemElement( - itemIcon = getIconResource(index.itemIcon), - lengthIcon = getLengthResource(index.itemLength), + item = index, modifier = Modifier .padding(8.dp), onClick = { - selectedElementIndex = myItems.value.indexOf(index) + selectedElementIndex = myItems.indexOf(index) } ) } @@ -69,11 +60,7 @@ fun MyItems( if (selectedElementIndex != null) { ItemDialog( - name = myItems.value[selectedElementIndex!!].name, - description = myItems.value[selectedElementIndex!!].description, - itemIcon = getIconResource(myItems.value[selectedElementIndex!!].itemIcon), - lengthIcon = getLengthResource(myItems.value[selectedElementIndex!!].itemLength), - amount = myItems.value[selectedElementIndex!!].quantity, + item = myItems[selectedElementIndex!!], onClickUse = { navController .navigate( @@ -81,7 +68,7 @@ fun MyItems( .ApplyItem.route .replace( "{itemId}", - myItems.value[selectedElementIndex!!].id.toString() + myItems[selectedElementIndex!!].id.toString() ) ) selectedElementIndex = null diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt new file mode 100644 index 0000000..42fc61a --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt @@ -0,0 +1,28 @@ +package com.github.nacabaro.vbhelper.source + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.intPreferencesKey +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +class CurrencyRepository ( + private val dataStore: DataStore +) { + + private companion object { + val CURRENCY_VALUE = intPreferencesKey("currency_value") + } + + val currencyValue: Flow = dataStore.data + .map { preferences -> + preferences[CURRENCY_VALUE] ?: 10000 + } + + suspend fun setCurrencyValue(newValue: Int) { + dataStore.edit { preferences -> + preferences[CURRENCY_VALUE] = newValue + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt index 8d6d705..e93a49b 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt @@ -1,17 +1,17 @@ package com.github.nacabaro.vbhelper.source import com.github.nacabaro.vbhelper.database.AppDatabase -import com.github.nacabaro.vbhelper.domain.items.Items import com.github.nacabaro.vbhelper.dtos.ItemDtos +import kotlinx.coroutines.flow.Flow class ItemsRepository( private val db: AppDatabase ) { - suspend fun getAllItems(): List { + fun getAllItems(): Flow> { return db.itemDao().getAllItems() } - suspend fun getUserItems(): List { + fun getUserItems(): Flow> { return db.itemDao().getAllUserItems() } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2754f1b..1db28ca 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.12.2" +agp = "8.13.1" datastore = "1.1.2" kotlin = "2.0.0" coreKtx = "1.15.0"