~cytrogen/vbhelper

b4a73031e7eb8cfc240dfefe1277eca35ae052d3 — Nacho 1 year, 3 months ago 3e41f82
Working items
- Click on use item > then choose the mon you want to apply the item to
M app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt => app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt +10 -2
@@ 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 {

M app/src/main/java/com/github/nacabaro/vbhelper/components/ItemElement.kt => app/src/main/java/com/github/nacabaro/vbhelper/components/ItemElement.kt +1 -0
@@ 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
    }
}

M app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt +8 -0
@@ 22,6 22,14 @@ interface ItemDao {
    suspend fun getAllUserItems(): List<ItemDtos.ItemsWithQuantities>

    @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
        WHERE itemId = :itemId

M app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt => app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt +14 -0
@@ 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()
                    )
                }
            }
        }
    }
}

M app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt => app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt +1 -0
@@ 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

M app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt +0 -2
@@ 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

A app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt +90 -0
@@ 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<List<CharacterDtos.CharacterWithSprites>>(emptyList())
    }

    var selectedCharacter by remember { mutableStateOf<Long?>(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

M app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenController.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenController.kt +1 -2
@@ 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

M app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenControllerImpl.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsScreenControllerImpl.kt +81 -46
@@ 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
    }

        if (item.itemIcon in 1 .. 5 && characterData.characterType == DeviceType.BEDevice) {
            beCharacterData.itemType = item.itemIcon
            beCharacterData.itemMultiplier = 3
            beCharacterData.itemRemainingTime = item.itemLength
    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

            database
                .userCharacterDao()
                .updateBECharacterData(beCharacterData)
                if (characterData.characterType == DeviceType.BEDevice) {
                    beCharacterData = database.userCharacterDao().getBeData(characterId)
                } else {
                    TODO("Not implemented")
                    //vbCharacterData = database.userCharacterDao().getVbData(characterId)
                }

        } else if (item.itemIcon == ItemTypes.EvoTimer.id) {
            characterData.transformationCountdown = item.itemLength
            if (characterData.transformationCountdown < 0) {
                characterData.transformationCountdown = 0
            }
                if (item.itemIcon in 1 .. 5 && characterData.characterType == DeviceType.BEDevice) {
                    beCharacterData.itemType = item.itemIcon
                    beCharacterData.itemMultiplier = 3
                    beCharacterData.itemRemainingTime = item.itemLength

            database
                .userCharacterDao()
                .updateCharacter(characterData)
                    database
                        .userCharacterDao()
                        .updateBECharacterData(beCharacterData)

        } else if (item.itemIcon == ItemTypes.LimitTimer.id) {
            beCharacterData.remainingTrainingTimeInMinutes = item.itemLength
            if (beCharacterData.remainingTrainingTimeInMinutes > 6000) {
                beCharacterData.remainingTrainingTimeInMinutes = 6000
            }
                } else if (item.itemIcon == ItemTypes.EvoTimer.id) {
                    characterData.transformationCountdown += item.itemLength
                    if (characterData.transformationCountdown < 0) {
                        characterData.transformationCountdown = 0
                    }

            database
                .userCharacterDao()
                .updateBECharacterData(beCharacterData)
                    // VB does not like it when the transformationCountdown is 0
                    if (characterData.characterType == DeviceType.VBDevice &&
                        characterData.transformationCountdown <= 0 ) {
                        characterData.transformationCountdown = 1
                    }

        } 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)

                } else if (item.itemIcon == ItemTypes.LimitTimer.id) {
                    beCharacterData.remainingTrainingTimeInMinutes += item.itemLength
                    if (beCharacterData.remainingTrainingTimeInMinutes > 6000) {
                        beCharacterData.remainingTrainingTimeInMinutes = 6000
                    }

            database
                .userCharacterDao()
                .updateCharacter(characterData)
                    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()
                }
            }
        }
    }

        consumeItem(item.id)
    private fun getItem(itemId: Long): ItemDtos.ItemsWithQuantities {
        return database
            .itemDao()
            .getUserItem(itemId)
    }

    private fun consumeItem(itemId: Long) {

M app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt +24 -2
@@ 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 }
                    )
                }