~cytrogen/vbhelper

bc02689850d962e11ea140a9ec7d6c06322f5d15 — nacabaro 1 year, 3 months ago 59033e6 + e8f441b
Merge pull request #4 from nacabaro/ui/get_character_details

Few things, again!
M app/src/main/java/com/github/nacabaro/vbhelper/components/TopBanner.kt => app/src/main/java/com/github/nacabaro/vbhelper/components/TopBanner.kt +44 -6
@@ 1,25 1,63 @@
package com.github.nacabaro.vbhelper.components

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
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.unit.dp
import androidx.compose.ui.unit.sp
import com.github.nacabaro.vbhelper.R

@Composable
fun TopBanner(
    text: String,
    modifier: Modifier = Modifier
    modifier: Modifier = Modifier,
    onGearClick: (() -> Unit)? = null,
    onBackClick: (() -> Unit)? = null
) {
    Text(
        text = text,
        textAlign = TextAlign.Center,
        fontSize = 24.sp,
    Box( // Use Box to overlay elements
        modifier = modifier
            .fillMaxWidth()
            .padding(16.dp)
    )
    ) {
        Text(
            text = text,
            textAlign = TextAlign.Center,
            fontSize = 24.sp,
            modifier = Modifier
                .align(Alignment.Center) // Center the text
        )
        if (onGearClick != null) {
            IconButton(
                onClick = onGearClick,
                modifier = Modifier
                    .align(Alignment.CenterEnd) // Place gear icon at the end
            ) {
                Icon(
                    painter = painterResource(R.drawable.baseline_settings_24), // Use a gear icon
                    contentDescription = "Settings"
                )
            }
        }

        if (onBackClick != null) {
            IconButton(
                onClick = onBackClick,
                modifier = Modifier
                    .align(Alignment.CenterStart) // Place gear icon at the end
            ) {
                Icon(
                    painter = painterResource(R.drawable.baseline_arrow_back_24), // Use a gear icon
                    contentDescription = "Settings"
                )
            }
        }
    }
}

M app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt => app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt +9 -1
@@ 11,6 11,7 @@ import com.github.nacabaro.vbhelper.screens.BattlesScreen
import com.github.nacabaro.vbhelper.screens.DexScreen
import com.github.nacabaro.vbhelper.screens.HomeScreen
import com.github.nacabaro.vbhelper.screens.ScanScreen
import com.github.nacabaro.vbhelper.screens.SettingsScreen
import com.github.nacabaro.vbhelper.screens.StorageScreen

@Composable


@@ 36,7 37,9 @@ fun AppNavigation(
                BattlesScreen()
            }
            composable(BottomNavItem.Home.route) {
                HomeScreen()
                HomeScreen(
                    navController = navController
                )
            }
            composable(BottomNavItem.Storage.route) {
                StorageScreen()


@@ 52,6 55,11 @@ fun AppNavigation(
            composable(BottomNavItem.Dex.route) {
                DexScreen()
            }
            composable(BottomNavItem.Settings.route) {
                SettingsScreen(
                    navController = navController
                )
            }
        }
    }
}

