M app/src/main/java/com/github/nacabaro/vbhelper/components/CharacterEntry.kt => app/src/main/java/com/github/nacabaro/vbhelper/components/CharacterEntry.kt +19 -0
@@ 43,6 43,7 @@ import androidx.compose.ui.res.stringResource
fun CharacterEntry(
icon: BitmapData,
modifier: Modifier = Modifier,
+ cardIcon: BitmapData? = null,
obscure: Boolean = false,
disabled: Boolean = false,
shape: Shape = MaterialTheme.shapes.medium,
@@ 55,6 56,7 @@ fun CharacterEntry(
val bitmap = remember (icon.bitmap) {
if(obscure) icon.getObscuredBitmap() else icon.getBitmap()
}
+ val iconSizeMultiplier = 3
val imageBitmap = remember(bitmap) { bitmap.asImageBitmap() }
val density: Float = LocalContext.current.resources.displayMetrics.density
val dpSize = (icon.width * multiplier / density).dp
@@ 86,7 88,24 @@ fun CharacterEntry(
},
modifier = Modifier
.size(dpSize)
+ .align(Alignment.BottomCenter)
)
+
+ if (cardIcon != null) {
+ val bitmap = remember (icon.bitmap) { cardIcon.getBitmap() }
+ val iconBitmap = remember(bitmap) { bitmap.asImageBitmap() }
+ val dpSize = (icon.width * iconSizeMultiplier /density).dp
+
+ Image(
+ bitmap = iconBitmap,
+ contentDescription = "Card icon",
+ filterQuality = FilterQuality.None,
+ modifier = Modifier
+ .size(dpSize)
+ .align(Alignment.BottomEnd)
+ .padding(8.dp)
+ )
+ }
}
}
}
M app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt +12 -0
@@ 5,6 5,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.card.Card
+import com.github.nacabaro.vbhelper.dtos.CardDtos
import kotlinx.coroutines.flow.Flow
@Dao
@@ 34,4 35,15 @@ interface CardDao {
@Query("DELETE FROM Card WHERE id = :id")
suspend fun deleteCard(id: Long)
+
+ @Query("""
+ SELECT
+ c.logo as cardIcon,
+ c.logoWidth as cardIconWidth,
+ c.logoHeight as cardIconHeight
+ FROM Card c
+ JOIN CardCharacter cc ON cc.cardId = c.id
+ WHERE cc.id = :charaId
+ """)
+ fun getCardIconByCharaId(charaId: Long): Flow<CardDtos.CardIcon>
}=
\ No newline at end of file
M app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt +5 -5
@@ 53,7 53,7 @@ interface UserCharacterDao {
WHERE monId = :monId
"""
)
- suspend fun getTransformationHistory(monId: Long): List<CharacterDtos.TransformationHistory>?
+ fun getTransformationHistory(monId: Long): Flow<List<CharacterDtos.TransformationHistory>>
@Query(
"""
@@ 110,13 110,13 @@ interface UserCharacterDao {
suspend fun getCharacter(id: Long): UserCharacter
@Query("SELECT * FROM BECharacterData WHERE id = :id")
- suspend fun getBeData(id: Long): BECharacterData
+ fun getBeData(id: Long): Flow<BECharacterData>
@Query("SELECT * FROM VBCharacterData WHERE id = :id")
- suspend fun getVbData(id: Long): VBCharacterData
+ fun getVbData(id: Long): Flow<VBCharacterData>
@Query("SELECT * FROM SpecialMissions WHERE characterId = :id")
- suspend fun getSpecialMissions(id: Long): List<SpecialMissions>
+ fun getSpecialMissions(id: Long): Flow<List<SpecialMissions>>
@Query(
"""
@@ 143,7 143,7 @@ interface UserCharacterDao {
LIMIT 1
"""
)
- suspend fun getActiveCharacter(): CharacterDtos.CharacterWithSprites?
+ fun getActiveCharacter(): Flow<CharacterDtos.CharacterWithSprites?>
@Query("DELETE FROM UserCharacter WHERE id = :id")
fun deleteCharacterById(id: Long)
M app/src/main/java/com/github/nacabaro/vbhelper/dtos/CardDtos.kt => app/src/main/java/com/github/nacabaro/vbhelper/dtos/CardDtos.kt +6 -0
@@ 24,4 24,10 @@ object CardDtos {
val characterHp: Int,
val steps: Int,
)
+
+ data class CardIcon (
+ val cardIcon: ByteArray,
+ val cardIconWidth: Int,
+ val cardIconHeight: Int
+ )
}=
\ No newline at end of file
M app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt => app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt +4 -11
@@ 1,13 1,12 @@
package com.github.nacabaro.vbhelper.navigation
-import android.util.Log
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
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
@@ 99,20 98,14 @@ fun AppNavigation(
composable(NavigationItems.Scan.route) {
val characterIdString = it.arguments?.getString("characterId")
var characterId by remember { mutableStateOf(characterIdString?.toLongOrNull()) }
- Log.d("ScanScreen", "characterId: $characterId")
val launchedFromHomeScreen = (characterIdString?.toLongOrNull() == null)
if (characterId == null) {
val context = LocalContext.current.applicationContext as VBHelper
val storageRepository = StorageRepository(context.container.db)
-
- LaunchedEffect(characterId) {
- if (characterId == null) {
- val characterData = storageRepository.getActiveCharacter()
- if (characterData != null) {
- characterId = characterData.id
- }
- }
+ val characterData by storageRepository.getActiveCharacter().collectAsState(null)
+ if (characterData != null) {
+ characterId = characterData!!.id
}
}
M app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreen.kt +81 -40
@@ 11,6 11,7 @@ import androidx.compose.material3.Scaffold
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
@@ 28,9 29,7 @@ import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.utils.DeviceType
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
-import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
-import com.github.nacabaro.vbhelper.dtos.CharacterDtos
import com.github.nacabaro.vbhelper.dtos.ItemDtos
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.screens.homeScreens.screens.BEBEmHomeScreen
@@ 38,9 37,12 @@ import com.github.nacabaro.vbhelper.screens.homeScreens.screens.BEDiMHomeScreen
import com.github.nacabaro.vbhelper.screens.homeScreens.screens.VBDiMHomeScreen
import com.github.nacabaro.vbhelper.screens.itemsScreen.ObtainedItemDialog
import com.github.nacabaro.vbhelper.source.StorageRepository
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
import com.github.nacabaro.vbhelper.R
+import com.github.nacabaro.vbhelper.dtos.CardDtos
+import com.github.nacabaro.vbhelper.source.CardRepository
+import com.github.nacabaro.vbhelper.utils.BitmapData
+import kotlinx.coroutines.flow.flowOf
+import kotlin.collections.emptyList
@Composable
fun HomeScreen(
@@ 49,30 51,60 @@ fun HomeScreen(
) {
val application = LocalContext.current.applicationContext as VBHelper
val storageRepository = StorageRepository(application.container.db)
- val activeMon = remember { mutableStateOf<CharacterDtos.CharacterWithSprites?>(null) }
- val transformationHistory = remember { mutableStateOf<List<CharacterDtos.TransformationHistory>?>(null) }
- val beData = remember { mutableStateOf<BECharacterData?>(null) }
- val vbData = remember { mutableStateOf<VBCharacterData?>(null) }
- val vbSpecialMissions = remember { mutableStateOf<List<SpecialMissions>>(emptyList()) }
+ val cardRepository = CardRepository(application.container.db)
+
+ val activeMon by storageRepository
+ .getActiveCharacter()
+ .collectAsState(initial = null)
+
+ val cardIconData by (
+ activeMon
+ ?.let { chara ->
+ cardRepository.getCardIconByCharaId(chara.charId)
+ }
+ ?: flowOf<CardDtos.CardIcon?>(null)
+ ).collectAsState(initial = null)
+
+ val transformationHistory by (
+ activeMon
+ ?.let { chara ->
+ storageRepository.getTransformationHistory(chara.id)
+ }
+ ?: flowOf(emptyList())
+ ).collectAsState(initial = emptyList())
+
+ val vbSpecialMissions by (
+ activeMon
+ ?.takeIf { it.characterType == DeviceType.VBDevice }
+ ?.let { chara ->
+ storageRepository.getSpecialMissions(chara.id)
+ }
+ ?: flowOf(emptyList())
+ ).collectAsState(initial = emptyList())
+
+ val vbData by (
+ activeMon
+ ?.takeIf { it.characterType == DeviceType.VBDevice }
+ ?.let { chara ->
+ storageRepository.getCharacterVbData(chara.id)
+ }
+ ?: flowOf<VBCharacterData?>(null)
+ ).collectAsState(initial = null)
+
+ val beData by (
+ activeMon
+ ?.takeIf { it.characterType == DeviceType.BEDevice }
+ ?.let { chara ->
+ storageRepository.getCharacterBeData(chara.id)
+ }
+ ?: flowOf<BECharacterData?>(null)
+ ).collectAsState(initial = null)
+
var adventureMissionsFinished by rememberSaveable { mutableStateOf(false) }
var betaWarning by rememberSaveable { mutableStateOf(true) }
var collectedItem by remember { mutableStateOf<ItemDtos.PurchasedItem?>(null) }
var collectedCurrency by remember { mutableStateOf<Int?>(null) }
- LaunchedEffect(storageRepository, activeMon, collectedItem) {
- withContext(Dispatchers.IO) {
- activeMon.value = storageRepository.getActiveCharacter()
- if (activeMon.value != null && activeMon.value!!.characterType == DeviceType.BEDevice) {
- beData.value = storageRepository.getCharacterBeData(activeMon.value!!.id)
- transformationHistory.value = storageRepository.getTransformationHistory(activeMon.value!!.id)
- } else if (activeMon.value != null && activeMon.value!!.characterType == DeviceType.VBDevice) {
- vbData.value = storageRepository.getCharacterVbData(activeMon.value!!.id)
- vbSpecialMissions.value = storageRepository.getSpecialMissions(activeMon.value!!.id)
- transformationHistory.value = storageRepository.getTransformationHistory(activeMon.value!!.id)
- }
- }
- }
-
LaunchedEffect(true) {
homeScreenController
.didAdventureMissionsFinish {
@@ 93,7 125,7 @@ fun HomeScreen(
)
}
) { contentPadding ->
- if (activeMon.value == null || (beData.value == null && vbData.value == null) || transformationHistory.value == null) {
+ if (activeMon == null || (beData == null && vbData == null) || cardIconData == null || transformationHistory.isEmpty()) {
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
@@ 104,32 136,41 @@ fun HomeScreen(
Text(text = stringResource(R.string.adventure_empty_state))
}
} else {
- if (activeMon.value!!.isBemCard) {
+ val cardIcon = BitmapData(
+ bitmap = cardIconData!!.cardIcon,
+ width = cardIconData!!.cardIconWidth,
+ height = cardIconData!!.cardIconHeight
+ )
+
+ if (activeMon!!.isBemCard && beData != null) {
BEBEmHomeScreen(
- activeMon = activeMon.value!!,
- beData = beData.value!!,
- transformationHistory = transformationHistory.value!!,
- contentPadding = contentPadding
+ activeMon = activeMon!!,
+ beData = beData!!,
+ transformationHistory = transformationHistory,
+ contentPadding = contentPadding,
+ cardIcon = cardIcon
)
- } else if (!activeMon.value!!.isBemCard && activeMon.value!!.characterType == DeviceType.BEDevice) {
+ } else if (!activeMon!!.isBemCard && activeMon!!.characterType == DeviceType.BEDevice && beData != null) {
BEDiMHomeScreen(
- activeMon = activeMon.value!!,
- beData = beData.value!!,
- transformationHistory = transformationHistory.value!!,
- contentPadding = contentPadding
+ activeMon = activeMon!!,
+ beData = beData!!,
+ transformationHistory = transformationHistory,
+ contentPadding = contentPadding,
+ cardIcon = cardIcon
)
- } else {
+ } else if (vbData != null) {
VBDiMHomeScreen(
- activeMon = activeMon.value!!,
- vbData = vbData.value!!,
- transformationHistory = transformationHistory.value!!,
+ activeMon = activeMon!!,
+ vbData = vbData!!,
+ transformationHistory = transformationHistory,
contentPadding = contentPadding,
- specialMissions = vbSpecialMissions.value,
+ specialMissions = vbSpecialMissions,
homeScreenController = homeScreenController,
onClickCollect = { item, currency ->
collectedItem = item
collectedCurrency = currency
- }
+ },
+ cardIcon = cardIcon
)
}
}
M app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/BEBEmHomeScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/BEBEmHomeScreen.kt +2 -0
@@ 26,6 26,7 @@ import java.util.Locale
fun BEBEmHomeScreen(
activeMon: CharacterDtos.CharacterWithSprites,
beData: BECharacterData,
+ cardIcon: BitmapData,
transformationHistory: List<CharacterDtos.TransformationHistory>,
contentPadding: PaddingValues
) {
@@ 46,6 47,7 @@ fun BEBEmHomeScreen(
),
multiplier = 8,
shape = androidx.compose.material.MaterialTheme.shapes.small,
+ cardIcon = cardIcon,
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
M app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/BEDiMHomeScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/BEDiMHomeScreen.kt +2 -0
@@ 26,6 26,7 @@ import kotlin.text.format
@Composable
fun BEDiMHomeScreen(
activeMon: CharacterDtos.CharacterWithSprites,
+ cardIcon: BitmapData,
beData: BECharacterData,
transformationHistory: List<CharacterDtos.TransformationHistory>,
contentPadding: PaddingValues
@@ 45,6 46,7 @@ fun BEDiMHomeScreen(
width = activeMon.spriteWidth,
height = activeMon.spriteHeight
),
+ cardIcon = cardIcon,
multiplier = 8,
shape = androidx.compose.material.MaterialTheme.shapes.small,
modifier = Modifier
M app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/VBDiMHomeScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/VBDiMHomeScreen.kt +2 -0
@@ 31,6 31,7 @@ import androidx.compose.ui.res.stringResource
@Composable
fun VBDiMHomeScreen(
activeMon: CharacterDtos.CharacterWithSprites,
+ cardIcon: BitmapData,
vbData: VBCharacterData,
specialMissions: List<SpecialMissions>,
homeScreenController: HomeScreenControllerImpl,
@@ 53,6 54,7 @@ fun VBDiMHomeScreen(
width = activeMon.spriteWidth,
height = activeMon.spriteHeight
),
+ cardIcon = cardIcon,
multiplier = 8,
shape = androidx.compose.material.MaterialTheme.shapes.small,
modifier = Modifier
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 +12 -3
@@ 11,6 11,8 @@ import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
import com.github.nacabaro.vbhelper.dtos.ItemDtos
import com.github.nacabaro.vbhelper.utils.DeviceType
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ 52,9 54,16 @@ class ItemsScreenControllerImpl (
var vbCharacterData: VBCharacterData? = null
if (characterData.characterType == DeviceType.BEDevice) {
- beCharacterData = database.userCharacterDao().getBeData(characterId)
+ beCharacterData = database
+ .userCharacterDao()
+ .getBeData(characterId)
+ .firstOrNull()
+
} else if (characterData.characterType == DeviceType.VBDevice) {
- vbCharacterData = database.userCharacterDao().getVbData(characterId)
+ vbCharacterData = database
+ .userCharacterDao()
+ .getVbData(characterId)
+ .firstOrNull()
}
if (
@@ 161,7 170,7 @@ class ItemsScreenControllerImpl (
var firstUnavailableMissionSlot: Long = 0
var watchId = 0
- for ((index, mission) in availableSpecialMissions.withIndex()) {
+ for ((index, mission) in availableSpecialMissions.first().withIndex()) {
if (
mission.status == SpecialMission.Status.UNAVAILABLE
) {
M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt +5 -1
@@ 55,6 55,7 @@ class ToNfcConverter(
val vbData = database
.userCharacterDao()
.getVbData(characterId)
+ .first()
val paddedTransformationArray = generateTransformationHistory(characterId, 9)
@@ 116,6 117,7 @@ class ToNfcConverter(
val specialMissions = database
.userCharacterDao()
.getSpecialMissions(characterId)
+ .first()
val watchSpecialMissions = specialMissions.map {
SpecialMission(
@@ 175,6 177,7 @@ class ToNfcConverter(
val beData = database
.userCharacterDao()
.getBeData(characterId)
+ .first()
val paddedTransformationArray = generateTransformationHistory(characterId)
@@ 237,7 240,8 @@ class ToNfcConverter(
): Array<NfcCharacter.Transformation> {
val transformationHistory = database
.userCharacterDao()
- .getTransformationHistory(characterId)!!
+ .getTransformationHistory(characterId)
+ .first()
.map {
val date = Date(it.transformationDate)
val calendar = android.icu.util.GregorianCalendar(TimeZone.getTimeZone("UTC"))
A app/src/main/java/com/github/nacabaro/vbhelper/source/CardRepository.kt => app/src/main/java/com/github/nacabaro/vbhelper/source/CardRepository.kt +15 -0
@@ 0,0 1,15 @@
+package com.github.nacabaro.vbhelper.source
+
+import com.github.nacabaro.vbhelper.database.AppDatabase
+import com.github.nacabaro.vbhelper.dtos.CardDtos
+import kotlinx.coroutines.flow.Flow
+
+class CardRepository (
+ private val db: AppDatabase
+) {
+ fun getCardIconByCharaId(charaId: Long): Flow<CardDtos.CardIcon> {
+ return db
+ .cardDao()
+ .getCardIconByCharaId(charaId = charaId)
+ }
+}<
\ 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 +5 -5
@@ 19,19 19,19 @@ class StorageRepository (
return db.userCharacterDao().getCharacterWithSprites(id)
}
- suspend fun getCharacterBeData(id: Long): BECharacterData {
+ fun getCharacterBeData(id: Long): Flow<BECharacterData> {
return db.userCharacterDao().getBeData(id)
}
- suspend fun getTransformationHistory(characterId: Long): List<CharacterDtos.TransformationHistory>? {
+ fun getTransformationHistory(characterId: Long): Flow<List<CharacterDtos.TransformationHistory>> {
return db.userCharacterDao().getTransformationHistory(characterId)
}
- suspend fun getCharacterVbData(id: Long): VBCharacterData {
+ fun getCharacterVbData(id: Long): Flow<VBCharacterData> {
return db.userCharacterDao().getVbData(id)
}
- suspend fun getSpecialMissions(id: Long): List<SpecialMissions> {
+ fun getSpecialMissions(id: Long): Flow<List<SpecialMissions>> {
return db.userCharacterDao().getSpecialMissions(id)
}
@@ 39,7 39,7 @@ class StorageRepository (
return db.itemDao().getItem(id)
}
- suspend fun getActiveCharacter(): CharacterDtos.CharacterWithSprites? {
+ fun getActiveCharacter(): Flow<CharacterDtos.CharacterWithSprites?> {
return db.userCharacterDao().getActiveCharacter()
}
M gradle/libs.versions.toml => gradle/libs.versions.toml +1 -1
@@ 1,5 1,5 @@
[versions]
-agp = "8.13.1"
+agp = "8.13.2"
datastore = "1.1.2"
kotlin = "2.0.0"
coreKtx = "1.15.0"