mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-10-01 15:41:36 +00:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
489e27b038 | ||
|
|
6be167bbed | ||
|
|
61dfc2ce0d | ||
|
|
dce186737d | ||
|
|
cf272e8030 | ||
|
|
ffa6958a89 |
@@ -15,7 +15,7 @@ android {
|
|||||||
minSdk = 28
|
minSdk = 28
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 1
|
versionCode = 1
|
||||||
versionName = "Alpha 0.6.1"
|
versionName = "Alpha 0.6.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardColors
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -44,6 +45,9 @@ fun CharacterEntry(
|
|||||||
disabled: Boolean = false,
|
disabled: Boolean = false,
|
||||||
shape: Shape = MaterialTheme.shapes.medium,
|
shape: Shape = MaterialTheme.shapes.medium,
|
||||||
multiplier: Int = 4,
|
multiplier: Int = 4,
|
||||||
|
cardColors: CardColors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceContainerHighest
|
||||||
|
),
|
||||||
onClick: () -> Unit = { }
|
onClick: () -> Unit = { }
|
||||||
) {
|
) {
|
||||||
val bitmap = remember (icon.bitmap) {
|
val bitmap = remember (icon.bitmap) {
|
||||||
@@ -61,7 +65,8 @@ fun CharacterEntry(
|
|||||||
},
|
},
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.aspectRatio(1f)
|
.aspectRatio(1f)
|
||||||
.padding(8.dp)
|
.padding(8.dp),
|
||||||
|
colors = cardColors
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.BottomCenter,
|
contentAlignment = Alignment.BottomCenter,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.daos
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@@ -37,7 +38,7 @@ interface AdventureDao {
|
|||||||
JOIN Adventure a ON uc.id = a.characterId
|
JOIN Adventure a ON uc.id = a.characterId
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getAdventureCharacters(): List<CharacterDtos.AdventureCharacterWithSprites>
|
fun getAdventureCharacters(): Flow<List<CharacterDtos.AdventureCharacterWithSprites>>
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
DELETE FROM Adventure
|
DELETE FROM Adventure
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.daos
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface CardAdventureDao {
|
interface CardAdventureDao {
|
||||||
@@ -52,7 +53,7 @@ interface CardAdventureDao {
|
|||||||
WHERE
|
WHERE
|
||||||
cc.cardId = :cardId
|
cc.cardId = :cardId
|
||||||
""")
|
""")
|
||||||
suspend fun getAdventureForCard(
|
fun getAdventureForCard(
|
||||||
cardId: Long
|
cardId: Long
|
||||||
): List<CardDtos.CardAdventureWithSprites>
|
): Flow<List<CardDtos.CardAdventureWithSprites>>
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import androidx.room.Insert
|
|||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.github.nacabaro.vbhelper.domain.card.Card
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface CardDao {
|
interface CardDao {
|
||||||
@@ -26,7 +27,7 @@ interface CardDao {
|
|||||||
WHERE uc.id = :id
|
WHERE uc.id = :id
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getCardByCharacterId(id: Long): Card
|
fun getCardByCharacterId(id: Long): Flow<Card>
|
||||||
|
|
||||||
@Query("UPDATE Card SET name = :newName WHERE id = :id")
|
@Query("UPDATE Card SET name = :newName WHERE id = :id")
|
||||||
suspend fun renameCard(id: Int, newName: String)
|
suspend fun renameCard(id: Int, newName: String)
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package com.github.nacabaro.vbhelper.daos
|
|||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface CardFusionsDao {
|
interface CardFusionsDao {
|
||||||
@@ -9,24 +12,37 @@ interface CardFusionsDao {
|
|||||||
INSERT INTO
|
INSERT INTO
|
||||||
CardFusions (
|
CardFusions (
|
||||||
fromCharaId,
|
fromCharaId,
|
||||||
attribute1Fusion,
|
attribute,
|
||||||
attribute2Fusion,
|
toCharaId
|
||||||
attribute3Fusion,
|
|
||||||
attribute4Fusion
|
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :fromCharaId),
|
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :fromCharaId),
|
||||||
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr1),
|
:attribute,
|
||||||
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr2),
|
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaId)
|
||||||
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr3),
|
|
||||||
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr4)
|
|
||||||
""")
|
""")
|
||||||
suspend fun insertNewFusion(
|
suspend fun insertNewFusion(
|
||||||
cardId: Long,
|
cardId: Long,
|
||||||
fromCharaId: Int,
|
fromCharaId: Int,
|
||||||
toCharaIdAttr1: Int,
|
attribute: NfcCharacter.Attribute,
|
||||||
toCharaIdAttr2: Int,
|
toCharaId: Int
|
||||||
toCharaIdAttr3: Int,
|
|
||||||
toCharaIdAttr4: Int
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT
|
||||||
|
cf.toCharaId as charaId,
|
||||||
|
cf.fromCharaId as fromCharaId,
|
||||||
|
s.spriteIdle1 as spriteIdle,
|
||||||
|
cc.attribute as attribute,
|
||||||
|
s.width as spriteWidth,
|
||||||
|
s.height as spriteHeight,
|
||||||
|
d.discoveredOn as discoveredOn,
|
||||||
|
cf.attribute as fusionAttribute
|
||||||
|
FROM CardFusions cf
|
||||||
|
JOIN CardCharacter cc ON cc.id = cf.toCharaId
|
||||||
|
JOIN Sprite s ON s.id = cc.id
|
||||||
|
LEFT JOIN Dex d ON d.id = cc.id
|
||||||
|
WHERE cf.fromCharaId = :charaId
|
||||||
|
ORDER BY cc.charaIndex
|
||||||
|
""")
|
||||||
|
fun getFusionsForCharacter(charaId: Long): Flow<List<CharacterDtos.FusionsWithSpritesAndObtained>>
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import androidx.room.Insert
|
|||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.github.nacabaro.vbhelper.domain.card.CardProgress
|
import com.github.nacabaro.vbhelper.domain.card.CardProgress
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface CardProgressDao {
|
interface CardProgressDao {
|
||||||
@@ -21,7 +22,7 @@ interface CardProgressDao {
|
|||||||
@Query(
|
@Query(
|
||||||
"SELECT currentStage FROM CardProgress WHERE cardId = :cardId"
|
"SELECT currentStage FROM CardProgress WHERE cardId = :cardId"
|
||||||
)
|
)
|
||||||
fun getCardProgress(cardId: Long): Int
|
fun getCardProgress(cardId: Long): Flow<Int>
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun insertCardProgress(cardProgress: CardProgress)
|
fun insertCardProgress(cardProgress: CardProgress)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.room.Query
|
|||||||
import com.github.nacabaro.vbhelper.domain.card.CardCharacter
|
import com.github.nacabaro.vbhelper.domain.card.CardCharacter
|
||||||
import com.github.nacabaro.vbhelper.domain.characters.Sprite
|
import com.github.nacabaro.vbhelper.domain.characters.Sprite
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface CharacterDao {
|
interface CharacterDao {
|
||||||
@@ -82,8 +83,8 @@ interface CharacterDao {
|
|||||||
JOIN Sprite s ON s.id = c.spriteId
|
JOIN Sprite s ON s.id = c.spriteId
|
||||||
LEFT JOIN Dex d ON d.id = pt.toCharaId
|
LEFT JOIN Dex d ON d.id = pt.toCharaId
|
||||||
WHERE
|
WHERE
|
||||||
c.cardId = :cardId
|
pt.charaId = :characterId
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getEvolutionRequirementsForCard(cardId: Long): List<CharacterDtos.EvolutionRequirementsWithSpritesAndObtained>
|
fun getEvolutionRequirementsForCard(characterId: Long): Flow<List<CharacterDtos.EvolutionRequirementsWithSpritesAndObtained>>
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import androidx.room.Dao
|
|||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface DexDao {
|
interface DexDao {
|
||||||
@@ -40,7 +41,7 @@ interface DexDao {
|
|||||||
WHERE c.cardId = :cardId
|
WHERE c.cardId = :cardId
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getSingleCardProgress(cardId: Long): List<CharacterDtos.CardCharaProgress>
|
fun getSingleCardProgress(cardId: Long): Flow<List<CharacterDtos.CardCharaProgress>>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"""
|
"""
|
||||||
@@ -55,5 +56,5 @@ interface DexDao {
|
|||||||
FROM Card c
|
FROM Card c
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getCardsWithProgress(): List<CardDtos.CardProgress>
|
fun getCardsWithProgress(): Flow<List<CardDtos.CardProgress>>
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
|
|||||||
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.VitalsHistory
|
import com.github.nacabaro.vbhelper.domain.device_data.VitalsHistory
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface UserCharacterDao {
|
interface UserCharacterDao {
|
||||||
@@ -68,7 +69,8 @@ interface UserCharacterDao {
|
|||||||
c.nameWidth as nameSpriteWidth,
|
c.nameWidth as nameSpriteWidth,
|
||||||
c.nameHeight as nameSpriteHeight,
|
c.nameHeight as nameSpriteHeight,
|
||||||
d.isBEm as isBemCard,
|
d.isBEm as isBemCard,
|
||||||
a.characterId = uc.id as isInAdventure
|
a.characterId = uc.id as isInAdventure,
|
||||||
|
uc.isActive as active
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN CardCharacter c ON uc.charId = c.id
|
JOIN CardCharacter c ON uc.charId = c.id
|
||||||
JOIN Card d ON d.id = c.cardId
|
JOIN Card d ON d.id = c.cardId
|
||||||
@@ -76,7 +78,7 @@ interface UserCharacterDao {
|
|||||||
LEFT JOIN Adventure a ON a.characterId = uc.id
|
LEFT JOIN Adventure a ON a.characterId = uc.id
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
suspend fun getAllCharacters(): List<CharacterDtos.CharacterWithSprites>
|
fun getAllCharacters(): Flow<List<CharacterDtos.CharacterWithSprites>>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
"""
|
"""
|
||||||
@@ -92,7 +94,8 @@ interface UserCharacterDao {
|
|||||||
c.nameWidth as nameSpriteWidth,
|
c.nameWidth as nameSpriteWidth,
|
||||||
c.nameHeight as nameSpriteHeight,
|
c.nameHeight as nameSpriteHeight,
|
||||||
d.isBEm as isBemCard,
|
d.isBEm as isBemCard,
|
||||||
a.characterId = uc.id as isInAdventure
|
a.characterId = uc.id as isInAdventure,
|
||||||
|
uc.isActive as active
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN CardCharacter c ON uc.charId = c.id
|
JOIN CardCharacter c ON uc.charId = c.id
|
||||||
JOIN Card d ON c.cardId = d.id
|
JOIN Card d ON c.cardId = d.id
|
||||||
@@ -129,7 +132,8 @@ interface UserCharacterDao {
|
|||||||
c.nameWidth as nameSpriteWidth,
|
c.nameWidth as nameSpriteWidth,
|
||||||
c.nameHeight as nameSpriteHeight,
|
c.nameHeight as nameSpriteHeight,
|
||||||
d.isBEm as isBemCard,
|
d.isBEm as isBemCard,
|
||||||
a.characterId as isInAdventure
|
a.characterId as isInAdventure,
|
||||||
|
uc.isActive as active
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN CardCharacter c ON uc.charId = c.id
|
JOIN CardCharacter c ON uc.charId = c.id
|
||||||
JOIN Card d ON c.cardId = d.id
|
JOIN Card d ON c.cardId = d.id
|
||||||
@@ -193,7 +197,8 @@ interface UserCharacterDao {
|
|||||||
c.nameWidth as nameSpriteWidth,
|
c.nameWidth as nameSpriteWidth,
|
||||||
c.nameHeight as nameSpriteHeight,
|
c.nameHeight as nameSpriteHeight,
|
||||||
d.isBEm as isBemCard,
|
d.isBEm as isBemCard,
|
||||||
a.characterId = uc.id as isInAdventure
|
a.characterId = uc.id as isInAdventure,
|
||||||
|
uc.isActive as active
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN CardCharacter c ON uc.charId = c.id
|
JOIN CardCharacter c ON uc.charId = c.id
|
||||||
JOIN Card d ON d.id = c.cardId
|
JOIN Card d ON d.id = c.cardId
|
||||||
@@ -218,7 +223,8 @@ interface UserCharacterDao {
|
|||||||
c.nameWidth as nameSpriteWidth,
|
c.nameWidth as nameSpriteWidth,
|
||||||
c.nameHeight as nameSpriteHeight,
|
c.nameHeight as nameSpriteHeight,
|
||||||
d.isBEm as isBemCard,
|
d.isBEm as isBemCard,
|
||||||
a.characterId = uc.id as isInAdventure
|
a.characterId = uc.id as isInAdventure,
|
||||||
|
uc.isActive as active
|
||||||
FROM UserCharacter uc
|
FROM UserCharacter uc
|
||||||
JOIN CardCharacter c ON uc.charId = c.id
|
JOIN CardCharacter c ON uc.charId = c.id
|
||||||
JOIN Card d ON d.id = c.cardId
|
JOIN Card d ON d.id = c.cardId
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.domain.card
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.ForeignKey
|
import androidx.room.ForeignKey
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
foreignKeys = [
|
foreignKeys = [
|
||||||
@@ -15,25 +16,7 @@ import androidx.room.PrimaryKey
|
|||||||
ForeignKey(
|
ForeignKey(
|
||||||
entity = CardCharacter::class,
|
entity = CardCharacter::class,
|
||||||
parentColumns = ["id"],
|
parentColumns = ["id"],
|
||||||
childColumns = ["attribute1Fusion"],
|
childColumns = ["toCharaId"],
|
||||||
onDelete = ForeignKey.CASCADE
|
|
||||||
),
|
|
||||||
ForeignKey(
|
|
||||||
entity = CardCharacter::class,
|
|
||||||
parentColumns = ["id"],
|
|
||||||
childColumns = ["attribute2Fusion"],
|
|
||||||
onDelete = ForeignKey.CASCADE
|
|
||||||
),
|
|
||||||
ForeignKey(
|
|
||||||
entity = CardCharacter::class,
|
|
||||||
parentColumns = ["id"],
|
|
||||||
childColumns = ["attribute3Fusion"],
|
|
||||||
onDelete = ForeignKey.CASCADE
|
|
||||||
),
|
|
||||||
ForeignKey(
|
|
||||||
entity = CardCharacter::class,
|
|
||||||
parentColumns = ["id"],
|
|
||||||
childColumns = ["attribute4Fusion"],
|
|
||||||
onDelete = ForeignKey.CASCADE
|
onDelete = ForeignKey.CASCADE
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@@ -41,8 +24,6 @@ import androidx.room.PrimaryKey
|
|||||||
data class CardFusions(
|
data class CardFusions(
|
||||||
@PrimaryKey(autoGenerate = true) val id: Long,
|
@PrimaryKey(autoGenerate = true) val id: Long,
|
||||||
val fromCharaId: Long,
|
val fromCharaId: Long,
|
||||||
val attribute1Fusion: Long?,
|
val attribute: NfcCharacter.Attribute,
|
||||||
val attribute2Fusion: Long?,
|
val toCharaId: Long
|
||||||
val attribute3Fusion: Long?,
|
|
||||||
val attribute4Fusion: Long?
|
|
||||||
)
|
)
|
||||||
@@ -31,7 +31,8 @@ object CharacterDtos {
|
|||||||
val nameSpriteWidth: Int,
|
val nameSpriteWidth: Int,
|
||||||
val nameSpriteHeight: Int,
|
val nameSpriteHeight: Int,
|
||||||
val isBemCard: Boolean,
|
val isBemCard: Boolean,
|
||||||
val isInAdventure: Boolean
|
val isInAdventure: Boolean,
|
||||||
|
val active: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
data class CardCharacterInfo(
|
data class CardCharacterInfo(
|
||||||
@@ -114,4 +115,14 @@ object CharacterDtos {
|
|||||||
val changeTimerHours: Int,
|
val changeTimerHours: Int,
|
||||||
val requiredAdventureLevelCompleted: Int
|
val requiredAdventureLevelCompleted: Int
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class FusionsWithSpritesAndObtained(
|
||||||
|
val charaId: Long,
|
||||||
|
val fromCharaId: Long,
|
||||||
|
val spriteIdle: ByteArray,
|
||||||
|
val spriteWidth: Int,
|
||||||
|
val spriteHeight: Int,
|
||||||
|
val discoveredOn: Long?,
|
||||||
|
val fusionAttribute: NfcCharacter.Attribute
|
||||||
|
)
|
||||||
}
|
}
|
||||||
+11
-17
@@ -9,12 +9,11 @@ import androidx.compose.foundation.lazy.items
|
|||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -29,7 +28,6 @@ import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
|||||||
import com.github.nacabaro.vbhelper.source.StorageRepository
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
import com.github.nacabaro.vbhelper.utils.BitmapData
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -37,16 +35,17 @@ fun AdventureScreen(
|
|||||||
navController: NavController,
|
navController: NavController,
|
||||||
storageScreenController: AdventureScreenControllerImpl
|
storageScreenController: AdventureScreenControllerImpl
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
val database = application.container.db
|
val database = application.container.db
|
||||||
val storageRepository = StorageRepository(database)
|
val storageRepository = StorageRepository(database)
|
||||||
val characterList = remember {
|
val characterList by storageRepository.getAdventureCharacters().collectAsState(emptyList())
|
||||||
mutableStateOf<List<CharacterDtos.AdventureCharacterWithSprites>>(emptyList())
|
|
||||||
}
|
|
||||||
var obtainedItem by remember {
|
var obtainedItem by remember {
|
||||||
mutableStateOf<ItemDtos.PurchasedItem?>(null)
|
mutableStateOf<ItemDtos.PurchasedItem?>(null)
|
||||||
}
|
}
|
||||||
|
var obtainedCurrency by remember {
|
||||||
|
mutableStateOf(0)
|
||||||
|
}
|
||||||
|
|
||||||
val currentTime by produceState(initialValue = Instant.now().epochSecond) {
|
val currentTime by produceState(initialValue = Instant.now().epochSecond) {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -59,13 +58,6 @@ fun AdventureScreen(
|
|||||||
mutableStateOf<CharacterDtos.AdventureCharacterWithSprites?>(null)
|
mutableStateOf<CharacterDtos.AdventureCharacterWithSprites?>(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(storageRepository) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
characterList.value = storageRepository
|
|
||||||
.getAdventureCharacters()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBanner(
|
TopBanner(
|
||||||
@@ -76,7 +68,7 @@ fun AdventureScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
if (characterList.value.isEmpty()) {
|
if (characterList.isEmpty()) {
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
@@ -91,7 +83,7 @@ fun AdventureScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = contentPadding.calculateTopPadding())
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
items(characterList.value) {
|
items(characterList) {
|
||||||
AdventureEntry(
|
AdventureEntry(
|
||||||
icon = BitmapData(
|
icon = BitmapData(
|
||||||
bitmap = it.spriteIdle,
|
bitmap = it.spriteIdle,
|
||||||
@@ -102,8 +94,9 @@ fun AdventureScreen(
|
|||||||
onClick = {
|
onClick = {
|
||||||
if (it.finishesAdventure < currentTime) {
|
if (it.finishesAdventure < currentTime) {
|
||||||
storageScreenController
|
storageScreenController
|
||||||
.getItemFromAdventure(it.id) { adventureResult ->
|
.getItemFromAdventure(it.id) { adventureResult, generatedCurrency ->
|
||||||
obtainedItem = adventureResult
|
obtainedItem = adventureResult
|
||||||
|
obtainedCurrency = generatedCurrency
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cancelAdventureDialog = it
|
cancelAdventureDialog = it
|
||||||
@@ -118,6 +111,7 @@ fun AdventureScreen(
|
|||||||
if (obtainedItem != null) {
|
if (obtainedItem != null) {
|
||||||
ObtainedItemDialog(
|
ObtainedItemDialog(
|
||||||
obtainedItem = obtainedItem!!,
|
obtainedItem = obtainedItem!!,
|
||||||
|
obtainedCurrency = obtainedCurrency,
|
||||||
onClickDismiss = {
|
onClickDismiss = {
|
||||||
obtainedItem = null
|
obtainedItem = null
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
|||||||
|
|
||||||
interface AdventureScreenController {
|
interface AdventureScreenController {
|
||||||
fun sendCharacterToAdventure(characterId: Long, timeInMinutes: Long)
|
fun sendCharacterToAdventure(characterId: Long, timeInMinutes: Long)
|
||||||
fun getItemFromAdventure(characterId: Long, onResult: (ItemDtos.PurchasedItem) -> Unit)
|
fun getItemFromAdventure(characterId: Long, onResult: (ItemDtos.PurchasedItem, Int) -> Unit)
|
||||||
fun cancelAdventure(characterId: Long, onResult: () -> Unit)
|
fun cancelAdventure(characterId: Long, onResult: () -> Unit)
|
||||||
}
|
}
|
||||||
+12
-2
@@ -38,19 +38,29 @@ class AdventureScreenControllerImpl(
|
|||||||
|
|
||||||
override fun getItemFromAdventure(
|
override fun getItemFromAdventure(
|
||||||
characterId: Long,
|
characterId: Long,
|
||||||
onResult: (ItemDtos.PurchasedItem) -> Unit
|
onResult: (ItemDtos.PurchasedItem, Int) -> Unit
|
||||||
) {
|
) {
|
||||||
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
database
|
database
|
||||||
.adventureDao()
|
.adventureDao()
|
||||||
.deleteAdventure(characterId)
|
.deleteAdventure(characterId)
|
||||||
|
|
||||||
|
val generatedCurrency = generateRandomCurrency()
|
||||||
|
|
||||||
val generatedItem = generateItem(characterId)
|
val generatedItem = generateItem(characterId)
|
||||||
|
|
||||||
onResult(generatedItem)
|
onResult(generatedItem, generatedCurrency)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun generateRandomCurrency(): Int {
|
||||||
|
val currentValue = application.container.currencyRepository.currencyValue.first()
|
||||||
|
val random = (2..6).random() * 1000
|
||||||
|
application.container.currencyRepository.setCurrencyValue(currentValue + random)
|
||||||
|
|
||||||
|
return random
|
||||||
|
}
|
||||||
|
|
||||||
override fun cancelAdventure(characterId: Long, onResult: () -> Unit) {
|
override fun cancelAdventure(characterId: Long, onResult: () -> Unit) {
|
||||||
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
database
|
database
|
||||||
|
|||||||
+8
-23
@@ -6,18 +6,11 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CardAdventureScreen(
|
fun CardAdventureScreen(
|
||||||
@@ -25,20 +18,12 @@ fun CardAdventureScreen(
|
|||||||
cardScreenController: CardScreenControllerImpl,
|
cardScreenController: CardScreenControllerImpl,
|
||||||
cardId: Long
|
cardId: Long
|
||||||
) {
|
) {
|
||||||
val cardAdventureMissions = remember { mutableStateOf(emptyList<CardDtos.CardAdventureWithSprites>()) }
|
val cardAdventureMissions by cardScreenController
|
||||||
var currentCardAdventure by remember { mutableIntStateOf(0) }
|
.getCardAdventureMissions(cardId)
|
||||||
|
.collectAsState(emptyList())
|
||||||
LaunchedEffect(cardId) {
|
val currentCardAdventure by cardScreenController
|
||||||
withContext(Dispatchers.IO) {
|
.getCardProgress(cardId)
|
||||||
cardAdventureMissions.value =
|
.collectAsState(0)
|
||||||
cardScreenController
|
|
||||||
.getCardAdventureMissions(cardId)
|
|
||||||
|
|
||||||
currentCardAdventure =
|
|
||||||
cardScreenController
|
|
||||||
.getCardProgress(cardId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
@@ -55,7 +40,7 @@ fun CardAdventureScreen(
|
|||||||
.padding(top = contentPadding.calculateTopPadding())
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
.verticalScroll(state = rememberScrollState())
|
.verticalScroll(state = rememberScrollState())
|
||||||
) {
|
) {
|
||||||
cardAdventureMissions.value.mapIndexed { index, it ->
|
cardAdventureMissions.mapIndexed { index, it ->
|
||||||
CardAdventureEntry(
|
CardAdventureEntry(
|
||||||
cardAdventureEntry = it,
|
cardAdventureEntry = it,
|
||||||
obscure = index > currentCardAdventure - 1
|
obscure = index > currentCardAdventure - 1
|
||||||
|
|||||||
+5
-2
@@ -1,10 +1,13 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.cardScreen
|
package com.github.nacabaro.vbhelper.screens.cardScreen
|
||||||
|
|
||||||
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface CardScreenController {
|
interface CardScreenController {
|
||||||
fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit)
|
fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit)
|
||||||
fun deleteCard(cardId: Long, onDeleted: () -> Unit)
|
fun deleteCard(cardId: Long, onDeleted: () -> Unit)
|
||||||
suspend fun getCardAdventureMissions(cardId: Long): List<CardDtos.CardAdventureWithSprites>
|
fun getCardAdventureMissions(cardId: Long): Flow<List<CardDtos.CardAdventureWithSprites>>
|
||||||
suspend fun getCardProgress(cardId: Long): Int
|
fun getCardProgress(cardId: Long): Flow<Int>
|
||||||
|
fun getFusionsForCharacters(characterId: Long): Flow<List<CharacterDtos.FusionsWithSpritesAndObtained>>
|
||||||
}
|
}
|
||||||
+11
-2
@@ -4,6 +4,8 @@ import androidx.activity.ComponentActivity
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class CardScreenControllerImpl(
|
class CardScreenControllerImpl(
|
||||||
@@ -32,15 +34,22 @@ class CardScreenControllerImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getCardAdventureMissions(cardId: Long): List<CardDtos.CardAdventureWithSprites> {
|
override fun getCardAdventureMissions(cardId: Long): Flow<List<CardDtos.CardAdventureWithSprites>> {
|
||||||
return database
|
return database
|
||||||
.cardAdventureDao()
|
.cardAdventureDao()
|
||||||
.getAdventureForCard(cardId)
|
.getAdventureForCard(cardId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getCardProgress(cardId: Long): Int {
|
override fun getCardProgress(cardId: Long): Flow<Int> {
|
||||||
return database
|
return database
|
||||||
.cardProgressDao()
|
.cardProgressDao()
|
||||||
.getCardProgress(cardId)
|
.getCardProgress(cardId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getFusionsForCharacters(characterId: Long): Flow<List<CharacterDtos.FusionsWithSpritesAndObtained>> {
|
||||||
|
return database
|
||||||
|
.cardFusionsDao()
|
||||||
|
.getFusionsForCharacter(characterId)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
-18
@@ -5,10 +5,10 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
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.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.github.nacabaro.vbhelper.utils.BitmapData
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
@@ -19,32 +19,19 @@ import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
|||||||
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.DexCharaDetailsDialog
|
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.DexCharaDetailsDialog
|
||||||
import com.github.nacabaro.vbhelper.source.DexRepository
|
import com.github.nacabaro.vbhelper.source.DexRepository
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CardViewScreen(
|
fun CardViewScreen(
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
cardId: Long
|
cardId: Long
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
val dexRepository = DexRepository(application.container.db)
|
val dexRepository = DexRepository(application.container.db)
|
||||||
|
|
||||||
val characterList = remember { mutableStateOf<List<CharacterDtos.CardCharaProgress>>(emptyList()) }
|
val characterList by dexRepository.getCharactersByCardId(cardId).collectAsState(emptyList())
|
||||||
val cardPossibleTransformations = remember { mutableStateOf<List<CharacterDtos.EvolutionRequirementsWithSpritesAndObtained>>(emptyList()) }
|
|
||||||
|
|
||||||
val selectedCharacter = remember { mutableStateOf<CharacterDtos.CardCharaProgress?>(null) }
|
val selectedCharacter = remember { mutableStateOf<CharacterDtos.CardCharaProgress?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(dexRepository) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
val newCharacterList = dexRepository.getCharactersByCardId(cardId)
|
|
||||||
characterList.value = newCharacterList
|
|
||||||
|
|
||||||
val newCardPossibleTransformations = dexRepository.getCardPossibleTransformations(cardId)
|
|
||||||
cardPossibleTransformations.value = newCardPossibleTransformations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBanner(
|
TopBanner(
|
||||||
@@ -70,7 +57,7 @@ fun CardViewScreen(
|
|||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(3),
|
||||||
contentPadding = contentPadding
|
contentPadding = contentPadding
|
||||||
) {
|
) {
|
||||||
items(characterList.value) { character ->
|
items(characterList) { character ->
|
||||||
CharacterEntry(
|
CharacterEntry(
|
||||||
onClick = {
|
onClick = {
|
||||||
selectedCharacter.value = character
|
selectedCharacter.value = character
|
||||||
@@ -88,7 +75,6 @@ fun CardViewScreen(
|
|||||||
if (selectedCharacter.value != null) {
|
if (selectedCharacter.value != null) {
|
||||||
DexCharaDetailsDialog(
|
DexCharaDetailsDialog(
|
||||||
currentChara = selectedCharacter.value!!,
|
currentChara = selectedCharacter.value!!,
|
||||||
possibleTransformations = cardPossibleTransformations.value,
|
|
||||||
obscure = selectedCharacter.value!!.discoveredOn == null,
|
obscure = selectedCharacter.value!!.discoveredOn == null,
|
||||||
onClickClose = {
|
onClickClose = {
|
||||||
selectedCharacter.value = null
|
selectedCharacter.value = null
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -25,17 +24,15 @@ import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
|||||||
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.CardDeleteDialog
|
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.CardDeleteDialog
|
||||||
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.CardRenameDialog
|
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.CardRenameDialog
|
||||||
import com.github.nacabaro.vbhelper.source.DexRepository
|
import com.github.nacabaro.vbhelper.source.DexRepository
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CardsScreen(
|
fun CardsScreen(
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
cardScreenController: CardScreenControllerImpl
|
cardScreenController: CardScreenControllerImpl
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
val dexRepository = DexRepository(application.container.db)
|
val dexRepository = DexRepository(application.container.db)
|
||||||
val cardList = remember { mutableStateOf<List<CardDtos.CardProgress>>(emptyList()) }
|
val cardList by dexRepository.getAllDims().collectAsState(emptyList())
|
||||||
|
|
||||||
val selectedCard = remember { mutableStateOf<CardDtos.CardProgress?>(null) }
|
val selectedCard = remember { mutableStateOf<CardDtos.CardProgress?>(null) }
|
||||||
var clickedDelete by remember { mutableStateOf(false) }
|
var clickedDelete by remember { mutableStateOf(false) }
|
||||||
@@ -43,13 +40,6 @@ fun CardsScreen(
|
|||||||
|
|
||||||
var modifyCards by remember { mutableStateOf(false) }
|
var modifyCards by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(dexRepository) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
val newDimList = dexRepository.getAllDims()
|
|
||||||
cardList.value = newDimList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBanner(
|
TopBanner(
|
||||||
@@ -64,7 +54,7 @@ fun CardsScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = contentPadding.calculateTopPadding())
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
items(cardList.value) {
|
items(cardList) {
|
||||||
CardEntry(
|
CardEntry(
|
||||||
name = it.cardName,
|
name = it.cardName,
|
||||||
logo = BitmapData(
|
logo = BitmapData(
|
||||||
|
|||||||
+52
-6
@@ -16,6 +16,11 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.contentColorFor
|
import androidx.compose.material3.contentColorFor
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
@@ -23,7 +28,9 @@ import androidx.compose.ui.graphics.FilterQuality
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import com.github.nacabaro.vbhelper.source.DexRepository
|
||||||
import com.github.nacabaro.vbhelper.utils.BitmapData
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
import com.github.nacabaro.vbhelper.utils.getImageBitmap
|
import com.github.nacabaro.vbhelper.utils.getImageBitmap
|
||||||
|
|
||||||
@@ -31,14 +38,25 @@ import com.github.nacabaro.vbhelper.utils.getImageBitmap
|
|||||||
@Composable
|
@Composable
|
||||||
fun DexCharaDetailsDialog(
|
fun DexCharaDetailsDialog(
|
||||||
currentChara: CharacterDtos.CardCharaProgress,
|
currentChara: CharacterDtos.CardCharaProgress,
|
||||||
possibleTransformations: List<CharacterDtos.EvolutionRequirementsWithSpritesAndObtained>,
|
|
||||||
obscure: Boolean,
|
obscure: Boolean,
|
||||||
onClickClose: () -> Unit
|
onClickClose: () -> Unit
|
||||||
) {
|
) {
|
||||||
val nameMultiplier = 3
|
val nameMultiplier = 3
|
||||||
val charaMultiplier = 4
|
val charaMultiplier = 4
|
||||||
|
|
||||||
val currentCharaPossibleTransformations = possibleTransformations.filter { it.fromCharaId == currentChara.id }
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val database = application.container.db
|
||||||
|
val dexRepository = DexRepository(database)
|
||||||
|
|
||||||
|
var showFusions by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val currentCharaPossibleTransformations by dexRepository
|
||||||
|
.getCharacterPossibleTransformations(currentChara.id)
|
||||||
|
.collectAsState(emptyList())
|
||||||
|
|
||||||
|
val currentCharaPossibleFusions by dexRepository
|
||||||
|
.getCharacterPossibleFusions(currentChara.id)
|
||||||
|
.collectAsState(emptyList())
|
||||||
|
|
||||||
val romanNumeralsStage = when (currentChara.stage) {
|
val romanNumeralsStage = when (currentChara.stage) {
|
||||||
1 -> "II"
|
1 -> "II"
|
||||||
@@ -204,12 +222,40 @@ fun DexCharaDetailsDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Row {
|
||||||
onClick = onClickClose
|
if (currentCharaPossibleFusions.isNotEmpty()) {
|
||||||
) {
|
Button(
|
||||||
Text("Close")
|
onClick = {
|
||||||
|
showFusions = true
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Fusions")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(4.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onClickClose
|
||||||
|
) {
|
||||||
|
Text("Close")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showFusions) {
|
||||||
|
DexCharaFusionsDialog(
|
||||||
|
currentChara = currentChara,
|
||||||
|
currentCharaPossibleFusions = currentCharaPossibleFusions,
|
||||||
|
onClickDismiss = {
|
||||||
|
showFusions = false
|
||||||
|
},
|
||||||
|
obscure = obscure
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+191
@@ -0,0 +1,191 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.cardScreen.dialogs
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardColors
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getImageBitmap
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DexCharaFusionsDialog(
|
||||||
|
currentChara: CharacterDtos.CardCharaProgress,
|
||||||
|
currentCharaPossibleFusions: List<CharacterDtos.FusionsWithSpritesAndObtained>,
|
||||||
|
obscure: Boolean,
|
||||||
|
onClickDismiss: () -> Unit,
|
||||||
|
) {
|
||||||
|
val nameMultiplier = 3
|
||||||
|
val charaMultiplier = 4
|
||||||
|
|
||||||
|
val charaBitmapData = BitmapData(
|
||||||
|
bitmap = currentChara.spriteIdle,
|
||||||
|
width = currentChara.spriteWidth,
|
||||||
|
height = currentChara.spriteHeight
|
||||||
|
)
|
||||||
|
val charaImageBitmapData = charaBitmapData.getImageBitmap(
|
||||||
|
context = LocalContext.current,
|
||||||
|
multiplier = charaMultiplier,
|
||||||
|
obscure = obscure
|
||||||
|
)
|
||||||
|
|
||||||
|
val nameBitmapData = BitmapData(
|
||||||
|
bitmap = currentChara.nameSprite,
|
||||||
|
width = currentChara.nameSpriteWidth,
|
||||||
|
height = currentChara.nameSpriteHeight
|
||||||
|
)
|
||||||
|
val nameImageBitmapData = nameBitmapData.getImageBitmap(
|
||||||
|
context = LocalContext.current,
|
||||||
|
multiplier = nameMultiplier,
|
||||||
|
obscure = obscure
|
||||||
|
)
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onClickDismiss,
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
|
Card (
|
||||||
|
colors = CardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
contentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
),
|
||||||
|
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
disabledContentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
bitmap = charaImageBitmapData.imageBitmap,
|
||||||
|
contentDescription = "Icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(charaImageBitmapData.dpWidth)
|
||||||
|
.padding(8.dp),
|
||||||
|
colorFilter = when (obscure) {
|
||||||
|
true -> ColorFilter.tint(color = MaterialTheme.colorScheme.secondary)
|
||||||
|
false -> null
|
||||||
|
},
|
||||||
|
filterQuality = FilterQuality.None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!obscure) {
|
||||||
|
Column {
|
||||||
|
Image(
|
||||||
|
bitmap = nameImageBitmapData.imageBitmap,
|
||||||
|
contentDescription = "Icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.width(nameImageBitmapData.dpWidth)
|
||||||
|
.height(nameImageBitmapData.dpHeight),
|
||||||
|
filterQuality = FilterQuality.None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Column {
|
||||||
|
Text(text = "????????????????")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.padding(16.dp))
|
||||||
|
Column {
|
||||||
|
currentCharaPossibleFusions.map {
|
||||||
|
val selectedCharaBitmap = BitmapData(
|
||||||
|
bitmap = it.spriteIdle,
|
||||||
|
width = it.spriteWidth,
|
||||||
|
height = it.spriteHeight
|
||||||
|
)
|
||||||
|
val selectedCharaImageBitmap = selectedCharaBitmap.getImageBitmap(
|
||||||
|
context = LocalContext.current,
|
||||||
|
multiplier = 4,
|
||||||
|
obscure = it.discoveredOn == null
|
||||||
|
)
|
||||||
|
|
||||||
|
Card (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
Row (
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Card (
|
||||||
|
colors = CardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
contentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
),
|
||||||
|
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
disabledContentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
bitmap = selectedCharaImageBitmap.imageBitmap,
|
||||||
|
contentDescription = "Icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(selectedCharaImageBitmap.dpWidth)
|
||||||
|
.padding(8.dp),
|
||||||
|
colorFilter = when (it.discoveredOn == null) {
|
||||||
|
true -> ColorFilter.tint(color = MaterialTheme.colorScheme.secondary)
|
||||||
|
false -> null
|
||||||
|
},
|
||||||
|
filterQuality = FilterQuality.None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
Column {
|
||||||
|
Text("Combine with ${it.fusionAttribute}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onClickDismiss
|
||||||
|
) {
|
||||||
|
Text("Close")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.homeScreens
|
package com.github.nacabaro.vbhelper.screens.homeScreens
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@@ -56,6 +55,7 @@ fun HomeScreen(
|
|||||||
var adventureMissionsFinished by rememberSaveable { mutableStateOf(false) }
|
var adventureMissionsFinished by rememberSaveable { mutableStateOf(false) }
|
||||||
var betaWarning by rememberSaveable { mutableStateOf(true) }
|
var betaWarning by rememberSaveable { mutableStateOf(true) }
|
||||||
var collectedItem by remember { mutableStateOf<ItemDtos.PurchasedItem?>(null) }
|
var collectedItem by remember { mutableStateOf<ItemDtos.PurchasedItem?>(null) }
|
||||||
|
var collectedCurrency by remember { mutableStateOf<Int?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(storageRepository, activeMon, collectedItem) {
|
LaunchedEffect(storageRepository, activeMon, collectedItem) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
@@ -92,7 +92,6 @@ fun HomeScreen(
|
|||||||
}
|
}
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
if (activeMon.value == null || (beData.value == null && vbData.value == null) || transformationHistory.value == null) {
|
if (activeMon.value == null || (beData.value == null && vbData.value == null) || transformationHistory.value == null) {
|
||||||
Log.d("TetTet", "Something is null")
|
|
||||||
Column (
|
Column (
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
@@ -103,7 +102,6 @@ fun HomeScreen(
|
|||||||
Text(text = "Nothing to see here")
|
Text(text = "Nothing to see here")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d("TetTet", "Something is not null")
|
|
||||||
if (activeMon.value!!.isBemCard) {
|
if (activeMon.value!!.isBemCard) {
|
||||||
BEBEmHomeScreen(
|
BEBEmHomeScreen(
|
||||||
activeMon = activeMon.value!!,
|
activeMon = activeMon.value!!,
|
||||||
@@ -126,8 +124,9 @@ fun HomeScreen(
|
|||||||
contentPadding = contentPadding,
|
contentPadding = contentPadding,
|
||||||
specialMissions = vbSpecialMissions.value,
|
specialMissions = vbSpecialMissions.value,
|
||||||
homeScreenController = homeScreenController,
|
homeScreenController = homeScreenController,
|
||||||
onClickCollect = { item ->
|
onClickCollect = { item, currency ->
|
||||||
collectedItem = item
|
collectedItem = item
|
||||||
|
collectedCurrency = currency
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -137,8 +136,10 @@ fun HomeScreen(
|
|||||||
if (collectedItem != null) {
|
if (collectedItem != null) {
|
||||||
ObtainedItemDialog(
|
ObtainedItemDialog(
|
||||||
obtainedItem = collectedItem!!,
|
obtainedItem = collectedItem!!,
|
||||||
|
obtainedCurrency = collectedCurrency!!,
|
||||||
onClickDismiss = {
|
onClickDismiss = {
|
||||||
collectedItem = null
|
collectedItem = null
|
||||||
|
collectedCurrency = null
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,5 +5,5 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
|||||||
|
|
||||||
interface HomeScreenController {
|
interface HomeScreenController {
|
||||||
fun didAdventureMissionsFinish(onCompletion: (Boolean) -> Unit)
|
fun didAdventureMissionsFinish(onCompletion: (Boolean) -> Unit)
|
||||||
fun clearSpecialMission(missionId: Long, missionCompletion: SpecialMission.Status, onCleared: (ItemDtos.PurchasedItem?) -> Unit)
|
fun clearSpecialMission(missionId: Long, missionCompletion: SpecialMission.Status, onCleared: (ItemDtos.PurchasedItem?, Int?) -> Unit)
|
||||||
}
|
}
|
||||||
+8
-3
@@ -23,6 +23,7 @@ class HomeScreenControllerImpl(
|
|||||||
val adventureCharacters = database
|
val adventureCharacters = database
|
||||||
.adventureDao()
|
.adventureDao()
|
||||||
.getAdventureCharacters()
|
.getAdventureCharacters()
|
||||||
|
.first()
|
||||||
|
|
||||||
val finishedAdventureCharacters = adventureCharacters.filter { character ->
|
val finishedAdventureCharacters = adventureCharacters.filter { character ->
|
||||||
character.finishesAdventure <= currentTime
|
character.finishesAdventure <= currentTime
|
||||||
@@ -32,7 +33,7 @@ class HomeScreenControllerImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearSpecialMission(missionId: Long, missionCompletion: SpecialMission.Status, onCleared: (ItemDtos.PurchasedItem?) -> Unit) {
|
override fun clearSpecialMission(missionId: Long, missionCompletion: SpecialMission.Status, onCleared: (ItemDtos.PurchasedItem?, Int?) -> Unit) {
|
||||||
componentActivity.lifecycleScope.launch {
|
componentActivity.lifecycleScope.launch {
|
||||||
database
|
database
|
||||||
.specialMissionDao()
|
.specialMissionDao()
|
||||||
@@ -64,9 +65,13 @@ class HomeScreenControllerImpl(
|
|||||||
itemType = randomItem.itemType
|
itemType = randomItem.itemType
|
||||||
)
|
)
|
||||||
|
|
||||||
onCleared(purchasedItem)
|
val randomAmount = (2..6).random() * 1000
|
||||||
|
val currentCurrency = application.container.currencyRepository.currencyValue.first()
|
||||||
|
application.container.currencyRepository.setCurrencyValue(currentCurrency + randomAmount)
|
||||||
|
|
||||||
|
onCleared(purchasedItem, randomAmount)
|
||||||
} else {
|
} else {
|
||||||
onCleared(null)
|
onCleared(null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ fun VBDiMHomeScreen(
|
|||||||
homeScreenController: HomeScreenControllerImpl,
|
homeScreenController: HomeScreenControllerImpl,
|
||||||
transformationHistory: List<CharacterDtos.TransformationHistory>,
|
transformationHistory: List<CharacterDtos.TransformationHistory>,
|
||||||
contentPadding: PaddingValues,
|
contentPadding: PaddingValues,
|
||||||
onClickCollect: (ItemDtos.PurchasedItem?) -> Unit
|
onClickCollect: (ItemDtos.PurchasedItem?, Int?) -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
+3
-2
@@ -24,6 +24,7 @@ import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
|||||||
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
import com.github.nacabaro.vbhelper.source.StorageRepository
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
import com.github.nacabaro.vbhelper.utils.BitmapData
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ fun ChooseCharacterScreen(
|
|||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
val storageRepository = StorageRepository(application.container.db)
|
val storageRepository = StorageRepository(application.container.db, )
|
||||||
val characterList = remember {
|
val characterList = remember {
|
||||||
mutableStateOf<List<CharacterDtos.CharacterWithSprites>>(emptyList())
|
mutableStateOf<List<CharacterDtos.CharacterWithSprites>>(emptyList())
|
||||||
}
|
}
|
||||||
@@ -57,7 +58,7 @@ fun ChooseCharacterScreen(
|
|||||||
characterList.value = storageRepository.getVBCharacters()
|
characterList.value = storageRepository.getVBCharacters()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
characterList.value = storageRepository.getAllCharacters()
|
characterList.value = storageRepository.getAllCharacters().first()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -23,6 +23,7 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
|||||||
@Composable
|
@Composable
|
||||||
fun ObtainedItemDialog(
|
fun ObtainedItemDialog(
|
||||||
obtainedItem: ItemDtos.PurchasedItem,
|
obtainedItem: ItemDtos.PurchasedItem,
|
||||||
|
obtainedCurrency: Int,
|
||||||
onClickDismiss: () -> Unit
|
onClickDismiss: () -> Unit
|
||||||
) {
|
) {
|
||||||
Dialog(
|
Dialog(
|
||||||
@@ -84,7 +85,16 @@ fun ObtainedItemDialog(
|
|||||||
text = "You have obtained ${obtainedItem.itemAmount} of this item",
|
text = "You have obtained ${obtainedItem.itemAmount} of this item",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(5.dp)
|
.padding(top = 4.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
|
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
|
||||||
|
text = "You also got $obtainedCurrency credits",
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(bottom = 4.dp)
|
||||||
)
|
)
|
||||||
Button(
|
Button(
|
||||||
onClick = onClickDismiss,
|
onClick = onClickDismiss,
|
||||||
|
|||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
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 ChooseConnectOption(
|
||||||
|
onClickRead: (() -> Unit)? = null,
|
||||||
|
onClickWrite: (() -> Unit)? = null,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Scan a Vital Bracelet",
|
||||||
|
onBackClick = {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { contentPadding ->
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(contentPadding)
|
||||||
|
) {
|
||||||
|
ScanButton(
|
||||||
|
text = "Vital Bracelet to App",
|
||||||
|
disabled = onClickRead == null,
|
||||||
|
onClick = onClickRead?: { },
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
ScanButton(
|
||||||
|
text = "App to Vital Bracelet",
|
||||||
|
disabled = onClickWrite == null,
|
||||||
|
onClick = onClickWrite?: { },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ScanButton(
|
||||||
|
text: String,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
disabled: Boolean = false,
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier,
|
||||||
|
enabled = !disabled,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,38 +1,24 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.scanScreen
|
package com.github.nacabaro.vbhelper.screens.scanScreen
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
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.platform.LocalContext
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
import com.github.nacabaro.vbhelper.ActivityLifecycleListener
|
import com.github.nacabaro.vbhelper.ActivityLifecycleListener
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.domain.card.Card
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
import com.github.nacabaro.vbhelper.screens.cardScreen.ChooseCard
|
import com.github.nacabaro.vbhelper.screens.scanScreen.screens.ReadingScreen
|
||||||
|
import com.github.nacabaro.vbhelper.screens.scanScreen.screens.WritingScreen
|
||||||
import com.github.nacabaro.vbhelper.source.StorageRepository
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
import com.github.nacabaro.vbhelper.source.isMissingSecrets
|
import com.github.nacabaro.vbhelper.source.isMissingSecrets
|
||||||
import com.github.nacabaro.vbhelper.source.proto.Secrets
|
import com.github.nacabaro.vbhelper.source.proto.Secrets
|
||||||
@@ -55,8 +41,6 @@ fun ScanScreen(
|
|||||||
val storageRepository = StorageRepository(application.container.db)
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
var nfcCharacter by remember { mutableStateOf<NfcCharacter?>(null) }
|
var nfcCharacter by remember { mutableStateOf<NfcCharacter?>(null) }
|
||||||
|
|
||||||
var cardsRead by remember { mutableStateOf<List<Card>?>(null) }
|
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(storageRepository) {
|
LaunchedEffect(storageRepository) {
|
||||||
@@ -73,143 +57,33 @@ fun ScanScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var readingScreen by remember { mutableStateOf(false) }
|
|
||||||
var writingScreen by remember { mutableStateOf(false) }
|
var writingScreen by remember { mutableStateOf(false) }
|
||||||
var cardSelectScreen by remember { mutableStateOf(false) }
|
var readingScreen by remember { mutableStateOf(false) }
|
||||||
var isDoneReadingCharacter by remember { mutableStateOf(false) }
|
|
||||||
var isDoneSendingCard by remember { mutableStateOf(false) }
|
|
||||||
var isDoneWritingCharacter by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
DisposableEffect(readingScreen) {
|
if (writingScreen && nfcCharacter != null && characterId != null) {
|
||||||
if(readingScreen) {
|
WritingScreen(
|
||||||
scanScreenController.registerActivityLifecycleListener(
|
scanScreenController = scanScreenController,
|
||||||
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER,
|
nfcCharacter = nfcCharacter!!,
|
||||||
object: ActivityLifecycleListener {
|
characterId = characterId,
|
||||||
override fun onPause() {
|
onComplete = {
|
||||||
scanScreenController.cancelRead()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
scanScreenController.onClickRead(
|
|
||||||
secrets = secrets!!,
|
|
||||||
onComplete = {
|
|
||||||
isDoneReadingCharacter = true
|
|
||||||
},
|
|
||||||
onMultipleCards = { cards ->
|
|
||||||
cardsRead = cards
|
|
||||||
readingScreen = false
|
|
||||||
cardSelectScreen = true
|
|
||||||
isDoneReadingCharacter = true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
scanScreenController.onClickRead(
|
|
||||||
secrets = secrets!!,
|
|
||||||
onComplete = {
|
|
||||||
isDoneReadingCharacter = true
|
|
||||||
},
|
|
||||||
onMultipleCards = { cards ->
|
|
||||||
cardsRead = cards
|
|
||||||
readingScreen = false
|
|
||||||
cardSelectScreen = true
|
|
||||||
isDoneReadingCharacter = true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onDispose {
|
|
||||||
if(readingScreen) {
|
|
||||||
scanScreenController.unregisterActivityLifecycleListener(
|
|
||||||
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER
|
|
||||||
)
|
|
||||||
scanScreenController.cancelRead()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DisposableEffect(writingScreen, isDoneSendingCard) {
|
|
||||||
if (writingScreen) {
|
|
||||||
scanScreenController.registerActivityLifecycleListener(
|
|
||||||
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER,
|
|
||||||
object : ActivityLifecycleListener {
|
|
||||||
override fun onPause() {
|
|
||||||
scanScreenController.cancelRead()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
if (!isDoneSendingCard) {
|
|
||||||
scanScreenController.onClickCheckCard(secrets!!, nfcCharacter!!) {
|
|
||||||
isDoneSendingCard = true
|
|
||||||
}
|
|
||||||
} else if (!isDoneWritingCharacter) {
|
|
||||||
scanScreenController.onClickWrite(secrets!!, nfcCharacter!!) {
|
|
||||||
isDoneWritingCharacter = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (secrets != null && nfcCharacter != null) {
|
|
||||||
if (!isDoneSendingCard) {
|
|
||||||
scanScreenController.onClickCheckCard(secrets!!, nfcCharacter!!) {
|
|
||||||
isDoneSendingCard = true
|
|
||||||
}
|
|
||||||
} else if (!isDoneWritingCharacter) {
|
|
||||||
scanScreenController.onClickWrite(secrets!!, nfcCharacter!!) {
|
|
||||||
isDoneWritingCharacter = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDispose {
|
|
||||||
if(writingScreen) {
|
|
||||||
scanScreenController.unregisterActivityLifecycleListener(SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER)
|
|
||||||
scanScreenController.cancelRead()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDoneReadingCharacter && !cardSelectScreen) {
|
|
||||||
readingScreen = false
|
|
||||||
navController.navigate(NavigationItems.Home.route)
|
|
||||||
} else if (isDoneSendingCard && isDoneWritingCharacter) {
|
|
||||||
writingScreen = false
|
|
||||||
navController.navigate(NavigationItems.Home.route)
|
|
||||||
LaunchedEffect(storageRepository) {
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
storageRepository
|
|
||||||
.deleteCharacter(characterId!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readingScreen) {
|
|
||||||
ReadingCharacterScreen("Reading character") {
|
|
||||||
readingScreen = false
|
|
||||||
scanScreenController.cancelRead()
|
|
||||||
}
|
|
||||||
} else if (writingScreen) {
|
|
||||||
if (!isDoneSendingCard) {
|
|
||||||
ReadingCharacterScreen("Sending card") {
|
|
||||||
writingScreen = false
|
writingScreen = false
|
||||||
scanScreenController.cancelRead()
|
navController.navigate(NavigationItems.Home.route)
|
||||||
}
|
},
|
||||||
} else if (!isDoneWritingCharacter) {
|
onCancel = {
|
||||||
ReadingCharacterScreen("Writing character") {
|
|
||||||
isDoneSendingCard = false
|
|
||||||
writingScreen = false
|
writingScreen = false
|
||||||
scanScreenController.cancelRead()
|
navController.navigate(NavigationItems.Home.route)
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
} else if (cardSelectScreen) {
|
} else if (readingScreen) {
|
||||||
ChooseCard(
|
ReadingScreen(
|
||||||
cards = cardsRead!!,
|
scanScreenController = scanScreenController,
|
||||||
onCardSelected = { card ->
|
onCancel = {
|
||||||
cardSelectScreen = false
|
readingScreen = false
|
||||||
scanScreenController.flushCharacter(card.id)
|
navController.navigate(NavigationItems.Home.route)
|
||||||
|
},
|
||||||
|
onComplete = {
|
||||||
|
readingScreen = false
|
||||||
|
navController.navigate(NavigationItems.Home.route)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -247,66 +121,8 @@ fun ScanScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChooseConnectOption(
|
|
||||||
onClickRead: (() -> Unit)? = null,
|
|
||||||
onClickWrite: (() -> Unit)? = null,
|
|
||||||
navController: NavController
|
|
||||||
) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
TopBanner(
|
|
||||||
text = "Scan a Vital Bracelet",
|
|
||||||
onBackClick = {
|
|
||||||
navController.popBackStack()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { contentPadding ->
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(contentPadding)
|
|
||||||
) {
|
|
||||||
ScanButton(
|
|
||||||
text = "Vital Bracelet to App",
|
|
||||||
disabled = onClickRead == null,
|
|
||||||
onClick = onClickRead?: { },
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
ScanButton(
|
|
||||||
text = "App to Vital Bracelet",
|
|
||||||
disabled = onClickWrite == null,
|
|
||||||
onClick = onClickWrite?: { },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ScanButton(
|
|
||||||
text: String,
|
|
||||||
onClick: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
disabled: Boolean = false,
|
|
||||||
) {
|
|
||||||
Button(
|
|
||||||
onClick = onClick,
|
|
||||||
modifier = modifier,
|
|
||||||
enabled = !disabled,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = text,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(4.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
fun ScanScreenPreview() {
|
fun ScanScreenPreview() {
|
||||||
|
|||||||
+3
-4
@@ -1,13 +1,11 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.scanScreen.converters
|
package com.github.nacabaro.vbhelper.screens.scanScreen.converters
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import com.github.cfogrady.vbnfc.be.BENfcCharacter
|
import com.github.cfogrady.vbnfc.be.BENfcCharacter
|
||||||
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
|
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.domain.card.Card
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
import com.github.nacabaro.vbhelper.domain.card.CardProgress
|
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
|
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.SpecialMissions
|
||||||
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
||||||
@@ -250,10 +248,11 @@ class FromNfcConverter (
|
|||||||
) {
|
) {
|
||||||
val vitalsHistoryWatch = nfcCharacter.vitalHistory
|
val vitalsHistoryWatch = nfcCharacter.vitalHistory
|
||||||
val vitalsHistory = vitalsHistoryWatch.map { historyElement ->
|
val vitalsHistory = vitalsHistoryWatch.map { historyElement ->
|
||||||
Log.d("VitalsHistory", "${historyElement.year.toInt()} ${historyElement.month.toInt()} ${historyElement.day.toInt()}")
|
val year = if (historyElement.year.toInt() !in 2021 .. 2035) 0 else historyElement.year.toInt()
|
||||||
|
|
||||||
VitalsHistory(
|
VitalsHistory(
|
||||||
charId = characterId,
|
charId = characterId,
|
||||||
year = historyElement.year.toInt(),
|
year = year,
|
||||||
month = historyElement.month.toInt(),
|
month = historyElement.month.toInt(),
|
||||||
day = historyElement.day.toInt(),
|
day = historyElement.day.toInt(),
|
||||||
vitalPoints = historyElement.vitalsGained.toInt()
|
vitalPoints = historyElement.vitalsGained.toInt()
|
||||||
|
|||||||
+2
@@ -14,6 +14,7 @@ import com.github.nacabaro.vbhelper.di.VBHelper
|
|||||||
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
import com.github.nacabaro.vbhelper.utils.DeviceType
|
import com.github.nacabaro.vbhelper.utils.DeviceType
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class ToNfcConverter(
|
class ToNfcConverter(
|
||||||
@@ -96,6 +97,7 @@ class ToNfcConverter(
|
|||||||
val cardData = database
|
val cardData = database
|
||||||
.cardDao()
|
.cardDao()
|
||||||
.getCardByCharacterId(userCharacter.id)
|
.getCardByCharacterId(userCharacter.id)
|
||||||
|
.first()
|
||||||
|
|
||||||
val appReserved = Array<UShort>(3) {
|
val appReserved = Array<UShort>(3) {
|
||||||
0u
|
0u
|
||||||
|
|||||||
+6
-3
@@ -1,4 +1,4 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.scanScreen
|
package com.github.nacabaro.vbhelper.screens.scanScreen.screens
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -14,13 +14,16 @@ import androidx.compose.ui.unit.dp
|
|||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReadingCharacterScreen(
|
fun ActionScreen(
|
||||||
topBannerText: String,
|
topBannerText: String,
|
||||||
onClickCancel: () -> Unit,
|
onClickCancel: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBanner(topBannerText)
|
TopBanner(
|
||||||
|
text = topBannerText,
|
||||||
|
onBackClick = onClickCancel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column (
|
Column (
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadCharacterScreen(
|
||||||
|
onClickCancel: () -> Unit,
|
||||||
|
onClickConfirm: () -> Unit
|
||||||
|
) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Read character",
|
||||||
|
onBackClick = onClickCancel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Prepare your device!",
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Go to connect and when ready press confirm!",
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.padding(8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onClickConfirm,
|
||||||
|
) {
|
||||||
|
Text("Confirm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen.screens
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import com.github.nacabaro.vbhelper.ActivityLifecycleListener
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
|
import com.github.nacabaro.vbhelper.screens.cardScreen.ChooseCard
|
||||||
|
import com.github.nacabaro.vbhelper.screens.scanScreen.SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER
|
||||||
|
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenController
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingScreen(
|
||||||
|
scanScreenController: ScanScreenController,
|
||||||
|
onCancel: () -> Unit,
|
||||||
|
onComplete: () -> Unit
|
||||||
|
) {
|
||||||
|
val secrets by scanScreenController.secretsFlow.collectAsState(null)
|
||||||
|
|
||||||
|
var cardsRead by remember { mutableStateOf<List<Card>?>(null) }
|
||||||
|
|
||||||
|
var readingScreen by remember { mutableStateOf(false) }
|
||||||
|
var isDoneReadingCharacter by remember { mutableStateOf(false) }
|
||||||
|
var cardSelectScreen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
DisposableEffect(readingScreen) {
|
||||||
|
if(readingScreen) {
|
||||||
|
scanScreenController.registerActivityLifecycleListener(
|
||||||
|
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER,
|
||||||
|
object: ActivityLifecycleListener {
|
||||||
|
override fun onPause() {
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
scanScreenController.onClickRead(
|
||||||
|
secrets = secrets!!,
|
||||||
|
onComplete = {
|
||||||
|
isDoneReadingCharacter = true
|
||||||
|
},
|
||||||
|
onMultipleCards = { cards ->
|
||||||
|
cardsRead = cards
|
||||||
|
readingScreen = false
|
||||||
|
cardSelectScreen = true
|
||||||
|
isDoneReadingCharacter = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
scanScreenController.onClickRead(
|
||||||
|
secrets = secrets!!,
|
||||||
|
onComplete = {
|
||||||
|
isDoneReadingCharacter = true
|
||||||
|
},
|
||||||
|
onMultipleCards = { cards ->
|
||||||
|
cardsRead = cards
|
||||||
|
readingScreen = false
|
||||||
|
cardSelectScreen = true
|
||||||
|
isDoneReadingCharacter = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onDispose {
|
||||||
|
if(readingScreen) {
|
||||||
|
scanScreenController.unregisterActivityLifecycleListener(
|
||||||
|
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER
|
||||||
|
)
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDoneReadingCharacter && !cardSelectScreen) {
|
||||||
|
readingScreen = false
|
||||||
|
onComplete()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readingScreen) {
|
||||||
|
ReadCharacterScreen(
|
||||||
|
onClickConfirm = {
|
||||||
|
readingScreen = true
|
||||||
|
},
|
||||||
|
onClickCancel = {
|
||||||
|
onCancel()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readingScreen) {
|
||||||
|
ActionScreen("Reading character") {
|
||||||
|
readingScreen = false
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
onCancel()
|
||||||
|
}
|
||||||
|
} else if (cardSelectScreen) {
|
||||||
|
ChooseCard(
|
||||||
|
cards = cardsRead!!,
|
||||||
|
onCardSelected = { card ->
|
||||||
|
cardSelectScreen = false
|
||||||
|
scanScreenController.flushCharacter(card.id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+132
@@ -0,0 +1,132 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen.screens
|
||||||
|
|
||||||
|
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.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardColors
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
|
import com.github.nacabaro.vbhelper.source.ScanRepository
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getImageBitmap
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WriteCardScreen(
|
||||||
|
characterId: Long,
|
||||||
|
onClickCancel: () -> Unit,
|
||||||
|
onClickConfirm: () -> Unit
|
||||||
|
) {
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val database = application.container.db
|
||||||
|
val scanRepository = ScanRepository(database)
|
||||||
|
val cardDetails by scanRepository.getCardDetails(characterId).collectAsState(Card(
|
||||||
|
id = 0,
|
||||||
|
cardId = 0,
|
||||||
|
name = "",
|
||||||
|
logo = byteArrayOf(),
|
||||||
|
logoHeight = 0,
|
||||||
|
logoWidth = 0,
|
||||||
|
stageCount = 0,
|
||||||
|
isBEm = false
|
||||||
|
))
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Writing card details",
|
||||||
|
onBackClick = onClickCancel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Card (
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Row (
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
){
|
||||||
|
if (cardDetails.logoHeight > 0 && cardDetails.logoWidth > 0) {
|
||||||
|
val charaBitmapData = BitmapData(
|
||||||
|
bitmap = cardDetails.logo,
|
||||||
|
width = cardDetails.logoWidth,
|
||||||
|
height = cardDetails.logoHeight
|
||||||
|
)
|
||||||
|
val charaImageBitmapData = charaBitmapData.getImageBitmap(
|
||||||
|
context = LocalContext.current,
|
||||||
|
multiplier = 4,
|
||||||
|
obscure = false
|
||||||
|
)
|
||||||
|
|
||||||
|
Card (
|
||||||
|
colors = CardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
contentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
),
|
||||||
|
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
disabledContentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
bitmap = charaImageBitmapData.imageBitmap,
|
||||||
|
contentDescription = "Icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(charaImageBitmapData.dpWidth)
|
||||||
|
.padding(8.dp),
|
||||||
|
filterQuality = FilterQuality.None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.width(8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Text("Get your device Ready!")
|
||||||
|
Text("You will need ${cardDetails.name} card!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onClickConfirm,
|
||||||
|
) {
|
||||||
|
Text("Confirm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen.screens
|
||||||
|
|
||||||
|
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.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardColors
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
|
import com.github.nacabaro.vbhelper.source.ScanRepository
|
||||||
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
|
import com.github.nacabaro.vbhelper.utils.getImageBitmap
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WriteCharacterScreen(
|
||||||
|
characterId: Long,
|
||||||
|
onClickCancel: () -> Unit,
|
||||||
|
onClickConfirm: () -> Unit
|
||||||
|
) {
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val database = application.container.db
|
||||||
|
val scanRepository = ScanRepository(database)
|
||||||
|
val cardDetails by scanRepository.getCardDetails(characterId).collectAsState(Card(
|
||||||
|
id = 0,
|
||||||
|
cardId = 0,
|
||||||
|
name = "",
|
||||||
|
logo = byteArrayOf(),
|
||||||
|
logoHeight = 0,
|
||||||
|
logoWidth = 0,
|
||||||
|
stageCount = 0,
|
||||||
|
isBEm = false
|
||||||
|
))
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Writing character",
|
||||||
|
onBackClick = onClickCancel
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Card (
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
|
) {
|
||||||
|
Row (
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
){
|
||||||
|
if (cardDetails.logoHeight > 0 && cardDetails.logoWidth > 0) {
|
||||||
|
val charaBitmapData = BitmapData(
|
||||||
|
bitmap = cardDetails.logo,
|
||||||
|
width = cardDetails.logoWidth,
|
||||||
|
height = cardDetails.logoHeight
|
||||||
|
)
|
||||||
|
val charaImageBitmapData = charaBitmapData.getImageBitmap(
|
||||||
|
context = LocalContext.current,
|
||||||
|
multiplier = 4,
|
||||||
|
obscure = false
|
||||||
|
)
|
||||||
|
|
||||||
|
Card (
|
||||||
|
colors = CardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
contentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
),
|
||||||
|
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
disabledContentColor = MaterialTheme.colorScheme.contentColorFor(
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
bitmap = charaImageBitmapData.imageBitmap,
|
||||||
|
contentDescription = "Icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.size(charaImageBitmapData.dpWidth)
|
||||||
|
.padding(8.dp),
|
||||||
|
filterQuality = FilterQuality.None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.width(8.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Text("Card installed successfully!!")
|
||||||
|
Text("Wait until your device is ready, then tap 'Confirm'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onClickConfirm,
|
||||||
|
) {
|
||||||
|
Text("Confirm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen.screens
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
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
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
import com.github.nacabaro.vbhelper.ActivityLifecycleListener
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.screens.scanScreen.SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER
|
||||||
|
import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenController
|
||||||
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WritingScreen(
|
||||||
|
scanScreenController: ScanScreenController,
|
||||||
|
characterId: Long,
|
||||||
|
nfcCharacter: NfcCharacter,
|
||||||
|
onComplete: () -> Unit,
|
||||||
|
onCancel: () -> Unit,
|
||||||
|
) {
|
||||||
|
val secrets by scanScreenController.secretsFlow.collectAsState(null)
|
||||||
|
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
|
|
||||||
|
var writing by remember { mutableStateOf(false) }
|
||||||
|
var writingScreen by remember { mutableStateOf(false) }
|
||||||
|
var writingConfirmScreen by remember { mutableStateOf(false) }
|
||||||
|
var isDoneSendingCard by remember { mutableStateOf(false) }
|
||||||
|
var isDoneWritingCharacter by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
DisposableEffect(writing) {
|
||||||
|
if (writing) {
|
||||||
|
scanScreenController.registerActivityLifecycleListener(
|
||||||
|
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER,
|
||||||
|
object : ActivityLifecycleListener {
|
||||||
|
override fun onPause() {
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
if (!isDoneSendingCard) {
|
||||||
|
scanScreenController.onClickCheckCard(secrets!!, nfcCharacter) {
|
||||||
|
isDoneSendingCard = true
|
||||||
|
}
|
||||||
|
} else if (!isDoneWritingCharacter) {
|
||||||
|
scanScreenController.onClickWrite(secrets!!, nfcCharacter) {
|
||||||
|
isDoneWritingCharacter = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (secrets != null) {
|
||||||
|
if (!isDoneSendingCard) {
|
||||||
|
scanScreenController.onClickCheckCard(secrets!!, nfcCharacter) {
|
||||||
|
isDoneSendingCard = true
|
||||||
|
}
|
||||||
|
} else if (!isDoneWritingCharacter) {
|
||||||
|
scanScreenController.onClickWrite(secrets!!, nfcCharacter) {
|
||||||
|
isDoneWritingCharacter = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDispose {
|
||||||
|
if (writing) {
|
||||||
|
scanScreenController.unregisterActivityLifecycleListener(
|
||||||
|
SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER
|
||||||
|
)
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!writingScreen) {
|
||||||
|
writing = false
|
||||||
|
WriteCardScreen (
|
||||||
|
characterId = characterId,
|
||||||
|
onClickCancel = {
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
onCancel()
|
||||||
|
},
|
||||||
|
onClickConfirm = {
|
||||||
|
writingScreen = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if (!isDoneSendingCard) {
|
||||||
|
writing = true
|
||||||
|
ActionScreen("Sending card") {
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
onCancel()
|
||||||
|
}
|
||||||
|
} else if (!writingConfirmScreen) {
|
||||||
|
writing = false
|
||||||
|
WriteCharacterScreen (
|
||||||
|
characterId = characterId,
|
||||||
|
onClickCancel = {
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
onCancel()
|
||||||
|
},
|
||||||
|
onClickConfirm = {
|
||||||
|
writingConfirmScreen = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if (!isDoneWritingCharacter) {
|
||||||
|
writing = true
|
||||||
|
ActionScreen("Writing character") {
|
||||||
|
isDoneSendingCard = false
|
||||||
|
scanScreenController.cancelRead()
|
||||||
|
onCancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var completedWriting by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
LaunchedEffect(isDoneSendingCard, isDoneWritingCharacter) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
if (isDoneSendingCard && isDoneWritingCharacter) {
|
||||||
|
storageRepository
|
||||||
|
.deleteCharacter(characterId)
|
||||||
|
completedWriting = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (completedWriting) {
|
||||||
|
onComplete()
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-3
@@ -1,5 +1,7 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.settingsScreen
|
package com.github.nacabaro.vbhelper.screens.settingsScreen
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -13,6 +15,7 @@ import androidx.compose.material3.Scaffold
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -25,6 +28,8 @@ fun SettingsScreen(
|
|||||||
navController: NavController,
|
navController: NavController,
|
||||||
settingsScreenController: SettingsScreenControllerImpl,
|
settingsScreenController: SettingsScreenControllerImpl,
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBanner(
|
TopBanner(
|
||||||
@@ -44,19 +49,22 @@ fun SettingsScreen(
|
|||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
SettingsSection("NFC Communication")
|
SettingsSection("NFC Communication")
|
||||||
SettingsEntry(title = "Import APK", description = "Import Secrets From Vital Arean 2.1.0 APK") {
|
SettingsEntry(title = "Import APK", description = "Import Secrets From Vital Arena 2.1.0 APK") {
|
||||||
settingsScreenController.onClickImportApk()
|
settingsScreenController.onClickImportApk()
|
||||||
}
|
}
|
||||||
SettingsSection("DiM/BEm management")
|
SettingsSection("DiM/BEm management")
|
||||||
SettingsEntry(title = "Import card", description = "Import DiM/BEm card file") {
|
SettingsEntry(title = "Import card", description = "Import DiM/BEm card file") {
|
||||||
settingsScreenController.onClickImportCard()
|
settingsScreenController.onClickImportCard()
|
||||||
}
|
}
|
||||||
SettingsEntry(title = "Rename DiM/BEm", description = "Set card name") { }
|
|
||||||
SettingsSection("About and credits")
|
SettingsSection("About and credits")
|
||||||
SettingsEntry(title = "Credits", description = "Credits") {
|
SettingsEntry(title = "Credits", description = "Credits") {
|
||||||
navController.navigate(NavigationItems.Credits.route)
|
navController.navigate(NavigationItems.Credits.route)
|
||||||
}
|
}
|
||||||
SettingsEntry(title = "About", description = "About") { }
|
SettingsEntry(title = "About", description = "About") {
|
||||||
|
val browserIntent = Intent(
|
||||||
|
Intent.ACTION_VIEW, Uri.parse("https://github.com/nacabaro/vbhelper/"))
|
||||||
|
context.startActivity(browserIntent)
|
||||||
|
}
|
||||||
SettingsSection("Data management")
|
SettingsSection("Data management")
|
||||||
SettingsEntry(title = "Export data", description = "Export application database") {
|
SettingsEntry(title = "Export data", description = "Export application database") {
|
||||||
settingsScreenController.onClickOpenDirectory()
|
settingsScreenController.onClickOpenDirectory()
|
||||||
|
|||||||
+10
-374
@@ -3,36 +3,24 @@ package com.github.nacabaro.vbhelper.screens.settingsScreen
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.OpenableColumns
|
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import com.github.cfogrady.vb.dim.card.BemCard
|
|
||||||
import com.github.cfogrady.vb.dim.card.DimCard
|
|
||||||
import com.github.cfogrady.vb.dim.card.DimReader
|
|
||||||
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
|
||||||
import com.github.nacabaro.vbhelper.database.AppDatabase
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.domain.characters.Sprite
|
import com.github.nacabaro.vbhelper.screens.settingsScreen.controllers.CardImportController
|
||||||
import com.github.nacabaro.vbhelper.domain.card.Card
|
import com.github.nacabaro.vbhelper.screens.settingsScreen.controllers.DatabaseManagementController
|
||||||
import com.github.nacabaro.vbhelper.domain.card.CardProgress
|
|
||||||
import com.github.nacabaro.vbhelper.domain.card.CardCharacter
|
|
||||||
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter
|
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter
|
||||||
import com.github.nacabaro.vbhelper.source.SecretsImporter
|
import com.github.nacabaro.vbhelper.source.SecretsImporter
|
||||||
import com.github.nacabaro.vbhelper.source.SecretsRepository
|
import com.github.nacabaro.vbhelper.source.SecretsRepository
|
||||||
import com.github.nacabaro.vbhelper.source.proto.Secrets
|
import com.github.nacabaro.vbhelper.source.proto.Secrets
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import java.io.File
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.OutputStream
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsScreenControllerImpl(
|
class SettingsScreenControllerImpl(
|
||||||
private val context: ComponentActivity,
|
private val context: ComponentActivity,
|
||||||
): SettingsScreenController {
|
): SettingsScreenController {
|
||||||
private val roomDbName = "internalDb"
|
|
||||||
private val filePickerLauncher: ActivityResultLauncher<String>
|
private val filePickerLauncher: ActivityResultLauncher<String>
|
||||||
private val filePickerOpenerLauncher: ActivityResultLauncher<Array<String>>
|
private val filePickerOpenerLauncher: ActivityResultLauncher<Array<String>>
|
||||||
private val filePickerApk: ActivityResultLauncher<Array<String>>
|
private val filePickerApk: ActivityResultLauncher<Array<String>>
|
||||||
@@ -41,13 +29,17 @@ class SettingsScreenControllerImpl(
|
|||||||
private val application = context.applicationContext as VBHelper
|
private val application = context.applicationContext as VBHelper
|
||||||
private val secretsRepository: SecretsRepository = application.container.dataStoreSecretsRepository
|
private val secretsRepository: SecretsRepository = application.container.dataStoreSecretsRepository
|
||||||
private val database: AppDatabase = application.container.db
|
private val database: AppDatabase = application.container.db
|
||||||
|
private val databaseManagementController = DatabaseManagementController(
|
||||||
|
componentActivity = context,
|
||||||
|
application = application
|
||||||
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
filePickerLauncher = context.registerForActivityResult(
|
filePickerLauncher = context.registerForActivityResult(
|
||||||
ActivityResultContracts.CreateDocument("application/octet-stream")
|
ActivityResultContracts.CreateDocument("application/octet-stream")
|
||||||
) { uri ->
|
) { uri ->
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
exportDatabase(uri)
|
databaseManagementController.exportDatabase(uri)
|
||||||
} else {
|
} else {
|
||||||
context.runOnUiThread {
|
context.runOnUiThread {
|
||||||
Toast.makeText(context, "No destination selected", Toast.LENGTH_SHORT)
|
Toast.makeText(context, "No destination selected", Toast.LENGTH_SHORT)
|
||||||
@@ -60,7 +52,7 @@ class SettingsScreenControllerImpl(
|
|||||||
ActivityResultContracts.OpenDocument()
|
ActivityResultContracts.OpenDocument()
|
||||||
) { uri ->
|
) { uri ->
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
importDatabase(uri)
|
databaseManagementController.importDatabase(uri)
|
||||||
} else {
|
} else {
|
||||||
context.runOnUiThread {
|
context.runOnUiThread {
|
||||||
Toast.makeText(context, "No source selected", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, "No source selected", Toast.LENGTH_SHORT).show()
|
||||||
@@ -109,276 +101,14 @@ class SettingsScreenControllerImpl(
|
|||||||
filePickerCard.launch(arrayOf("*/*"))
|
filePickerCard.launch(arrayOf("*/*"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun importEvoData(
|
|
||||||
cardId: Long,
|
|
||||||
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
|
||||||
) {
|
|
||||||
for (index in 0 until card.transformationRequirements.transformationEntries.size) {
|
|
||||||
val evo = card.transformationRequirements.transformationEntries[index]
|
|
||||||
|
|
||||||
var transformationTimerHours: Int
|
|
||||||
var unlockAdventureLevel: Int
|
|
||||||
|
|
||||||
if (card is BemCard) {
|
|
||||||
transformationTimerHours = card
|
|
||||||
.transformationRequirements
|
|
||||||
.transformationEntries[index]
|
|
||||||
.minutesUntilTransformation / 60
|
|
||||||
unlockAdventureLevel = if (
|
|
||||||
card
|
|
||||||
.transformationRequirements
|
|
||||||
.transformationEntries[index]
|
|
||||||
.requiredCompletedAdventureLevel == 65535
|
|
||||||
) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
card
|
|
||||||
.transformationRequirements
|
|
||||||
.transformationEntries[index]
|
|
||||||
.requiredCompletedAdventureLevel
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
transformationTimerHours = (card as DimCard)
|
|
||||||
.transformationRequirements
|
|
||||||
.transformationEntries[index]
|
|
||||||
.hoursUntilEvolution
|
|
||||||
unlockAdventureLevel = if (
|
|
||||||
card
|
|
||||||
.adventureLevels
|
|
||||||
.levels
|
|
||||||
.last()
|
|
||||||
.bossCharacterIndex == card.transformationRequirements.transformationEntries[index].toCharacterIndex
|
|
||||||
) {
|
|
||||||
14
|
|
||||||
/*
|
|
||||||
Magic number incoming!!
|
|
||||||
|
|
||||||
In the case of DiMCards, stage 15 is the one that unlocks the locked character.
|
|
||||||
We know it is a locked character if the last adventure level's boss character index
|
|
||||||
is the current index. If it is, we add stage 15 complete as a requirement for transformation.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
/*
|
|
||||||
Another magic number...
|
|
||||||
|
|
||||||
The rest of the characters are not locked.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
database
|
|
||||||
.characterDao()
|
|
||||||
.insertPossibleTransformation(
|
|
||||||
cardId = cardId,
|
|
||||||
fromChraraIndex = evo.fromCharacterIndex,
|
|
||||||
toChraraIndex = evo.toCharacterIndex,
|
|
||||||
requiredVitals = evo.requiredVitalValues,
|
|
||||||
requiredTrophies = evo.requiredTrophies,
|
|
||||||
requiredBattles = evo.requiredBattles,
|
|
||||||
requiredWinRate = evo.requiredWinRatio,
|
|
||||||
requiredAdventureLevelCompleted = unlockAdventureLevel,
|
|
||||||
changeTimerHours = transformationTimerHours
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun importCharacterData(
|
|
||||||
cardId: Long,
|
|
||||||
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
|
||||||
) {
|
|
||||||
var spriteCounter = when (card is BemCard) {
|
|
||||||
true -> 54
|
|
||||||
false -> 10
|
|
||||||
}
|
|
||||||
|
|
||||||
val domainCharacters = mutableListOf<CardCharacter>()
|
|
||||||
|
|
||||||
val characters = card
|
|
||||||
.characterStats
|
|
||||||
.characterEntries
|
|
||||||
|
|
||||||
for (index in 0 until characters.size) {
|
|
||||||
var domainSprite: Sprite?
|
|
||||||
if (index < 2 && card is DimCard) {
|
|
||||||
domainSprite = Sprite(
|
|
||||||
width = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.width,
|
|
||||||
height = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.height,
|
|
||||||
spriteIdle1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
|
||||||
spriteIdle2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
|
|
||||||
spriteWalk1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
|
||||||
spriteWalk2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
|
||||||
spriteRun1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
|
||||||
spriteRun2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
|
||||||
spriteTrain1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
|
||||||
spriteTrain2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
|
||||||
spriteHappy = card.spriteData.sprites[spriteCounter + 4].pixelData,
|
|
||||||
spriteSleep = card.spriteData.sprites[spriteCounter + 5].pixelData,
|
|
||||||
spriteAttack = card.spriteData.sprites[spriteCounter + 2].pixelData,
|
|
||||||
spriteDodge = card.spriteData.sprites[spriteCounter + 3].pixelData
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
domainSprite = Sprite(
|
|
||||||
width = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.width,
|
|
||||||
height = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.height,
|
|
||||||
spriteIdle1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
|
||||||
spriteIdle2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
|
|
||||||
spriteWalk1 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
|
||||||
spriteWalk2 = card.spriteData.sprites[spriteCounter + 4].pixelData,
|
|
||||||
spriteRun1 = card.spriteData.sprites[spriteCounter + 5].pixelData,
|
|
||||||
spriteRun2 = card.spriteData.sprites[spriteCounter + 6].pixelData,
|
|
||||||
spriteTrain1 = card.spriteData.sprites[spriteCounter + 7].pixelData,
|
|
||||||
spriteTrain2 = card.spriteData.sprites[spriteCounter + 8].pixelData,
|
|
||||||
spriteHappy = card.spriteData.sprites[spriteCounter + 9].pixelData,
|
|
||||||
spriteSleep = card.spriteData.sprites[spriteCounter + 10].pixelData,
|
|
||||||
spriteAttack = card.spriteData.sprites[spriteCounter + 11].pixelData,
|
|
||||||
spriteDodge = card.spriteData.sprites[spriteCounter + 12].pixelData
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val spriteId = database
|
|
||||||
.spriteDao()
|
|
||||||
.insertSprite(domainSprite)
|
|
||||||
|
|
||||||
|
|
||||||
domainCharacters.add(
|
|
||||||
CardCharacter(
|
|
||||||
cardId = cardId,
|
|
||||||
spriteId = spriteId,
|
|
||||||
charaIndex = index,
|
|
||||||
nameSprite = card.spriteData.sprites[spriteCounter].pixelData,
|
|
||||||
stage = characters[index].stage,
|
|
||||||
attribute = NfcCharacter.Attribute.entries[characters[index].attribute],
|
|
||||||
baseHp = characters[index].hp,
|
|
||||||
baseBp = characters[index].dp,
|
|
||||||
baseAp = characters[index].ap,
|
|
||||||
nameWidth = card.spriteData.sprites[spriteCounter].spriteDimensions.width,
|
|
||||||
nameHeight = card.spriteData.sprites[spriteCounter].spriteDimensions.height
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
spriteCounter += if (card is BemCard) {
|
|
||||||
14
|
|
||||||
} else {
|
|
||||||
when (index) {
|
|
||||||
0 -> 6
|
|
||||||
1 -> 7
|
|
||||||
else -> 14
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
database
|
|
||||||
.characterDao()
|
|
||||||
.insertCharacter(*domainCharacters.toTypedArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun importAdventureMissions(
|
|
||||||
cardId: Long,
|
|
||||||
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
|
||||||
) {
|
|
||||||
Log.d("importAdventureMissions", "Importing adventure missions")
|
|
||||||
if (card is BemCard) {
|
|
||||||
card.adventureLevels.levels.forEach {
|
|
||||||
database
|
|
||||||
.cardAdventureDao()
|
|
||||||
.insertNewAdventure(
|
|
||||||
cardId = cardId,
|
|
||||||
characterId = it.bossCharacterIndex,
|
|
||||||
steps = it.steps,
|
|
||||||
bossAp = it.bossAp,
|
|
||||||
bossHp = it.bossHp,
|
|
||||||
bossDp = it.bossDp,
|
|
||||||
bossBp = it.bossBp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else if (card is DimCard) {
|
|
||||||
card.adventureLevels.levels.map {
|
|
||||||
database
|
|
||||||
.cardAdventureDao()
|
|
||||||
.insertNewAdventure(
|
|
||||||
cardId = cardId,
|
|
||||||
characterId = it.bossCharacterIndex,
|
|
||||||
steps = it.steps,
|
|
||||||
bossAp = it.bossAp,
|
|
||||||
bossHp = it.bossHp,
|
|
||||||
bossDp = it.bossDp,
|
|
||||||
bossBp = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun importCardFusions(
|
|
||||||
cardId: Long,
|
|
||||||
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
|
||||||
) {
|
|
||||||
Log.d("importCardFusions", "Importing card fusions")
|
|
||||||
if (card is DimCard) {
|
|
||||||
card
|
|
||||||
.attributeFusions
|
|
||||||
.entries
|
|
||||||
.forEach {
|
|
||||||
database
|
|
||||||
.cardFusionsDao()
|
|
||||||
.insertNewFusion(
|
|
||||||
cardId = cardId,
|
|
||||||
fromCharaId = it.characterIndex,
|
|
||||||
toCharaIdAttr1 = it.attribute1Fusion,
|
|
||||||
toCharaIdAttr2 = it.attribute2Fusion,
|
|
||||||
toCharaIdAttr3 = it.attribute3Fusion,
|
|
||||||
toCharaIdAttr4 = it.attribute4Fusion
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateCardProgress(
|
|
||||||
cardId: Long,
|
|
||||||
) {
|
|
||||||
database
|
|
||||||
.cardProgressDao()
|
|
||||||
.insertCardProgress(
|
|
||||||
CardProgress(
|
|
||||||
cardId = cardId,
|
|
||||||
currentStage = 1,
|
|
||||||
unlocked = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun importCard(uri: Uri) {
|
private fun importCard(uri: Uri) {
|
||||||
context.lifecycleScope.launch(Dispatchers.IO) {
|
context.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val contentResolver = context.contentResolver
|
val contentResolver = context.contentResolver
|
||||||
val inputStream = contentResolver.openInputStream(uri)
|
val inputStream = contentResolver.openInputStream(uri)
|
||||||
|
|
||||||
inputStream.use { fileReader ->
|
inputStream.use { fileReader ->
|
||||||
val dimReader = DimReader()
|
val cardImportController = CardImportController(database)
|
||||||
val card = dimReader.readCard(fileReader, false)
|
cardImportController.importCard(fileReader)
|
||||||
|
|
||||||
val cardModel = Card(
|
|
||||||
cardId = card.header.dimId,
|
|
||||||
logo = card.spriteData.sprites[0].pixelData,
|
|
||||||
name = card.spriteData.text,
|
|
||||||
stageCount = card.adventureLevels.levels.size,
|
|
||||||
logoHeight = card.spriteData.sprites[0].height,
|
|
||||||
logoWidth = card.spriteData.sprites[0].width,
|
|
||||||
isBEm = card is BemCard
|
|
||||||
)
|
|
||||||
|
|
||||||
val cardId = database
|
|
||||||
.cardDao()
|
|
||||||
.insertNewCard(cardModel)
|
|
||||||
|
|
||||||
updateCardProgress(cardId = cardId)
|
|
||||||
|
|
||||||
importCharacterData(cardId, card)
|
|
||||||
|
|
||||||
importEvoData(cardId, card)
|
|
||||||
|
|
||||||
importAdventureMissions(cardId, card)
|
|
||||||
|
|
||||||
importCardFusions(cardId, card)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputStream?.close()
|
inputStream?.close()
|
||||||
@@ -388,100 +118,6 @@ class SettingsScreenControllerImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun exportDatabase(destinationUri: Uri) {
|
|
||||||
context.lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
try {
|
|
||||||
val dbFile = File(context.getDatabasePath(roomDbName).absolutePath)
|
|
||||||
if (!dbFile.exists()) {
|
|
||||||
throw IllegalStateException("Database file does not exist!")
|
|
||||||
}
|
|
||||||
|
|
||||||
application.container.db.close()
|
|
||||||
|
|
||||||
context.contentResolver.openOutputStream(destinationUri)?.use { outputStream ->
|
|
||||||
dbFile.inputStream().use { inputStream ->
|
|
||||||
copyFile(inputStream, outputStream)
|
|
||||||
}
|
|
||||||
} ?: throw IllegalArgumentException("Unable to open destination Uri for writing")
|
|
||||||
|
|
||||||
context.runOnUiThread {
|
|
||||||
Toast.makeText(context, "Database exported successfully!", Toast.LENGTH_SHORT).show()
|
|
||||||
Toast.makeText(context, "Closing application to avoid changes.", Toast.LENGTH_LONG).show()
|
|
||||||
context.finishAffinity()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("ScanScreenController", "Error exporting database $e")
|
|
||||||
context.runOnUiThread {
|
|
||||||
Toast.makeText(context, "Error exporting database: ${e.message}", Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun importDatabase(sourceUri: Uri) {
|
|
||||||
context.lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
try {
|
|
||||||
if (!getFileNameFromUri(sourceUri)!!.endsWith(".vbhelper")) {
|
|
||||||
context.runOnUiThread {
|
|
||||||
Toast.makeText(context, "Invalid file format", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
application.container.db.close()
|
|
||||||
|
|
||||||
val dbPath = context.getDatabasePath(roomDbName)
|
|
||||||
val shmFile = File(dbPath.parent, "$roomDbName-shm")
|
|
||||||
val walFile = File(dbPath.parent, "$roomDbName-wal")
|
|
||||||
|
|
||||||
// Delete existing database files
|
|
||||||
if (dbPath.exists()) dbPath.delete()
|
|
||||||
if (shmFile.exists()) shmFile.delete()
|
|
||||||
if (walFile.exists()) walFile.delete()
|
|
||||||
|
|
||||||
val dbFile = File(dbPath.absolutePath)
|
|
||||||
|
|
||||||
context.contentResolver.openInputStream(sourceUri)?.use { inputStream ->
|
|
||||||
dbFile.outputStream().use { outputStream ->
|
|
||||||
copyFile(inputStream, outputStream)
|
|
||||||
}
|
|
||||||
} ?: throw IllegalArgumentException("Unable to open source Uri for reading")
|
|
||||||
|
|
||||||
context.runOnUiThread {
|
|
||||||
Toast.makeText(context, "Database imported successfully!", Toast.LENGTH_SHORT).show()
|
|
||||||
Toast.makeText(context, "Reopen the app to finish import process!", Toast.LENGTH_LONG).show()
|
|
||||||
context.finishAffinity()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e("ScanScreenController", "Error importing database $e")
|
|
||||||
context.runOnUiThread {
|
|
||||||
Toast.makeText(context, "Error importing database: ${e.message}", Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getFileNameFromUri(uri: Uri): String? {
|
|
||||||
var fileName: String? = null
|
|
||||||
val cursor = context.contentResolver.query(uri, null, null, null, null)
|
|
||||||
cursor?.use {
|
|
||||||
if (it.moveToFirst()) {
|
|
||||||
val nameIndex = it.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
|
|
||||||
fileName = it.getString(nameIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fileName
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyFile(inputStream: InputStream, outputStream: OutputStream) {
|
|
||||||
val buffer = ByteArray(1024)
|
|
||||||
var bytesRead: Int
|
|
||||||
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
|
||||||
outputStream.write(buffer, 0, bytesRead)
|
|
||||||
}
|
|
||||||
outputStream.flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun importApk(uri: Uri) {
|
private fun importApk(uri: Uri) {
|
||||||
context.lifecycleScope.launch(Dispatchers.IO) {
|
context.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
context.contentResolver.openInputStream(uri).use {
|
context.contentResolver.openInputStream(uri).use {
|
||||||
|
|||||||
+320
@@ -0,0 +1,320 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.settingsScreen.controllers
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.github.cfogrady.vb.dim.card.BemCard
|
||||||
|
import com.github.cfogrady.vb.dim.card.DimCard
|
||||||
|
import com.github.cfogrady.vb.dim.card.DimReader
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.CardCharacter
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.CardProgress
|
||||||
|
import com.github.nacabaro.vbhelper.domain.characters.Sprite
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
class CardImportController(
|
||||||
|
private val database: AppDatabase
|
||||||
|
) {
|
||||||
|
suspend fun importCard(
|
||||||
|
fileReader: InputStream?
|
||||||
|
) {
|
||||||
|
val dimReader = DimReader()
|
||||||
|
val card = dimReader.readCard(fileReader, false)
|
||||||
|
|
||||||
|
val cardModel = Card(
|
||||||
|
cardId = card.header.dimId,
|
||||||
|
logo = card.spriteData.sprites[0].pixelData,
|
||||||
|
name = card.spriteData.text,
|
||||||
|
stageCount = card.adventureLevels.levels.size,
|
||||||
|
logoHeight = card.spriteData.sprites[0].height,
|
||||||
|
logoWidth = card.spriteData.sprites[0].width,
|
||||||
|
isBEm = card is BemCard
|
||||||
|
)
|
||||||
|
|
||||||
|
val cardId = database
|
||||||
|
.cardDao()
|
||||||
|
.insertNewCard(cardModel)
|
||||||
|
|
||||||
|
updateCardProgress(cardId = cardId)
|
||||||
|
|
||||||
|
importCharacterData(cardId, card)
|
||||||
|
|
||||||
|
importEvoData(cardId, card)
|
||||||
|
|
||||||
|
importAdventureMissions(cardId, card)
|
||||||
|
|
||||||
|
importCardFusions(cardId, card)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCardProgress(
|
||||||
|
cardId: Long,
|
||||||
|
) {
|
||||||
|
database
|
||||||
|
.cardProgressDao()
|
||||||
|
.insertCardProgress(
|
||||||
|
CardProgress(
|
||||||
|
cardId = cardId,
|
||||||
|
currentStage = 1,
|
||||||
|
unlocked = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun importCharacterData(
|
||||||
|
cardId: Long,
|
||||||
|
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
||||||
|
) {
|
||||||
|
var spriteCounter = when (card is BemCard) {
|
||||||
|
true -> 54
|
||||||
|
false -> 10
|
||||||
|
}
|
||||||
|
|
||||||
|
val domainCharacters = mutableListOf<CardCharacter>()
|
||||||
|
|
||||||
|
val characters = card
|
||||||
|
.characterStats
|
||||||
|
.characterEntries
|
||||||
|
|
||||||
|
for (index in 0 until characters.size) {
|
||||||
|
var domainSprite: Sprite?
|
||||||
|
if (index < 2 && card is DimCard) {
|
||||||
|
domainSprite = Sprite(
|
||||||
|
width = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.width,
|
||||||
|
height = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.height,
|
||||||
|
spriteIdle1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
||||||
|
spriteIdle2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
|
||||||
|
spriteWalk1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
||||||
|
spriteWalk2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
||||||
|
spriteRun1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
||||||
|
spriteRun2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
||||||
|
spriteTrain1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
||||||
|
spriteTrain2 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
||||||
|
spriteHappy = card.spriteData.sprites[spriteCounter + 4].pixelData,
|
||||||
|
spriteSleep = card.spriteData.sprites[spriteCounter + 5].pixelData,
|
||||||
|
spriteAttack = card.spriteData.sprites[spriteCounter + 2].pixelData,
|
||||||
|
spriteDodge = card.spriteData.sprites[spriteCounter + 3].pixelData
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
domainSprite = Sprite(
|
||||||
|
width = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.width,
|
||||||
|
height = card.spriteData.sprites[spriteCounter + 1].spriteDimensions.height,
|
||||||
|
spriteIdle1 = card.spriteData.sprites[spriteCounter + 1].pixelData,
|
||||||
|
spriteIdle2 = card.spriteData.sprites[spriteCounter + 2].pixelData,
|
||||||
|
spriteWalk1 = card.spriteData.sprites[spriteCounter + 3].pixelData,
|
||||||
|
spriteWalk2 = card.spriteData.sprites[spriteCounter + 4].pixelData,
|
||||||
|
spriteRun1 = card.spriteData.sprites[spriteCounter + 5].pixelData,
|
||||||
|
spriteRun2 = card.spriteData.sprites[spriteCounter + 6].pixelData,
|
||||||
|
spriteTrain1 = card.spriteData.sprites[spriteCounter + 7].pixelData,
|
||||||
|
spriteTrain2 = card.spriteData.sprites[spriteCounter + 8].pixelData,
|
||||||
|
spriteHappy = card.spriteData.sprites[spriteCounter + 9].pixelData,
|
||||||
|
spriteSleep = card.spriteData.sprites[spriteCounter + 10].pixelData,
|
||||||
|
spriteAttack = card.spriteData.sprites[spriteCounter + 11].pixelData,
|
||||||
|
spriteDodge = card.spriteData.sprites[spriteCounter + 12].pixelData
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val spriteId = database
|
||||||
|
.spriteDao()
|
||||||
|
.insertSprite(domainSprite)
|
||||||
|
|
||||||
|
|
||||||
|
domainCharacters.add(
|
||||||
|
CardCharacter(
|
||||||
|
cardId = cardId,
|
||||||
|
spriteId = spriteId,
|
||||||
|
charaIndex = index,
|
||||||
|
nameSprite = card.spriteData.sprites[spriteCounter].pixelData,
|
||||||
|
stage = characters[index].stage,
|
||||||
|
attribute = NfcCharacter.Attribute.entries[characters[index].attribute],
|
||||||
|
baseHp = characters[index].hp,
|
||||||
|
baseBp = characters[index].dp,
|
||||||
|
baseAp = characters[index].ap,
|
||||||
|
nameWidth = card.spriteData.sprites[spriteCounter].spriteDimensions.width,
|
||||||
|
nameHeight = card.spriteData.sprites[spriteCounter].spriteDimensions.height
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
spriteCounter += if (card is BemCard) {
|
||||||
|
14
|
||||||
|
} else {
|
||||||
|
when (index) {
|
||||||
|
0 -> 6
|
||||||
|
1 -> 7
|
||||||
|
else -> 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
database
|
||||||
|
.characterDao()
|
||||||
|
.insertCharacter(*domainCharacters.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun importAdventureMissions(
|
||||||
|
cardId: Long,
|
||||||
|
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
||||||
|
) {
|
||||||
|
Log.d("importAdventureMissions", "Importing adventure missions")
|
||||||
|
if (card is BemCard) {
|
||||||
|
card.adventureLevels.levels.forEach {
|
||||||
|
database
|
||||||
|
.cardAdventureDao()
|
||||||
|
.insertNewAdventure(
|
||||||
|
cardId = cardId,
|
||||||
|
characterId = it.bossCharacterIndex,
|
||||||
|
steps = it.steps,
|
||||||
|
bossAp = it.bossAp,
|
||||||
|
bossHp = it.bossHp,
|
||||||
|
bossDp = it.bossDp,
|
||||||
|
bossBp = it.bossBp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (card is DimCard) {
|
||||||
|
card.adventureLevels.levels.map {
|
||||||
|
database
|
||||||
|
.cardAdventureDao()
|
||||||
|
.insertNewAdventure(
|
||||||
|
cardId = cardId,
|
||||||
|
characterId = it.bossCharacterIndex,
|
||||||
|
steps = it.steps,
|
||||||
|
bossAp = it.bossAp,
|
||||||
|
bossHp = it.bossHp,
|
||||||
|
bossDp = it.bossDp,
|
||||||
|
bossBp = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun importCardFusions(
|
||||||
|
cardId: Long,
|
||||||
|
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
||||||
|
) {
|
||||||
|
Log.d("importCardFusions", "Importing card fusions")
|
||||||
|
if (card is DimCard) {
|
||||||
|
card
|
||||||
|
.attributeFusions
|
||||||
|
.entries
|
||||||
|
.forEach {
|
||||||
|
Log.d("importCardFusions", "Importing fusion: ${it.attribute1Fusion}")
|
||||||
|
if (it.attribute1Fusion != 65535 && it.characterIndex != 65535) {
|
||||||
|
database
|
||||||
|
.cardFusionsDao()
|
||||||
|
.insertNewFusion(
|
||||||
|
cardId = cardId,
|
||||||
|
fromCharaId = it.characterIndex,
|
||||||
|
attribute = NfcCharacter.Attribute.Virus,
|
||||||
|
toCharaId = it.attribute1Fusion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.attribute2Fusion != 65535 && it.characterIndex != 65535) {
|
||||||
|
database
|
||||||
|
.cardFusionsDao()
|
||||||
|
.insertNewFusion(
|
||||||
|
cardId = cardId,
|
||||||
|
fromCharaId = it.characterIndex,
|
||||||
|
attribute = NfcCharacter.Attribute.Data,
|
||||||
|
toCharaId = it.attribute2Fusion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.attribute3Fusion != 65535 && it.characterIndex != 65535) {
|
||||||
|
database
|
||||||
|
.cardFusionsDao()
|
||||||
|
.insertNewFusion(
|
||||||
|
cardId = cardId,
|
||||||
|
fromCharaId = it.characterIndex,
|
||||||
|
attribute = NfcCharacter.Attribute.Vaccine,
|
||||||
|
toCharaId = it.attribute3Fusion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.attribute4Fusion != 65535 && it.characterIndex != 65535) {
|
||||||
|
database
|
||||||
|
.cardFusionsDao()
|
||||||
|
.insertNewFusion(
|
||||||
|
cardId = cardId,
|
||||||
|
fromCharaId = it.characterIndex,
|
||||||
|
attribute = NfcCharacter.Attribute.Free,
|
||||||
|
toCharaId = it.attribute4Fusion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun importEvoData(
|
||||||
|
cardId: Long,
|
||||||
|
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
|
||||||
|
) {
|
||||||
|
for (index in 0 until card.transformationRequirements.transformationEntries.size) {
|
||||||
|
val evo = card.transformationRequirements.transformationEntries[index]
|
||||||
|
|
||||||
|
var transformationTimerHours: Int
|
||||||
|
var unlockAdventureLevel: Int
|
||||||
|
|
||||||
|
if (card is BemCard) {
|
||||||
|
transformationTimerHours = card
|
||||||
|
.transformationRequirements
|
||||||
|
.transformationEntries[index]
|
||||||
|
.minutesUntilTransformation / 60
|
||||||
|
unlockAdventureLevel = if (
|
||||||
|
card
|
||||||
|
.transformationRequirements
|
||||||
|
.transformationEntries[index]
|
||||||
|
.requiredCompletedAdventureLevel == 65535
|
||||||
|
) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
card
|
||||||
|
.transformationRequirements
|
||||||
|
.transformationEntries[index]
|
||||||
|
.requiredCompletedAdventureLevel
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transformationTimerHours = (card as DimCard)
|
||||||
|
.transformationRequirements
|
||||||
|
.transformationEntries[index]
|
||||||
|
.hoursUntilEvolution
|
||||||
|
unlockAdventureLevel = if (
|
||||||
|
card
|
||||||
|
.adventureLevels
|
||||||
|
.levels
|
||||||
|
.last()
|
||||||
|
.bossCharacterIndex == card.transformationRequirements.transformationEntries[index].toCharacterIndex
|
||||||
|
) {
|
||||||
|
14
|
||||||
|
/*
|
||||||
|
Magic number incoming!!
|
||||||
|
|
||||||
|
In the case of DiMCards, stage 15 is the one that unlocks the locked character.
|
||||||
|
We know it is a locked character if the last adventure level's boss character index
|
||||||
|
is the current index. If it is, we add stage 15 complete as a requirement for transformation.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
/*
|
||||||
|
Another magic number...
|
||||||
|
|
||||||
|
The rest of the characters are not locked.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
database
|
||||||
|
.characterDao()
|
||||||
|
.insertPossibleTransformation(
|
||||||
|
cardId = cardId,
|
||||||
|
fromChraraIndex = evo.fromCharacterIndex,
|
||||||
|
toChraraIndex = evo.toCharacterIndex,
|
||||||
|
requiredVitals = evo.requiredVitalValues,
|
||||||
|
requiredTrophies = evo.requiredTrophies,
|
||||||
|
requiredBattles = evo.requiredBattles,
|
||||||
|
requiredWinRate = evo.requiredWinRatio,
|
||||||
|
requiredAdventureLevelCompleted = unlockAdventureLevel,
|
||||||
|
changeTimerHours = transformationTimerHours
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.settingsScreen.controllers
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.OpenableColumns
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
|
||||||
|
class DatabaseManagementController(
|
||||||
|
val componentActivity: ComponentActivity,
|
||||||
|
val application: VBHelper
|
||||||
|
) {
|
||||||
|
private val roomDbName = "internalDb"
|
||||||
|
|
||||||
|
fun exportDatabase( destinationUri: Uri) {
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val dbFile = File(componentActivity.getDatabasePath(roomDbName).absolutePath)
|
||||||
|
if (!dbFile.exists()) {
|
||||||
|
throw IllegalStateException("Database file does not exist!")
|
||||||
|
}
|
||||||
|
|
||||||
|
application.container.db.close()
|
||||||
|
|
||||||
|
componentActivity.contentResolver.openOutputStream(destinationUri)?.use { outputStream ->
|
||||||
|
dbFile.inputStream().use { inputStream ->
|
||||||
|
copyFile(inputStream, outputStream)
|
||||||
|
}
|
||||||
|
} ?: throw IllegalArgumentException("Unable to open destination Uri for writing")
|
||||||
|
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(componentActivity, "Database exported successfully!", Toast.LENGTH_SHORT).show()
|
||||||
|
Toast.makeText(componentActivity, "Closing application to avoid changes.", Toast.LENGTH_LONG).show()
|
||||||
|
componentActivity.finishAffinity()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("ScanScreenController", "Error exporting database $e")
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(componentActivity, "Error exporting database: ${e.message}", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun importDatabase(sourceUri: Uri) {
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
if (!getFileNameFromUri(sourceUri)!!.endsWith(".vbhelper")) {
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(componentActivity, "Invalid file format", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
application.container.db.close()
|
||||||
|
|
||||||
|
val dbPath = componentActivity.getDatabasePath(roomDbName)
|
||||||
|
val shmFile = File(dbPath.parent, "$roomDbName-shm")
|
||||||
|
val walFile = File(dbPath.parent, "$roomDbName-wal")
|
||||||
|
|
||||||
|
// Delete existing database files
|
||||||
|
if (dbPath.exists()) dbPath.delete()
|
||||||
|
if (shmFile.exists()) shmFile.delete()
|
||||||
|
if (walFile.exists()) walFile.delete()
|
||||||
|
|
||||||
|
val dbFile = File(dbPath.absolutePath)
|
||||||
|
|
||||||
|
componentActivity.contentResolver.openInputStream(sourceUri)?.use { inputStream ->
|
||||||
|
dbFile.outputStream().use { outputStream ->
|
||||||
|
copyFile(inputStream, outputStream)
|
||||||
|
}
|
||||||
|
} ?: throw IllegalArgumentException("Unable to open source Uri for reading")
|
||||||
|
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(componentActivity, "Database imported successfully!", Toast.LENGTH_SHORT).show()
|
||||||
|
Toast.makeText(componentActivity, "Reopen the app to finish import process!", Toast.LENGTH_LONG).show()
|
||||||
|
componentActivity.finishAffinity()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("ScanScreenController", "Error importing database $e")
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(componentActivity, "Error importing database: ${e.message}", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyFile(inputStream: InputStream, outputStream: OutputStream) {
|
||||||
|
val buffer = ByteArray(1024)
|
||||||
|
var bytesRead: Int
|
||||||
|
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead)
|
||||||
|
}
|
||||||
|
outputStream.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFileNameFromUri(uri: Uri): String? {
|
||||||
|
var fileName: String? = null
|
||||||
|
val cursor = componentActivity.contentResolver.query(uri, null, null, null, null)
|
||||||
|
cursor?.use {
|
||||||
|
if (it.moveToFirst()) {
|
||||||
|
val nameIndex = it.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
|
||||||
|
fileName = it.getString(nameIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileName
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ import kotlinx.coroutines.launch
|
|||||||
fun StorageDialog(
|
fun StorageDialog(
|
||||||
characterId: Long,
|
characterId: Long,
|
||||||
onDismissRequest: () -> Unit,
|
onDismissRequest: () -> Unit,
|
||||||
|
onClickDelete: () -> Unit,
|
||||||
onSendToBracelet: () -> Unit,
|
onSendToBracelet: () -> Unit,
|
||||||
onClickSetActive: () -> Unit,
|
onClickSetActive: () -> Unit,
|
||||||
onClickSendToAdventure: (time: Long) -> Unit
|
onClickSendToAdventure: (time: Long) -> Unit
|
||||||
@@ -141,6 +142,13 @@ fun StorageDialog(
|
|||||||
) {
|
) {
|
||||||
Text(text = "Send on adventure")
|
Text(text = "Send on adventure")
|
||||||
}
|
}
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
onClick = onClickDelete
|
||||||
|
) {
|
||||||
|
Text(text = "Delete character")
|
||||||
|
}
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
|
|||||||
+28
-15
@@ -1,5 +1,6 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens.storageScreen
|
package com.github.nacabaro.vbhelper.screens.storageScreen
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
import androidx.compose.foundation.gestures.scrollable
|
import androidx.compose.foundation.gestures.scrollable
|
||||||
@@ -11,14 +12,15 @@ import androidx.compose.foundation.lazy.grid.GridCells
|
|||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -28,12 +30,10 @@ import androidx.navigation.NavController
|
|||||||
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
import com.github.nacabaro.vbhelper.components.CharacterEntry
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
import com.github.nacabaro.vbhelper.di.VBHelper
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
|
||||||
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
import com.github.nacabaro.vbhelper.navigation.NavigationItems
|
||||||
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
|
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
|
||||||
import com.github.nacabaro.vbhelper.source.StorageRepository
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
import com.github.nacabaro.vbhelper.utils.BitmapData
|
import com.github.nacabaro.vbhelper.utils.BitmapData
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -42,18 +42,11 @@ fun StorageScreen(
|
|||||||
storageScreenController: StorageScreenControllerImpl,
|
storageScreenController: StorageScreenControllerImpl,
|
||||||
adventureScreenController: AdventureScreenControllerImpl
|
adventureScreenController: AdventureScreenControllerImpl
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val application = LocalContext.current.applicationContext as VBHelper
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
val storageRepository = StorageRepository(application.container.db)
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
val monList = remember { mutableStateOf<List<CharacterDtos.CharacterWithSprites>>(emptyList()) }
|
val characterList by storageRepository.getAllCharacters().collectAsState(initial = emptyList())
|
||||||
var selectedCharacter by remember { mutableStateOf<Long?>(null) }
|
|
||||||
|
|
||||||
LaunchedEffect(storageRepository, selectedCharacter) {
|
var selectedCharacter by remember { mutableStateOf<Long?>(null) }
|
||||||
coroutineScope.launch {
|
|
||||||
val characterList = storageRepository.getAllCharacters()
|
|
||||||
monList.value = characterList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = {
|
topBar = {
|
||||||
@@ -65,7 +58,7 @@ fun StorageScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
if (monList.value.isEmpty()) {
|
if (characterList.isEmpty()) {
|
||||||
Column (
|
Column (
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
@@ -86,7 +79,7 @@ fun StorageScreen(
|
|||||||
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
|
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
|
||||||
.padding(top = contentPadding.calculateTopPadding())
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
items(monList.value) { index ->
|
items(characterList) { index ->
|
||||||
CharacterEntry(
|
CharacterEntry(
|
||||||
icon = BitmapData(
|
icon = BitmapData(
|
||||||
bitmap = index.spriteIdle,
|
bitmap = index.spriteIdle,
|
||||||
@@ -107,6 +100,16 @@ fun StorageScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
cardColors = if (index.active) {
|
||||||
|
CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceContainerHighest
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,6 +141,16 @@ fun StorageScreen(
|
|||||||
timeInMinutes = time
|
timeInMinutes = time
|
||||||
)
|
)
|
||||||
selectedCharacter = null
|
selectedCharacter = null
|
||||||
|
},
|
||||||
|
onClickDelete = {
|
||||||
|
storageScreenController
|
||||||
|
.deleteCharacter(
|
||||||
|
characterId = selectedCharacter!!,
|
||||||
|
onCompletion = {
|
||||||
|
Log.d("StorageScreen", "Character deleted")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
selectedCharacter = null
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -2,4 +2,5 @@ package com.github.nacabaro.vbhelper.screens.storageScreen
|
|||||||
|
|
||||||
interface StorageScreenController {
|
interface StorageScreenController {
|
||||||
fun setActive(characterId: Long, onCompletion: () -> Unit)
|
fun setActive(characterId: Long, onCompletion: () -> Unit)
|
||||||
|
fun deleteCharacter(characterId: Long, onCompletion: () -> Unit)
|
||||||
}
|
}
|
||||||
+17
@@ -28,4 +28,21 @@ class StorageScreenControllerImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun deleteCharacter(characterId: Long, onCompletion: () -> Unit) {
|
||||||
|
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
database
|
||||||
|
.userCharacterDao()
|
||||||
|
.deleteCharacterById(characterId)
|
||||||
|
|
||||||
|
componentActivity.runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
componentActivity,
|
||||||
|
"Character deleted!",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
onCompletion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,19 +3,24 @@ package com.github.nacabaro.vbhelper.source
|
|||||||
import com.github.nacabaro.vbhelper.database.AppDatabase
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
import com.github.nacabaro.vbhelper.dtos.CardDtos
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
class DexRepository (
|
class DexRepository (
|
||||||
private val db: AppDatabase
|
private val db: AppDatabase
|
||||||
) {
|
) {
|
||||||
suspend fun getAllDims(): List<CardDtos.CardProgress> {
|
fun getAllDims(): Flow<List<CardDtos.CardProgress>> {
|
||||||
return db.dexDao().getCardsWithProgress()
|
return db.dexDao().getCardsWithProgress()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCharactersByCardId(cardId: Long): List<CharacterDtos.CardCharaProgress> {
|
fun getCharactersByCardId(cardId: Long): Flow<List<CharacterDtos.CardCharaProgress>> {
|
||||||
return db.dexDao().getSingleCardProgress(cardId)
|
return db.dexDao().getSingleCardProgress(cardId)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCardPossibleTransformations(cardId: Long): List<CharacterDtos.EvolutionRequirementsWithSpritesAndObtained> {
|
fun getCharacterPossibleTransformations(characterId: Long): Flow<List<CharacterDtos.EvolutionRequirementsWithSpritesAndObtained>> {
|
||||||
return db.characterDao().getEvolutionRequirementsForCard(cardId)
|
return db.characterDao().getEvolutionRequirementsForCard(characterId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCharacterPossibleFusions(characterId: Long): Flow<List<CharacterDtos.FusionsWithSpritesAndObtained>> {
|
||||||
|
return db.cardFusionsDao().getFusionsForCharacter(characterId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.source
|
||||||
|
|
||||||
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
|
import com.github.nacabaro.vbhelper.domain.card.Card
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class ScanRepository(
|
||||||
|
val database: AppDatabase
|
||||||
|
) {
|
||||||
|
fun getCardDetails(characterId: Long): Flow<Card> {
|
||||||
|
return database.cardDao().getCardByCharacterId(characterId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,11 +6,12 @@ import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions
|
|||||||
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
|
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
|
||||||
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
|
||||||
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
import com.github.nacabaro.vbhelper.dtos.ItemDtos
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
class StorageRepository (
|
class StorageRepository (
|
||||||
private val db: AppDatabase
|
private val db: AppDatabase
|
||||||
) {
|
) {
|
||||||
suspend fun getAllCharacters(): List<CharacterDtos.CharacterWithSprites> {
|
fun getAllCharacters(): Flow<List<CharacterDtos.CharacterWithSprites>> {
|
||||||
return db.userCharacterDao().getAllCharacters()
|
return db.userCharacterDao().getAllCharacters()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ class StorageRepository (
|
|||||||
return db.userCharacterDao().deleteCharacterById(id)
|
return db.userCharacterDao().deleteCharacterById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getAdventureCharacters(): List<CharacterDtos.AdventureCharacterWithSprites> {
|
fun getAdventureCharacters(): Flow<List<CharacterDtos.AdventureCharacterWithSprites>> {
|
||||||
return db.adventureDao().getAdventureCharacters()
|
return db.adventureDao().getAdventureCharacters()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user