M app/src/main/java/com/github/nacabaro/vbhelper/navigation/BottomNavItem.kt => app/src/main/java/com/github/nacabaro/vbhelper/navigation/BottomNavItem.kt +2 -1
@@ 8,8 8,9 @@ sealed class BottomNavItem (
    var label: String
) {
    object Scan : BottomNavItem("Scan", R.drawable.baseline_nfc_24, "Scan")
    object Battles : BottomNavItem("Battles", R.drawable.baseline_swords_24, "Battles")
    object Battles : BottomNavItem("Battle", R.drawable.baseline_swords_24, "Battle")
    object Home : BottomNavItem("Home", R.drawable.baseline_cottage_24, "Home")
    object Dex : BottomNavItem("Dex", R.drawable.baseline_menu_book_24, "Dex")
    object Storage : BottomNavItem("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
    object Settings : BottomNavItem("Settings", R.drawable.baseline_settings_24, "Settings")
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/screens/HomeScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/HomeScreen.kt +27 -2
@@ 1,9 1,34 @@
package com.github.nacabaro.vbhelper.screens

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.navigation.BottomNavItem

@Composable
fun HomeScreen() {
    Text("Home Screen")
fun HomeScreen(
    navController: NavController
) {
    Scaffold (
        topBar = {
            TopBanner(
                text = "VB Helper",
                onGearClick = {
                    navController.navigate(BottomNavItem.Settings.route)
                }
            )
        }
    ) { contentPadding ->
        Box (
            modifier = Modifier
                .padding(top = contentPadding.calculateTopPadding())
        ) {
            Text("Home Screen")
        }
    }
}

A app/src/main/java/com/github/nacabaro/vbhelper/screens/SettingsScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/SettingsScreen.kt +96 -0
@@ 0,0 1,96 @@
package com.github.nacabaro.vbhelper.screens

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
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.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner

@Composable
fun SettingsScreen(
    navController: NavController
) {
    Scaffold (
        topBar = {
            TopBanner(
                text = "Settings",
                onBackClick = {
                    navController.popBackStack()
                }
            )
        },
        modifier = Modifier
            .fillMaxSize()
    ) { contentPadding ->
        Column (
            modifier = Modifier
                .padding(top = contentPadding.calculateTopPadding())
                .fillMaxSize()
                .verticalScroll(rememberScrollState())
        ) {
            SettingsSection("General")
            SettingsEntry(title = "Import VB key", description = "Import standard vital bracelet keys") { }
            SettingsEntry(title = "Import VB Characters key", description = "Import standard vital bracelet keys") { }
            SettingsEntry(title = "Import VB BE key", description = "Import standard vital bracelet keys") { }
            SettingsEntry(title = "Import transform functions", description = "Import standard vital bracelet keys") { }
            SettingsEntry(title = "Import decryption key", description = "Import standard vital bracelet keys") { }
            SettingsSection("DiM/BEm management")
            SettingsEntry(title = "Import DiM card", description = "Import DiM card file") { }
            SettingsEntry(title = "Import BEm card", description = "Import BEm card file") { }
            SettingsSection("About and credits")
            SettingsEntry(title = "Credits", description = "Credits") { }
            SettingsEntry(title = "About", description = "About") { }
        }
    }
}

@Composable
fun SettingsEntry(
    title: String,
    description: String,
    onClick: () -> Unit
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clickable { onClick() }
            .padding(16.dp)
    ) {
        Text(text = title)
        Text(
            text = description,
            fontSize = 12.sp,
            color = MaterialTheme.colorScheme.outline
        )
    }
}

@Composable
fun SettingsSection(
    title: String
) {
    Box (
        modifier = Modifier
            .padding(start = 16.dp)
    ) {
        Text(
            text = title,
            fontSize = 12.sp,
            fontWeight = FontWeight.Bold,
            color = MaterialTheme.colorScheme.primary
        )
    }
}
\ 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 +83 -6
@@ 4,6 4,7 @@ import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding


@@ 12,7 13,10 @@ import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardElevation
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text


@@ 23,12 27,16 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
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.res.painterResource
import androidx.compose.ui.text.style.TextAlign
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.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper


@@ 45,6 53,7 @@ fun StorageScreen() {
    val storageRepository = StorageRepository(application.container.db)
    val monList = remember { mutableStateListOf<TemporaryCharacterData>() }

    var selectedCharacter by remember { mutableStateOf<Long?>(null) }

    LaunchedEffect(storageRepository) {
        coroutineScope.launch {


@@ 60,11 69,19 @@ fun StorageScreen() {
        topBar = { TopBanner(text = "My Digimon") }
    ) { contentPadding ->
        if (monList.isEmpty()) {
            Text(
                text = "Nothing to see here",
            Column (
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center,
                modifier = Modifier
                    .padding(8.dp)
            )
                    .padding(contentPadding)
                    .fillMaxSize()
            ) {
                Text(
                    text = "Nothing to see here",
                    textAlign = TextAlign.Center,
                    modifier = Modifier
                )
            }
        }

        LazyVerticalGrid(


@@ 74,12 91,22 @@ fun StorageScreen() {
                .padding(top = contentPadding.calculateTopPadding())
        ) {
            items(monList) { index ->
                var showDialog by rememberSaveable { mutableStateOf(false) }

                StorageEntry(
                    name = index.dimId.toString() + " - " + index.charIndex.toString(),
                    icon = R.drawable.ic_launcher_foreground,
                    onClick = { selectedCharacter = index.id },
                    modifier = Modifier
                        .padding(8.dp)
                )

                if (selectedCharacter != null) {
                    StorageDialog(
                        characterId = selectedCharacter!!,
                        onDismissRequest = { selectedCharacter = null }
                    )
                }
            }
        }
    }


@@ 89,14 116,16 @@ fun StorageScreen() {
fun StorageEntry(
    name: String,
    icon: Int,
    onClick: () -> Unit = {},
    modifier: Modifier = Modifier
) {
    Card (
    Card(
        shape = MaterialTheme.shapes.medium,
        onClick = onClick,
        modifier = modifier
            .padding(8.dp)
    ) {
        Column (
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = Modifier
                .fillMaxSize()


@@ 116,4 145,52 @@ fun StorageEntry(
            )
        }
    }
}

@Composable
fun StorageDialog(
    characterId: Long,
    onDismissRequest: () -> Unit
) {
    val coroutineScope = rememberCoroutineScope()
    val application = LocalContext.current.applicationContext as VBHelper
    val storageRepository = StorageRepository(application.container.db)
    val character = remember { mutableStateOf<TemporaryCharacterData?>(null) }

    LaunchedEffect(storageRepository) {
        coroutineScope.launch {
            character.value = storageRepository.getSingleCharacter(characterId)
        }
    }

    Dialog(
        onDismissRequest = onDismissRequest,
        properties = DialogProperties(
            dismissOnBackPress = true,
            dismissOnClickOutside = true
        )
    ) {
        Card(
            shape = RoundedCornerShape(16.dp)
        ) {
            Column (
                modifier = Modifier
                    .padding(16.dp)
            ) {
                if (character.value != null) {
                    Text(
                        text = character.value?.toString() ?: "Loading...",
                        textAlign = TextAlign.Center,
                        modifier = Modifier
                            .padding(8.dp)
                    )
                }
                Button(
                    onClick = onDismissRequest
                ) {
                    Text(text = "Close")
                }
            }
        }
    }
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt => app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt +4 -0
@@ 9,4 9,8 @@ class StorageRepository (
    suspend fun getAllCharacters(): List<TemporaryCharacterData> {
        return db.temporaryMonsterDao().getAllCharacters()
    }

    suspend fun getSingleCharacter(id: Long): TemporaryCharacterData {
        return db.temporaryMonsterDao().getCharacter(id)
    }
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/temporary_daos/TemporaryMonsterDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/temporary_daos/TemporaryMonsterDao.kt +3 -0
@@ 24,4 24,7 @@ interface TemporaryMonsterDao {

    @Query("SELECT * FROM TemporaryCharacterData")
    suspend fun getAllCharacters(): List<TemporaryCharacterData>

    @Query("SELECT * FROM TemporaryCharacterData WHERE id = :id")
    suspend fun getCharacter(id: Long): TemporaryCharacterData
}
\ No newline at end of file

A app/src/main/res/drawable/baseline_arrow_back_24.xml => app/src/main/res/drawable/baseline_arrow_back_24.xml +5 -0
@@ 0,0 1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
      
    <path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
    
</vector>

A app/src/main/res/drawable/baseline_settings_24.xml => app/src/main/res/drawable/baseline_settings_24.xml +5 -0
@@ 0,0 1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
      
    <path android:fillColor="@android:color/white" android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
    
</vector>