diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt index 569662b..eaa7d0e 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt @@ -24,6 +24,7 @@ import com.github.nacabaro.vbhelper.domain.characters.Character import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter import com.github.nacabaro.vbhelper.navigation.AppNavigationHandlers +import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme @@ -63,12 +64,17 @@ class MainActivity : ComponentActivity() { this::unregisterActivityLifecycleListener ) val settingsScreenController = SettingsScreenControllerImpl(this) + val itemsScreenController = ItemsScreenControllerImpl(this) super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { VBHelperTheme { - MainApplication(scanScreenController, settingsScreenController) + MainApplication( + scanScreenController = scanScreenController, + settingsScreenController = settingsScreenController, + itemsScreenController = itemsScreenController + ) } } Log.i("MainActivity", "Activity onCreated") @@ -189,13 +195,15 @@ class MainActivity : ComponentActivity() { @Composable private fun MainApplication( scanScreenController: ScanScreenControllerImpl, - settingsScreenController: SettingsScreenControllerImpl + settingsScreenController: SettingsScreenControllerImpl, + itemsScreenController: ItemsScreenControllerImpl ) { AppNavigation( applicationNavigationHandlers = AppNavigationHandlers( settingsScreenController, scanScreenController, + itemsScreenController ), onClickImportCard = { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply { diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/components/ItemElement.kt b/app/src/main/java/com/github/nacabaro/vbhelper/components/ItemElement.kt index 1a2783e..07778ac 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/components/ItemElement.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/components/ItemElement.kt @@ -166,6 +166,7 @@ fun getIconResource(index: Int): Int { 5 -> 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 } } 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 7eaa1bf..3aad016 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 @@ -21,6 +21,14 @@ interface ItemDao { """) suspend fun getAllUserItems(): List + @Query(""" + SELECT Items.*, UserItems.quantity + FROM Items + JOIN UserItems ON Items.id = UserItems.itemId + WHERE UserItems.itemId = :itemId + """) + fun getUserItem(itemId: Long): ItemDtos.ItemsWithQuantities + @Query(""" UPDATE UserItems SET quantity = quantity - 1 diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt index acf7d0a..13e8fd4 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt @@ -17,11 +17,14 @@ import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreen import com.github.nacabaro.vbhelper.screens.SpriteViewer import com.github.nacabaro.vbhelper.screens.StorageScreen +import com.github.nacabaro.vbhelper.screens.itemsScreen.ChooseCharacterScreen +import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl data class AppNavigationHandlers( val settingsScreenController: SettingsScreenControllerImpl, val scanScreenController: ScanScreenControllerImpl, + val itemsScreenController: ItemsScreenControllerImpl ) @Composable @@ -96,6 +99,17 @@ fun AppNavigation( navController = navController ) } + composable(NavigationItems.ApplyItem.route) { + val itemId = it.arguments?.getString("itemId") + if (itemId != null) { + ChooseCharacterScreen( + itemsScreenController = applicationNavigationHandlers + .itemsScreenController, + navController = navController, + itemId = itemId.toLong() + ) + } + } } } } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt index ee831b0..45c654e 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt @@ -18,4 +18,5 @@ sealed class NavigationItems ( object Items : NavigationItems("Items", R.drawable.baseline_data_24, "Items") object MyItems : NavigationItems("MyItems", R.drawable.baseline_data_24, "My items") object ItemsStore : NavigationItems("ItemsStore", R.drawable.baseline_data_24, "Items store") + object ApplyItem : NavigationItems("ApplyItem/{itemId}", R.drawable.baseline_data_24, "Apply item") } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt index 533b131..ac0f28c 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt @@ -1,6 +1,5 @@ package com.github.nacabaro.vbhelper.screens -import android.util.Log import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.scrollable import androidx.compose.foundation.layout.Arrangement @@ -8,7 +7,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt new file mode 100644 index 0000000..fe52df1 --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt @@ -0,0 +1,90 @@ +package com.github.nacabaro.vbhelper.screens.itemsScreen + +import android.widget.Toast +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.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation.NavController +import com.github.nacabaro.vbhelper.components.CharacterEntry +import com.github.nacabaro.vbhelper.components.TopBanner +import com.github.nacabaro.vbhelper.di.VBHelper +import com.github.nacabaro.vbhelper.dtos.CharacterDtos +import com.github.nacabaro.vbhelper.source.StorageRepository +import com.github.nacabaro.vbhelper.utils.BitmapData +import kotlinx.coroutines.launch + + +@Composable +fun ChooseCharacterScreen( + navController: NavController, + itemsScreenController: ItemsScreenControllerImpl, + itemId: Long +) { + val coroutineScope = rememberCoroutineScope() + val application = LocalContext.current.applicationContext as VBHelper + val storageRepository = StorageRepository(application.container.db) + val characterList = remember { + mutableStateOf>(emptyList()) + } + + var selectedCharacter by remember { mutableStateOf(null) } + + LaunchedEffect(storageRepository) { + coroutineScope.launch { + characterList.value = storageRepository.getAllCharacters() + } + } + + LaunchedEffect (selectedCharacter) { + if (selectedCharacter != null) { + itemsScreenController.applyItem(itemId, selectedCharacter!!) { + Toast.makeText( + application.applicationContext, + "Item applied!", + Toast.LENGTH_SHORT + ).show() + navController.popBackStack() + } + } + } + + Scaffold( + topBar = { + TopBanner( + text = "Choose character", + onBackClick = { + navController.popBackStack() + } + ) + } + ) { contentPadding -> + LazyVerticalGrid( + columns = GridCells.Fixed(3), + modifier = Modifier + .padding(top = contentPadding.calculateTopPadding()) + ) { + items(characterList.value) { + CharacterEntry( + icon = BitmapData( + bitmap = it.spriteIdle, + width = it.spriteWidth, + height = it.spriteHeight + ) + ) { + selectedCharacter = it.id + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenController.kt index de3c2d1..d967c08 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenController.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenController.kt @@ -1,7 +1,6 @@ package com.github.nacabaro.vbhelper.screens.itemsScreen -import com.github.nacabaro.vbhelper.domain.items.Items interface ItemsScreenController { - suspend fun applyItem(item: Items, characterId: Long) + fun applyItem(itemId: Long, characterId: Long, onCompletion: () -> Unit) } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenControllerImpl.kt index 0b02122..70fc514 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenControllerImpl.kt @@ -1,14 +1,22 @@ package com.github.nacabaro.vbhelper.screens.itemsScreen +import androidx.activity.ComponentActivity +import androidx.lifecycle.lifecycleScope import com.github.nacabaro.vbhelper.database.AppDatabase +import com.github.nacabaro.vbhelper.di.VBHelper import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData -import com.github.nacabaro.vbhelper.domain.items.Items +import com.github.nacabaro.vbhelper.dtos.ItemDtos import com.github.nacabaro.vbhelper.utils.DeviceType +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext class ItemsScreenControllerImpl ( - private val database: AppDatabase + private val context: ComponentActivity, ): ItemsScreenController { + private var database: AppDatabase + private enum class ItemTypes(val id: Int) { PPTraining(1), HPTraining(2), @@ -20,60 +28,87 @@ class ItemsScreenControllerImpl ( Vitals(8) } - override suspend fun applyItem(item: Items, characterId: Long) { - var characterData = database.userCharacterDao().getCharacter(characterId) - var beCharacterData: BECharacterData - var vbCharacterData: VBCharacterData - if (characterData.characterType == DeviceType.BEDevice) { - beCharacterData = database.userCharacterDao().getBeData(characterId) - } else { - TODO("Not implemented") - //vbCharacterData = database.userCharacterDao().getVbData(characterId) + init { + val application = context.applicationContext as VBHelper + database = application.container.db + } + + override fun applyItem(itemId: Long, characterId: Long, onCompletion: () -> Unit) { + context.lifecycleScope.launch { + withContext(Dispatchers.IO) { + val item = getItem(itemId) + val characterData = database.userCharacterDao().getCharacter(characterId) + val beCharacterData: BECharacterData + var vbCharacterData: VBCharacterData + + if (characterData.characterType == DeviceType.BEDevice) { + beCharacterData = database.userCharacterDao().getBeData(characterId) + } else { + TODO("Not implemented") + //vbCharacterData = database.userCharacterDao().getVbData(characterId) + } + + if (item.itemIcon in 1 .. 5 && characterData.characterType == DeviceType.BEDevice) { + beCharacterData.itemType = item.itemIcon + beCharacterData.itemMultiplier = 3 + beCharacterData.itemRemainingTime = item.itemLength + + database + .userCharacterDao() + .updateBECharacterData(beCharacterData) + + } else if (item.itemIcon == ItemTypes.EvoTimer.id) { + characterData.transformationCountdown += item.itemLength + if (characterData.transformationCountdown < 0) { + characterData.transformationCountdown = 0 + } + + // VB does not like it when the transformationCountdown is 0 + if (characterData.characterType == DeviceType.VBDevice && + characterData.transformationCountdown <= 0 ) { + characterData.transformationCountdown = 1 + } + + database + .userCharacterDao() + .updateCharacter(characterData) + + } else if (item.itemIcon == ItemTypes.LimitTimer.id) { + beCharacterData.remainingTrainingTimeInMinutes += item.itemLength + if (beCharacterData.remainingTrainingTimeInMinutes > 6000) { + beCharacterData.remainingTrainingTimeInMinutes = 6000 + } + + database + .userCharacterDao() + .updateBECharacterData(beCharacterData) + + } else if (item.itemIcon == ItemTypes.Vitals.id) { + characterData.vitalPoints += item.itemLength + if (characterData.vitalPoints < 0) { + characterData.vitalPoints = 0 + } else if (characterData.vitalPoints > 9999) { + characterData.vitalPoints = 9999 + } + + database + .userCharacterDao() + .updateCharacter(characterData) + } + + consumeItem(item.id) + + context.runOnUiThread { + onCompletion() + } + } } + } - if (item.itemIcon in 1 .. 5 && characterData.characterType == DeviceType.BEDevice) { - beCharacterData.itemType = item.itemIcon - beCharacterData.itemMultiplier = 3 - beCharacterData.itemRemainingTime = item.itemLength - - database - .userCharacterDao() - .updateBECharacterData(beCharacterData) - - } else if (item.itemIcon == ItemTypes.EvoTimer.id) { - characterData.transformationCountdown = item.itemLength - if (characterData.transformationCountdown < 0) { - characterData.transformationCountdown = 0 - } - - database - .userCharacterDao() - .updateCharacter(characterData) - - } else if (item.itemIcon == ItemTypes.LimitTimer.id) { - beCharacterData.remainingTrainingTimeInMinutes = item.itemLength - if (beCharacterData.remainingTrainingTimeInMinutes > 6000) { - beCharacterData.remainingTrainingTimeInMinutes = 6000 - } - - database - .userCharacterDao() - .updateBECharacterData(beCharacterData) - - } else if (item.itemIcon == ItemTypes.Vitals.id) { - characterData.vitalPoints = item.itemLength - if (characterData.vitalPoints < 0) { - characterData.vitalPoints = 0 - } else if (characterData.vitalPoints > 9999) { - characterData.vitalPoints = 9999 - } - - database - .userCharacterDao() - .updateCharacter(characterData) - } - - consumeItem(item.id) + private fun getItem(itemId: Long): ItemDtos.ItemsWithQuantities { + return database + .itemDao() + .getUserItem(itemId) } private fun consumeItem(itemId: Long) { 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 f9e678b..6513f26 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 @@ -1,5 +1,8 @@ package com.github.nacabaro.vbhelper.screens.itemsScreen +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid @@ -11,6 +14,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember 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 @@ -21,6 +25,7 @@ import com.github.nacabaro.vbhelper.components.getIconResource import com.github.nacabaro.vbhelper.components.getLengthResource 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 @@ -42,7 +47,13 @@ fun MyItems( } if (myItems.value.isEmpty()) { - Text("No items") + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxSize() + ) { + Text("No items") + } } else { LazyVerticalGrid( columns = GridCells.Fixed(3), @@ -67,7 +78,18 @@ fun MyItems( itemIcon = getIconResource(myItems.value[selectedElementIndex!!].itemIcon), lengthIcon = getLengthResource(myItems.value[selectedElementIndex!!].itemLength), amount = myItems.value[selectedElementIndex!!].quantity, - onClickUse = { }, + onClickUse = { + showDialog = false + navController + .navigate( + NavigationItems + .ApplyItem.route + .replace( + "{itemId}", + myItems.value[selectedElementIndex!!].id.toString() + ) + ) + }, onClickCancel = { showDialog = false } ) }