Dex stuff

- Added dex domain model, and rearranged class
- Added dex functionality to the dex screen, and updated the corresponding controller
This commit is contained in:
Nacho 2025-01-17 21:12:41 +01:00
parent 586d6c01ef
commit 88163684ca
25 changed files with 189 additions and 77 deletions

View File

@ -18,21 +18,20 @@ import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.Dim
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.domain.characters.Dex
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
import com.github.nacabaro.vbhelper.navigation.AppNavigationHandlers
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.SettingsScreenController
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
import com.github.nacabaro.vbhelper.utils.DeviceType
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.util.Date
import java.util.GregorianCalendar
class MainActivity : ComponentActivity() {
@ -113,7 +112,7 @@ class MainActivity : ComponentActivity() {
Log.i("MainActivity", "Card name: ${card is BemCard}")
val dimModel = Dim(
val cardModel = Card(
dimId = card.header.dimId,
logo = card.spriteData.sprites[0].pixelData,
name = card.spriteData.text, // TODO Make user write card name
@ -125,7 +124,7 @@ class MainActivity : ComponentActivity() {
val dimId = storageRepository
.dimDao()
.insertNewDim(dimModel)
.insertNewDim(cardModel)
val characters = card.characterStats.characterEntries
@ -216,7 +215,6 @@ class MainActivity : ComponentActivity() {
//
/*
TODO:
- Make it able to detect the different model of watches
- Support for regular VB
The good news is that the theory behind inserting to the database should be working
@ -255,8 +253,8 @@ class MainActivity : ComponentActivity() {
activityLevel = nfcCharacter.value!!.activityLevel.toInt(),
heartRateCurrent = nfcCharacter.value!!.heartRateCurrent.toInt(),
characterType = when (nfcCharacter.value) {
is BENfcCharacter -> com.github.nacabaro.vbhelper.domain.DeviceType.BEDevice
else -> com.github.nacabaro.vbhelper.domain.DeviceType.VBDevice
is BENfcCharacter -> DeviceType.BEDevice
else -> DeviceType.VBDevice
},
isActive = true
)
@ -307,12 +305,16 @@ class MainActivity : ComponentActivity() {
val date = GregorianCalendar(item.year.toInt(), item.month.toInt(), item.day.toInt())
.time
.time
storageRepository
.characterDao()
.insertTransformation(characterId, item.toCharIndex.toInt(), dimData.id, date)
}
}
storageRepository
.dexDao()
.insertCharacter(item.toCharIndex.toInt(), dimData.id, date)
}
}
} else if (nfcCharacter.value is VBNfcCharacter) {
return "Not implemented yet"
}

View File

@ -2,6 +2,7 @@ package com.github.nacabaro.vbhelper.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@ -23,6 +24,8 @@ import com.github.nacabaro.vbhelper.utils.getBitmap
fun DexDiMEntry(
name: String,
logo: BitmapData,
obtainedCharacters: Int,
totalCharacters: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
@ -50,11 +53,21 @@ fun DexDiMEntry(
.padding(8.dp)
.size(dpSize)
)
Column(
modifier = Modifier
.padding(8.dp)
) {
Text(
text = name,
modifier = Modifier
.padding(8.dp)
)
Text(
text = "$obtainedCharacters of $totalCharacters characters obtained",
fontFamily = MaterialTheme.typography.labelSmall.fontFamily,
fontSize = MaterialTheme.typography.labelSmall.fontSize,
modifier = Modifier
)
}
}
}
}

View File

@ -3,10 +3,9 @@ package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
import java.util.GregorianCalendar
@Dao
interface CharacterDao {
@ -28,15 +27,17 @@ interface CharacterDao {
@Query("SELECT * FROM Sprites")
suspend fun getAllSprites(): List<Sprites>
@Query("""
@Query(
"""
SELECT
d.dimId as cardId,
c.monIndex as charId
FROM Character c
JOIN UserCharacter uc ON c.id = uc.charId
JOIN Dim d ON c.dimId = d.id
JOIN Card d ON c.dimId = d.id
WHERE uc.id = :charId
""")
"""
)
suspend fun getCharacterInfo(charId: Long): CharacterDtos.DiMInfo
@Query("""

View File

@ -0,0 +1,44 @@
package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Query
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
@Dao
interface DexDao {
@Query("""
INSERT OR IGNORE INTO Dex(id, discoveredOn)
VALUES (
(SELECT id FROM Character WHERE monIndex = :charIndex AND dimId = :cardId),
:discoveredOn
)
""")
fun insertCharacter(charIndex: Int, cardId: Long, discoveredOn: Long)
@Query("""
SELECT
c.id AS id,
c.sprite1 AS spriteIdle,
c.spritesWidth AS spriteWidth,
c.spritesHeight AS spriteHeight,
d.discoveredOn AS discoveredOn
FROM character c
LEFT JOIN dex d ON c.id = d.id
WHERE c.dimId = :cardId
""")
suspend fun getSingleCardProgress(cardId: Long): List<CharacterDtos.CardProgress>
@Query("""
SELECT
c.id as cardId,
c.name as cardName,
c.logo as cardLogo,
c.logoWidth as logoWidth,
c.logoHeight as logoHeight,
(SELECT COUNT(*) FROM Character cc WHERE cc.dimId = c.id) AS totalCharacters,
(SELECT COUNT(*) FROM Dex d JOIN Character cc ON d.id = cc.id WHERE cc.dimId = c.id AND d.discoveredOn IS NOT NULL) AS obtainedCharacters
FROM Card c
""")
suspend fun getCardsWithProgress(): List<CardDtos.CardProgress>
}

View File

@ -4,16 +4,16 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.Dim
import com.github.nacabaro.vbhelper.domain.characters.Card
@Dao
interface DiMDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertNewDim(dim: Dim): Long
suspend fun insertNewDim(card: Card): Long
@Query("SELECT * FROM Dim")
suspend fun getAllDims(): List<Dim>
@Query("SELECT * FROM Card")
suspend fun getAllDims(): List<Card>
@Query("SELECT * FROM Dim WHERE dimId = :id")
fun getDimById(id: Int): Dim?
@Query("SELECT * FROM Card WHERE dimId = :id")
fun getDimById(id: Int): Card?
}

View File

@ -34,7 +34,8 @@ interface UserCharacterDao {
""")
fun getTransformationHistory(monId: Long): List<CharacterDtos.TransformationHistory>?
@Query("""
@Query(
"""
SELECT
uc.*,
c.sprite1 AS spriteIdle,
@ -43,8 +44,9 @@ interface UserCharacterDao {
d.isBEm as isBemCard
FROM UserCharacter uc
JOIN Character c ON uc.charId = c.id
JOIN Dim d ON c.dimId = d.id
""")
JOIN Card d ON c.dimId = d.id
"""
)
suspend fun getAllCharacters(): List<CharacterDtos.CharacterWithSprites>
@Query("SELECT * FROM UserCharacter WHERE id = :id")
@ -53,7 +55,8 @@ interface UserCharacterDao {
@Query("SELECT * FROM BECharacterData WHERE id = :id")
suspend fun getBeData(id: Long): BECharacterData
@Query("""
@Query(
"""
SELECT
uc.*,
c.sprite1 AS spriteIdle,
@ -62,10 +65,11 @@ interface UserCharacterDao {
d.isBEm as isBemCard
FROM UserCharacter uc
JOIN Character c ON uc.charId = c.id
JOIN Dim d ON c.dimId = d.id
JOIN Card d ON c.dimId = d.id
WHERE uc.isActive = 1
LIMIT 1
""")
"""
)
suspend fun getActiveCharacter(): CharacterDtos.CharacterWithSprites?
@Query("DELETE FROM UserCharacter WHERE id = :id")

View File

@ -3,11 +3,13 @@ package com.github.nacabaro.vbhelper.database
import androidx.room.Database
import androidx.room.RoomDatabase
import com.github.nacabaro.vbhelper.daos.CharacterDao
import com.github.nacabaro.vbhelper.daos.DexDao
import com.github.nacabaro.vbhelper.daos.DiMDao
import com.github.nacabaro.vbhelper.daos.UserCharacterDao
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.domain.Dim
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.Sprites
import com.github.nacabaro.vbhelper.domain.characters.Dex
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
@ -15,16 +17,18 @@ import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
@Database(
version = 1,
entities = [
Dim::class,
Card::class,
Character::class,
Sprites::class,
UserCharacter::class,
BECharacterData::class,
TransformationHistory::class
TransformationHistory::class,
Dex::class
]
)
abstract class AppDatabase : RoomDatabase() {
abstract fun dimDao(): DiMDao
abstract fun characterDao(): CharacterDao
abstract fun userCharacterDao(): UserCharacterDao
abstract fun dexDao(): DexDao
}

View File

@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.domain
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.characters.Card
@Entity(
foreignKeys = [
@ -13,7 +14,7 @@ import androidx.room.PrimaryKey
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Dim::class,
entity = Card::class,
parentColumns = ["id"],
childColumns = ["dimId"],
onDelete = ForeignKey.CASCADE

View File

@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.domain
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.characters.Character
@Entity(
foreignKeys = [

View File

@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.domain
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.characters.Character
@Entity(
foreignKeys = [

View File

@ -1,11 +1,10 @@
package com.github.nacabaro.vbhelper.domain
package com.github.nacabaro.vbhelper.domain.characters
import android.icu.text.ListFormatter.Width
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity
data class Dim(
data class Card(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val dimId: Int,

View File

@ -1,4 +1,4 @@
package com.github.nacabaro.vbhelper.domain
package com.github.nacabaro.vbhelper.domain.characters
import androidx.room.Entity
import androidx.room.PrimaryKey
@ -7,7 +7,7 @@ import androidx.room.ForeignKey
@Entity(
foreignKeys = [
ForeignKey(
entity = Dim::class,
entity = Card::class,
parentColumns = ["id"],
childColumns = ["dimId"],
onDelete = ForeignKey.CASCADE

View File

@ -0,0 +1,20 @@
package com.github.nacabaro.vbhelper.domain.characters
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@Entity(
foreignKeys = [
ForeignKey(
entity = Character::class,
parentColumns = ["id"],
childColumns = ["id"],
onDelete = ForeignKey.CASCADE
)
]
)
data class Dex(
@PrimaryKey val id: Long = 0,
val discoveredOn: Long
)

View File

@ -3,7 +3,7 @@ package com.github.nacabaro.vbhelper.domain.device_data
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.domain.characters.Character
@Entity(
foreignKeys = [

View File

@ -4,8 +4,8 @@ import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.domain.DeviceType
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.utils.DeviceType
import com.github.nacabaro.vbhelper.domain.characters.Character
@Entity(
foreignKeys = [

View File

@ -0,0 +1,13 @@
package com.github.nacabaro.vbhelper.dtos
object CardDtos {
data class CardProgress (
val cardId: Long,
val cardName: String,
val cardLogo: ByteArray,
val logoWidth: Int,
val logoHeight: Int,
val totalCharacters: Int,
val obtainedCharacters: Int,
)
}

View File

@ -1,7 +1,7 @@
package com.github.nacabaro.vbhelper.dtos
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.domain.DeviceType
import com.github.nacabaro.vbhelper.utils.DeviceType
object CharacterDtos {
@ -43,4 +43,12 @@ object CharacterDtos {
val monIndex: Int,
val transformationDate: Long
)
data class CardProgress(
val id: Long,
val spriteIdle: ByteArray,
val spriteWidth: Int,
val spriteHeight: Int,
val discoveredOn: Long?
)
}

View File

@ -81,12 +81,11 @@ fun AppNavigation(
)
}
composable(NavigationItems.CardView.route) {
val dimId = it.arguments?.getString("dimId")
Log.d("dimId", dimId.toString())
if (dimId != null) {
val cardId = it.arguments?.getString("cardId")
if (cardId != null) {
DiMScreen(
navController = navController,
dimId = dimId.toInt()
dimId = cardId.toLong()
)
}
}

View File

@ -14,6 +14,6 @@ sealed class NavigationItems (
object Storage : NavigationItems("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
object Settings : NavigationItems("Settings", R.drawable.baseline_settings_24, "Settings")
object Viewer : NavigationItems("Viewer", R.drawable.baseline_image_24, "Viewer")
object CardView : NavigationItems("Card/{dimId}", R.drawable.baseline_image_24, "Card")
object CardView : NavigationItems("Card/{cardId}", R.drawable.baseline_image_24, "Card")
object Items : NavigationItems("Items", R.drawable.baseline_data_24, "Items")
}

View File

@ -18,7 +18,8 @@ import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.components.DexDiMEntry
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.Dim
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.source.DexRepository
import kotlinx.coroutines.launch
@ -31,19 +32,19 @@ fun DexScreen(
val application = LocalContext.current.applicationContext as VBHelper
val dexRepository = DexRepository(application.container.db)
val dimList = remember { mutableStateOf<List<Dim>>(emptyList()) }
val cardList = remember { mutableStateOf<List<CardDtos.CardProgress>>(emptyList()) }
LaunchedEffect(dexRepository) {
coroutineScope.launch {
val newDimList = dexRepository.getAllDims()
dimList.value = newDimList // Replace the entire list atomically
cardList.value = newDimList // Replace the entire list atomically
}
}
Scaffold (
topBar = {
TopBanner(
text = "Discovered Digimon",
text = "Discovered characters",
onGearClick = {
navController.navigate(NavigationItems.Viewer.route)
}
@ -54,11 +55,11 @@ fun DexScreen(
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
) {
items(dimList.value) {
items(cardList.value) {
DexDiMEntry(
name = it.name,
name = it.cardName,
logo = BitmapData(
bitmap = it.logo,
bitmap = it.cardLogo,
width = it.logoWidth,
height = it.logoHeight
),
@ -67,9 +68,11 @@ fun DexScreen(
.navigate(
NavigationItems
.CardView.route
.replace("{dimId}", "${it.id}")
.replace("{cardId}", "${it.cardId}")
)
},
obtainedCharacters = it.obtainedCharacters,
totalCharacters = it.totalCharacters,
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)

View File

@ -1,6 +1,5 @@
package com.github.nacabaro.vbhelper.screens
import android.util.Log
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
@ -15,21 +14,22 @@ import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.components.CharacterEntry
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
import com.github.nacabaro.vbhelper.source.DexRepository
import kotlinx.coroutines.launch
@Composable
fun DiMScreen(
navController: NavController,
dimId: Int
dimId: Long
) {
val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper
val dexRepository = DexRepository(application.container.db)
val characterList = remember { mutableStateOf<List<Character>>(emptyList()) }
val characterList = remember { mutableStateOf<List<CharacterDtos.CardProgress>>(emptyList()) }
LaunchedEffect(dexRepository) {
coroutineScope.launch {
@ -41,7 +41,7 @@ fun DiMScreen(
Scaffold (
topBar = {
TopBanner(
text = "Discovered Digimon",
text = "Discovered characters",
onBackClick = {
navController.popBackStack()
}
@ -55,11 +55,11 @@ fun DiMScreen(
items(characterList.value) { character ->
CharacterEntry(
onClick = { },
obscure = true,
obscure = character.discoveredOn == null,
icon = BitmapData(
bitmap = character.sprite1,
width = character.spritesWidth,
height = character.spritesHeight
bitmap = character.spriteIdle,
width = character.spriteWidth,
height = character.spriteHeight,
),
)
}

View File

@ -17,7 +17,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.DeviceType
import com.github.nacabaro.vbhelper.utils.DeviceType
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
import com.github.nacabaro.vbhelper.dtos.CharacterDtos

View File

@ -1,18 +1,18 @@
package com.github.nacabaro.vbhelper.source
import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.domain.Character
import com.github.nacabaro.vbhelper.domain.Dim
import kotlinx.coroutines.flow.Flow
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
class DexRepository (
private val db: AppDatabase
) {
suspend fun getAllDims(): List<Dim> {
return db.dimDao().getAllDims()
suspend fun getAllDims(): List<CardDtos.CardProgress> {
return db.dexDao().getCardsWithProgress()
}
suspend fun getCharactersByDimId(dimId: Int): List<Character> {
return db.characterDao().getCharacterByDimId(dimId)
suspend fun getCharactersByDimId(cardId: Long): List<CharacterDtos.CardProgress> {
return db.dexDao().getSingleCardProgress(cardId)
}
}

View File

@ -7,7 +7,6 @@ import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.be.FirmwareVersion
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.DeviceType
import com.github.nacabaro.vbhelper.source.StorageRepository
import java.util.Date

View File

@ -1,4 +1,4 @@
package com.github.nacabaro.vbhelper.domain
package com.github.nacabaro.vbhelper.utils
enum class DeviceType {
VBDevice,