diff --git a/README.md b/README.md
index d9be74f..72298e4 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,69 @@
# VBHelper
-## Developer Setup
+Application to interact with the Vital series, VB, VH, VBC and VBBE.
-1. Clone vb-nfc-reader (https://github.com/cfogrady/lib-vb-nfc)
-2. Run vb-nfc-reader/publishToMavenLocal gradle task in the lib-vb-nfc project.
-3. Clone vb-dim-reader (https://github.com/cfogrady/vb-dim-reader)
-4. Run publishToMavenLocal gradle task in the vb-dim-reader project.
-5. Create res/values/keys.xml within the app module.
-6. Populate with:
-```
-
-
- beHmacKey1
- beHmacKey2
- aesKey
-
- - 0
- - 1
- - 2
- - 3
- - 4
- - 5
- - 6
- - 7
- - 8
- - 9
- - 10
- - 11
- - 12
- - 13
- - 14
- - 15
-
-
-```
-7. Replace the values in the keys.xml file with those extracted from the original app.
-8. Run
\ No newline at end of file
+## Current state of the project
+
+Right now the project is still under development, and until further notice, any database updates will result in having to erase application data.
+
+This document will be updated once the application does not need any more database resets.
+
+## Features
+
+As of now, the project allows you to read characters, view characters stats, and send them back to your watch.
+
+You can also apply items to the characters read, such as special missions, or change timers, and store characters in the storage section.
+
+You also earn new items every time an item such as a special mission (VB only) or a character completes an in-app adventure mission.
+
+App also comes with a dex that will update every time a new character is added, and allows you to see evolution requirements and current adventure stage in the watch.
+
+## How to set up
+
+1. Download the latest version for VB Arena APK from a trustworthy source. If your download is a standalone APK, continue to step 2. Otherwise, if your download is an XAPK, do the following:
+
+ 1. Using your phone file manager, rename the XAPK file to ZIP, and extract its contents. You can also do this with any other device, such as Windows, macOS and Linux.
+
+ 2. Once the files are extracted, look for an APK called `com.bandai.vitalbraceletarena.apk`. Copy it somewhere else, you will need it.
+
+2. Install an APK release for VB Arena. You will find the releases [here](http://github.com/nacabaro/vbhelper/releases). Download the latest release and install its APK.
+
+ Note, in the current stage of the project, you will have to delete the old application from your device. If the app keeps crashing after installing, clear application data and storage.
+
+3. Import secrets in the app. These secrets will allow the app to talk to the watch. On the main screen, click on the gear icon, then `Import secrets`.
+
+ You will be prompted to choose a file. Choose the APK file that was previously obtained.
+
+4. Import cards. Due to copyright laws, we cannot offer the characters and sprites themselves in the application. In order to import the cards do the following.
+
+ 1. Using your own DiM/BEm cards, dump the cards to your device. You can get an in-depth tutorial in [here](http://mrblinky.net/digimon/vb/dimcardtool/dimcardtool.html). You can download the dump tool from [here](http://mrblinky.net/digimon/vb/dimcardtool/)
+
+ 2. Once installed the tool and drivers, open the tool, connect your DiM/BEm reader hardware to yout computer and click on Read card.
+
+ 3. Transfer the resulting file to your mobile device. You can put them anywhere, as long as they are accessible. My recommendation is to put them under a folder called `Cards` in your `Internal storage` or `SD Card`
+
+ 4. In the app, click on import card. Next choose the BIN file corresponding to the card you want to import.
+
+ **Note: if you do not import the card, whenever you attempt to read a character from th watch, the character you read will get deleted.**
+
+5. App will now be ready to be used.
+
+## Planned features
+
+- Online battles, undegoing development by `lightheel`.
+
+- VitalWear compatibility, undergoing development by `cfogrady`.
+
+- Support for multiple languages, not yet started.
+
+- Database backup/restore.
+
+## Credits
+
+- `cyanic` for helping us understand more about the VB connection protocol.
+
+- `cfogrady` for making both [`VB-DIM-Reader`](https://github.com/cfogrady/VB-DIM-Reader) and [`lib-vb-nfc`](https://github.com/cfogrady/lib-vb-nfc)
+
+- `lightheel` for working on the online component in the application, both server and battle client.
+
+- `shvstrz` for the app icon.
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index e687775..7e4a241 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -15,7 +15,7 @@ android {
minSdk = 28
targetSdk = 35
versionCode = 1
- versionName = "Alpha 0.6"
+ versionName = "Alpha 0.6.2"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -91,11 +91,5 @@ dependencies {
implementation("com.google.android.material:material:1.2.0")
implementation(libs.protobuf.javalite)
implementation("androidx.compose.material:material")
-
- implementation("com.squareup.retrofit2:retrofit:2.9.0")
- implementation("com.squareup.retrofit2:converter-gson:2.9.0")
- implementation("com.google.code.gson:gson:2.10.1")
-
- // HTTP request logging
- implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
+ implementation("androidx.datastore:datastore-preferences:1.1.7")
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/components/CharacterEntry.kt b/app/src/main/java/com/github/nacabaro/vbhelper/components/CharacterEntry.kt
index a6ffa91..9b929d5 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/components/CharacterEntry.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/components/CharacterEntry.kt
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
+import androidx.compose.material3.CardColors
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@@ -44,6 +45,9 @@ fun CharacterEntry(
disabled: Boolean = false,
shape: Shape = MaterialTheme.shapes.medium,
multiplier: Int = 4,
+ cardColors: CardColors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainerHighest
+ ),
onClick: () -> Unit = { }
) {
val bitmap = remember (icon.bitmap) {
@@ -61,7 +65,8 @@ fun CharacterEntry(
},
modifier = modifier
.aspectRatio(1f)
- .padding(8.dp)
+ .padding(8.dp),
+ colors = cardColors
) {
Box(
contentAlignment = Alignment.BottomCenter,
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/AdventureDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/AdventureDao.kt
index 5197e7d..7167b97 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/AdventureDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/AdventureDao.kt
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Query
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
@Dao
@@ -31,13 +32,13 @@ interface AdventureDao {
a.finishesAdventure AS finishesAdventure,
a.originalDuration AS originalTimeInMinutes
FROM UserCharacter uc
- JOIN CharacterData c ON uc.charId = c.id
+ JOIN CardCharacter c ON uc.charId = c.id
JOIN Sprite s ON s.id = c.spriteId
JOIN Card d ON c.cardId = d.id
JOIN Adventure a ON uc.id = a.characterId
"""
)
- suspend fun getAdventureCharacters(): List
+ fun getAdventureCharacters(): Flow>
@Query("""
DELETE FROM Adventure
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardAdventureDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardAdventureDao.kt
new file mode 100644
index 0000000..3496ec2
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardAdventureDao.kt
@@ -0,0 +1,59 @@
+package com.github.nacabaro.vbhelper.daos
+
+import androidx.room.Dao
+import androidx.room.Query
+import com.github.nacabaro.vbhelper.dtos.CardDtos
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface CardAdventureDao {
+ @Query("""
+ INSERT INTO
+ CardAdventure (cardId, characterId, steps, bossAp, bossHp, bossDp, bossBp)
+ SELECT
+ :cardId,
+ cc.id,
+ :steps,
+ :bossAp,
+ :bossHp,
+ :bossDp,
+ :bossBp
+ FROM
+ CardCharacter cc
+ WHERE
+ cc.charaIndex = :characterId AND
+ cc.cardId = :cardId
+ """)
+ suspend fun insertNewAdventure(
+ cardId: Long,
+ characterId: Int,
+ steps: Int,
+ bossAp: Int,
+ bossHp: Int,
+ bossDp: Int,
+ bossBp: Int?
+ )
+
+ @Query("""
+ SELECT
+ cc.nameSprite as characterName,
+ cc.nameWidth as characterNameWidth,
+ cc.nameHeight as characterNameHeight,
+ s.spriteIdle1 as characterIdleSprite,
+ s.width as characterIdleSpriteWidth,
+ s.height as characterIdleSpriteHeight,
+ ca.bossAp as characterAp,
+ ca.bossBp as characterBp,
+ ca.bossDp as characterDp,
+ ca.bossHp as characterHp,
+ ca.steps as steps
+ FROM CardCharacter cc
+ JOIN Sprite s ON cc.spriteId = s.id
+ JOIN CardAdventure ca ON cc.id = ca.characterId
+ WHERE
+ cc.cardId = :cardId
+ """)
+ fun getAdventureForCard(
+ cardId: Long
+ ): Flow>
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt
index a55ad14..e9511f2 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt
@@ -5,6 +5,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.card.Card
+import kotlinx.coroutines.flow.Flow
@Dao
interface CardDao {
@@ -21,12 +22,12 @@ interface CardDao {
"""
SELECT ca.*
FROM Card ca
- JOIN CharacterData ch ON ca.id = ch.cardId
+ JOIN CardCharacter ch ON ca.id = ch.cardId
JOIN UserCharacter uc ON ch.id = uc.charId
WHERE uc.id = :id
"""
)
- suspend fun getCardByCharacterId(id: Long): Card
+ fun getCardByCharacterId(id: Long): Flow
@Query("UPDATE Card SET name = :newName WHERE id = :id")
suspend fun renameCard(id: Int, newName: String)
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardFusionsDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardFusionsDao.kt
new file mode 100644
index 0000000..86d6a9a
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardFusionsDao.kt
@@ -0,0 +1,48 @@
+package com.github.nacabaro.vbhelper.daos
+
+import androidx.room.Dao
+import androidx.room.Query
+import com.github.cfogrady.vbnfc.data.NfcCharacter
+import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface CardFusionsDao {
+ @Query("""
+ INSERT INTO
+ CardFusions (
+ fromCharaId,
+ attribute,
+ toCharaId
+ )
+ SELECT
+ (SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :fromCharaId),
+ :attribute,
+ (SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaId)
+ """)
+ suspend fun insertNewFusion(
+ cardId: Long,
+ fromCharaId: Int,
+ attribute: NfcCharacter.Attribute,
+ toCharaId: 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>
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardProgressDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardProgressDao.kt
index 788dc77..3fde614 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardProgressDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CardProgressDao.kt
@@ -1,17 +1,29 @@
package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
+import androidx.room.Insert
import androidx.room.Query
-import androidx.room.Upsert
import com.github.nacabaro.vbhelper.domain.card.CardProgress
+import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
@Dao
interface CardProgressDao {
- @Upsert
- fun updateDimProgress(vararg cardProgresses: CardProgress)
+ @Query("""
+ UPDATE CardProgress
+ SET
+ currentStage = :currentStage,
+ unlocked = :unlocked
+ WHERE cardId = :cardId AND
+ currentStage < :currentStage
+ """)
+ fun updateCardProgress(currentStage: Int, cardId: Long, unlocked: Boolean)
@Query(
"SELECT currentStage FROM CardProgress WHERE cardId = :cardId"
)
- fun getCardProgress(cardId: Int): Int
+ fun getCardProgress(cardId: Long): Flow
+
+ @Insert
+ fun insertCardProgress(cardProgress: CardProgress)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt
index a7683f1..378e92f 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt
@@ -3,17 +3,18 @@ package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
@Dao
interface CharacterDao {
@Insert
- suspend fun insertCharacter(vararg characterData: CharacterData)
+ suspend fun insertCharacter(vararg characterData: CardCharacter)
- @Query("SELECT * FROM CharacterData WHERE charaIndex = :monIndex AND cardId = :dimId LIMIT 1")
- fun getCharacterByMonIndex(monIndex: Int, dimId: Long): CharacterData
+ @Query("SELECT * FROM CardCharacter WHERE charaIndex = :monIndex AND cardId = :dimId LIMIT 1")
+ fun getCharacterByMonIndex(monIndex: Int, dimId: Long): CardCharacter
@Insert
suspend fun insertSprite(vararg sprite: Sprite)
@@ -24,10 +25,12 @@ interface CharacterDao {
d.cardId as cardId,
c.charaIndex as charId,
c.stage as stage,
- c.attribute as attribute
- FROM CharacterData c
+ c.attribute as attribute,
+ cp.currentStage as currentStage
+ FROM CardCharacter c
JOIN UserCharacter uc ON c.id = uc.charId
JOIN Card d ON c.cardId = d.id
+ JOIN CardProgress cp ON d.id = cp.cardId
WHERE c.id = :charId
"""
)
@@ -37,14 +40,14 @@ interface CharacterDao {
"""
INSERT INTO PossibleTransformations (charaId, requiredVitals, requiredTrophies, requiredBattles, requiredWinRate, changeTimerHours, requiredAdventureLevelCompleted, toCharaId)
SELECT
- (SELECT id FROM CharacterData WHERE charaIndex = :fromChraraIndex AND cardId = :cardId),
+ (SELECT id FROM CardCharacter WHERE charaIndex = :fromChraraIndex AND cardId = :cardId),
:requiredVitals,
:requiredTrophies,
:requiredBattles,
:requiredWinRate,
:changeTimerHours,
:requiredAdventureLevelCompleted,
- (SELECT id FROM CharacterData WHERE charaIndex = :toChraraIndex AND cardId = :cardId)
+ (SELECT id FROM CardCharacter WHERE charaIndex = :toChraraIndex AND cardId = :cardId)
"""
)
suspend fun insertPossibleTransformation(
@@ -76,12 +79,12 @@ interface CharacterDao {
pt.requiredAdventureLevelCompleted as requiredAdventureLevelCompleted
FROM
PossibleTransformations pt
- JOIN CharacterData c on pt.toCharaId = c.id
+ JOIN CardCharacter c on pt.toCharaId = c.id
JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Dex d ON d.id = pt.toCharaId
WHERE
- c.cardId = :cardId
+ pt.charaId = :characterId
"""
)
- suspend fun getEvolutionRequirementsForCard(cardId: Long): List
+ fun getEvolutionRequirementsForCard(characterId: Long): Flow>
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/DexDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/DexDao.kt
index ecba234..c343796 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/DexDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/DexDao.kt
@@ -4,6 +4,7 @@ import androidx.room.Dao
import androidx.room.Query
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
@Dao
interface DexDao {
@@ -11,7 +12,7 @@ interface DexDao {
"""
INSERT OR IGNORE INTO Dex(id, discoveredOn)
VALUES (
- (SELECT id FROM CharacterData WHERE charaIndex = :charIndex AND cardId = :cardId),
+ (SELECT id FROM CardCharacter WHERE charaIndex = :charIndex AND cardId = :cardId),
:discoveredOn
)
"""
@@ -34,13 +35,13 @@ interface DexDao {
c.baseAp as baseAp,
c.stage as stage,
c.attribute as attribute
- FROM CharacterData c
+ FROM CardCharacter c
JOIN Sprite s ON c.spriteId = s.id
LEFT JOIN dex d ON c.id = d.id
WHERE c.cardId = :cardId
"""
)
- suspend fun getSingleCardProgress(cardId: Long): List
+ fun getSingleCardProgress(cardId: Long): Flow>
@Query(
"""
@@ -50,10 +51,10 @@ interface DexDao {
c.logo as cardLogo,
c.logoWidth as logoWidth,
c.logoHeight as logoHeight,
- (SELECT COUNT(*) FROM CharacterData cc WHERE cc.cardId = c.id) AS totalCharacters,
- (SELECT COUNT(*) FROM Dex d JOIN CharacterData cc ON d.id = cc.id WHERE cc.cardId = c.id AND d.discoveredOn IS NOT NULL) AS obtainedCharacters
+ (SELECT COUNT(*) FROM CardCharacter cc WHERE cc.cardId = c.id) AS totalCharacters,
+ (SELECT COUNT(*) FROM Dex d JOIN CardCharacter cc ON d.id = cc.id WHERE cc.cardId = c.id AND d.discoveredOn IS NOT NULL) AS obtainedCharacters
FROM Card c
"""
)
- suspend fun getCardsWithProgress(): List
+ fun getCardsWithProgress(): Flow>
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt
index 1164815..076de9d 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/ItemDao.kt
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Query
import com.github.nacabaro.vbhelper.dtos.ItemDtos
+import kotlinx.coroutines.flow.Flow
@Dao
interface ItemDao {
@@ -13,7 +14,7 @@ interface ItemDao {
ORDER BY Items.itemIcon ASC
"""
)
- suspend fun getAllItems(): List
+ fun getAllItems(): Flow>
@Query(
"""
@@ -22,7 +23,7 @@ interface ItemDao {
WHERE quantity > 0
"""
)
- suspend fun getAllUserItems(): List
+ fun getAllUserItems(): Flow>
@Query(
"""
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt
index 00cc1df..1bc97fc 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/daos/UserCharacterDao.kt
@@ -5,7 +5,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Upsert
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions
@@ -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.VitalsHistory
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
@Dao
interface UserCharacterDao {
@@ -47,7 +48,7 @@ interface UserCharacterDao {
c.charaIndex AS monIndex,
t.transformationDate AS transformationDate
FROM TransformationHistory t
- JOIN CharacterData c ON c.id = t.stageId
+ JOIN CardCharacter c ON c.id = t.stageId
JOIN Sprite s ON s.id = c.spriteId
WHERE monId = :monId
"""
@@ -68,15 +69,16 @@ interface UserCharacterDao {
c.nameWidth as nameSpriteWidth,
c.nameHeight as nameSpriteHeight,
d.isBEm as isBemCard,
- a.characterId = uc.id as isInAdventure
+ a.characterId = uc.id as isInAdventure,
+ uc.isActive as active
FROM UserCharacter uc
- JOIN CharacterData c ON uc.charId = c.id
+ JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON d.id = c.cardId
JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id
"""
)
- suspend fun getAllCharacters(): List
+ fun getAllCharacters(): Flow>
@Query(
"""
@@ -92,9 +94,10 @@ interface UserCharacterDao {
c.nameWidth as nameSpriteWidth,
c.nameHeight as nameSpriteHeight,
d.isBEm as isBemCard,
- a.characterId = uc.id as isInAdventure
+ a.characterId = uc.id as isInAdventure,
+ uc.isActive as active
FROM UserCharacter uc
- JOIN CharacterData c ON uc.charId = c.id
+ JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON c.cardId = d.id
JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id
@@ -129,9 +132,10 @@ interface UserCharacterDao {
c.nameWidth as nameSpriteWidth,
c.nameHeight as nameSpriteHeight,
d.isBEm as isBemCard,
- a.characterId as isInAdventure
+ a.characterId as isInAdventure,
+ uc.isActive as active
FROM UserCharacter uc
- JOIN CharacterData c ON uc.charId = c.id
+ JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON c.cardId = d.id
JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id
@@ -153,13 +157,13 @@ interface UserCharacterDao {
@Query(
"""
SELECT c.*
- FROM CharacterData c
+ FROM CardCharacter c
join UserCharacter uc on c.id = uc.charId
where uc.id = :charId
LIMIT 1
"""
)
- suspend fun getCharacterInfo(charId: Long): CharacterData
+ suspend fun getCharacterInfo(charId: Long): CardCharacter
@Query(
@@ -167,7 +171,7 @@ interface UserCharacterDao {
INSERT INTO TransformationHistory(monId, stageId, transformationDate)
VALUES
(:monId,
- (SELECT id FROM CharacterData WHERE charaIndex = :stage AND cardId = :dimId),
+ (SELECT id FROM CardCharacter WHERE charaIndex = :stage AND cardId = :dimId),
:transformationDate)
"""
)
@@ -193,9 +197,10 @@ interface UserCharacterDao {
c.nameWidth as nameSpriteWidth,
c.nameHeight as nameSpriteHeight,
d.isBEm as isBemCard,
- a.characterId = uc.id as isInAdventure
+ a.characterId = uc.id as isInAdventure,
+ uc.isActive as active
FROM UserCharacter uc
- JOIN CharacterData c ON uc.charId = c.id
+ JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON d.id = c.cardId
JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id
@@ -218,9 +223,10 @@ interface UserCharacterDao {
c.nameWidth as nameSpriteWidth,
c.nameHeight as nameSpriteHeight,
d.isBEm as isBemCard,
- a.characterId = uc.id as isInAdventure
+ a.characterId = uc.id as isInAdventure,
+ uc.isActive as active
FROM UserCharacter uc
- JOIN CharacterData c ON uc.charId = c.id
+ JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON d.id = c.cardId
JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt b/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt
index bec8d12..7aa784c 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt
@@ -3,17 +3,21 @@ package com.github.nacabaro.vbhelper.database
import androidx.room.Database
import androidx.room.RoomDatabase
import com.github.nacabaro.vbhelper.daos.AdventureDao
+import com.github.nacabaro.vbhelper.daos.CardAdventureDao
import com.github.nacabaro.vbhelper.daos.CharacterDao
import com.github.nacabaro.vbhelper.daos.DexDao
import com.github.nacabaro.vbhelper.daos.CardDao
+import com.github.nacabaro.vbhelper.daos.CardFusionsDao
import com.github.nacabaro.vbhelper.daos.CardProgressDao
import com.github.nacabaro.vbhelper.daos.ItemDao
import com.github.nacabaro.vbhelper.daos.SpecialMissionDao
import com.github.nacabaro.vbhelper.daos.SpriteDao
import com.github.nacabaro.vbhelper.daos.UserCharacterDao
import com.github.nacabaro.vbhelper.domain.card.Background
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.domain.card.Card
+import com.github.nacabaro.vbhelper.domain.card.CardAdventure
+import com.github.nacabaro.vbhelper.domain.card.CardFusions
import com.github.nacabaro.vbhelper.domain.card.CardProgress
import com.github.nacabaro.vbhelper.domain.card.PossibleTransformations
import com.github.nacabaro.vbhelper.domain.characters.Sprite
@@ -32,7 +36,9 @@ import com.github.nacabaro.vbhelper.domain.items.Items
entities = [
Card::class,
CardProgress::class,
- CharacterData::class,
+ CardCharacter::class,
+ CardAdventure::class,
+ CardFusions::class,
Sprite::class,
UserCharacter::class,
BECharacterData::class,
@@ -57,4 +63,6 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun adventureDao(): AdventureDao
abstract fun spriteDao(): SpriteDao
abstract fun specialMissionDao(): SpecialMissionDao
+ abstract fun cardAdventureDao(): CardAdventureDao
+ abstract fun cardFusionsDao(): CardFusionsDao
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt b/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt
index bc447f2..2d82b95 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/di/AppContainer.kt
@@ -1,9 +1,11 @@
package com.github.nacabaro.vbhelper.di
import com.github.nacabaro.vbhelper.database.AppDatabase
+import com.github.nacabaro.vbhelper.source.CurrencyRepository
import com.github.nacabaro.vbhelper.source.DataStoreSecretsRepository
interface AppContainer {
val db: AppDatabase
val dataStoreSecretsRepository: DataStoreSecretsRepository
+ val currencyRepository: CurrencyRepository
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt b/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt
index 4724bc6..70305b2 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/di/DefaultAppContainer.kt
@@ -1,20 +1,27 @@
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.dataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.preferencesDataStore
import androidx.room.Room
import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.di.AppContainer
+import com.github.nacabaro.vbhelper.source.CurrencyRepository
import com.github.nacabaro.vbhelper.source.DataStoreSecretsRepository
import com.github.nacabaro.vbhelper.source.SecretsSerializer
import com.github.nacabaro.vbhelper.source.proto.Secrets
private const val SECRETS_DATA_STORE_NAME = "secrets.pb"
-
+private const val USER_PREFERENCES_NAME = "user_preferences"
val Context.secretsStore: DataStore by dataStore(
fileName = SECRETS_DATA_STORE_NAME,
serializer = SecretsSerializer
)
+val Context.currencyStore: DataStore by preferencesDataStore(
+ name = USER_PREFERENCES_NAME
+)
+
class DefaultAppContainer(private val context: Context) : AppContainer {
override val db: AppDatabase by lazy {
@@ -29,5 +36,6 @@ class DefaultAppContainer(private val context: Context) : AppContainer {
override val dataStoreSecretsRepository = DataStoreSecretsRepository(context.secretsStore)
+ override val currencyRepository = CurrencyRepository(context.currencyStore)
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardAdventure.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardAdventure.kt
new file mode 100644
index 0000000..b8f4f56
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardAdventure.kt
@@ -0,0 +1,32 @@
+package com.github.nacabaro.vbhelper.domain.card
+
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.PrimaryKey
+
+@Entity(
+ foreignKeys = [
+ ForeignKey(
+ entity = CardCharacter::class,
+ parentColumns = ["id"],
+ childColumns = ["characterId"],
+ onDelete = ForeignKey.CASCADE
+ ),
+ ForeignKey(
+ entity = Card::class,
+ parentColumns = ["id"],
+ childColumns = ["cardId"],
+ onDelete = ForeignKey.CASCADE
+ )
+ ]
+)
+data class CardAdventure(
+ @PrimaryKey(autoGenerate = true) val id: Long = 0,
+ val cardId: Long,
+ val characterId: Long,
+ val steps: Int,
+ val bossHp: Int,
+ val bossAp: Int,
+ val bossDp: Int,
+ val bossBp: Int?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CharacterData.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardCharacter.kt
similarity index 97%
rename from app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CharacterData.kt
rename to app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardCharacter.kt
index 0c3f99d..050cc9a 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CharacterData.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardCharacter.kt
@@ -28,7 +28,7 @@ import com.github.nacabaro.vbhelper.domain.characters.Sprite
* and monIndex.
* TODO: Customs will mean this should be unique per cardName and monIndex
*/
-data class CharacterData (
+data class CardCharacter (
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val cardId: Long,
val spriteId: Long,
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardFusions.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardFusions.kt
new file mode 100644
index 0000000..1769eda
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardFusions.kt
@@ -0,0 +1,29 @@
+package com.github.nacabaro.vbhelper.domain.card
+
+import androidx.room.Entity
+import androidx.room.ForeignKey
+import androidx.room.PrimaryKey
+import com.github.cfogrady.vbnfc.data.NfcCharacter
+
+@Entity(
+ foreignKeys = [
+ ForeignKey(
+ entity = CardCharacter::class,
+ parentColumns = ["id"],
+ childColumns = ["fromCharaId"],
+ onDelete = ForeignKey.CASCADE
+ ),
+ ForeignKey(
+ entity = CardCharacter::class,
+ parentColumns = ["id"],
+ childColumns = ["toCharaId"],
+ onDelete = ForeignKey.CASCADE
+ )
+ ]
+)
+data class CardFusions(
+ @PrimaryKey(autoGenerate = true) val id: Long,
+ val fromCharaId: Long,
+ val attribute: NfcCharacter.Attribute,
+ val toCharaId: Long
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/PossibleTransformations.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/PossibleTransformations.kt
index 1aabaed..2dc2e8b 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/PossibleTransformations.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/card/PossibleTransformations.kt
@@ -7,13 +7,13 @@ import androidx.room.PrimaryKey
@Entity(
foreignKeys = [
ForeignKey(
- entity = CharacterData::class,
+ entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["charaId"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
- entity = CharacterData::class,
+ entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["toCharaId"],
onDelete = ForeignKey.CASCADE
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Dex.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Dex.kt
index a2f0430..14f0c09 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Dex.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Dex.kt
@@ -3,12 +3,12 @@ package com.github.nacabaro.vbhelper.domain.characters
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.domain.card.CardCharacter
@Entity(
foreignKeys = [
ForeignKey(
- entity = CharacterData::class,
+ entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["id"],
onDelete = ForeignKey.CASCADE
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/TransformationHistory.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/TransformationHistory.kt
index 10912e0..0a560cc 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/TransformationHistory.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/TransformationHistory.kt
@@ -3,7 +3,7 @@ package com.github.nacabaro.vbhelper.domain.device_data
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.domain.card.CardCharacter
@Entity(
foreignKeys = [
@@ -14,7 +14,7 @@ import com.github.nacabaro.vbhelper.domain.card.CharacterData
onDelete = ForeignKey.CASCADE
),
ForeignKey(
- entity = CharacterData::class,
+ entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["stageId"],
onDelete = ForeignKey.CASCADE
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/UserCharacter.kt b/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/UserCharacter.kt
index 66eedf2..e34b57d 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/UserCharacter.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/UserCharacter.kt
@@ -5,12 +5,12 @@ import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.utils.DeviceType
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.domain.card.CardCharacter
@Entity(
foreignKeys = [
ForeignKey(
- entity = CharacterData::class,
+ entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["charId"],
onDelete = ForeignKey.CASCADE
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CardDtos.kt b/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CardDtos.kt
index 48e7c74..252b553 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CardDtos.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CardDtos.kt
@@ -10,4 +10,18 @@ object CardDtos {
val totalCharacters: Int,
val obtainedCharacters: Int,
)
+
+ data class CardAdventureWithSprites (
+ val characterName: ByteArray,
+ val characterNameWidth: Int,
+ val characterNameHeight: Int,
+ val characterIdleSprite: ByteArray,
+ val characterIdleSpriteWidth: Int,
+ val characterIdleSpriteHeight: Int,
+ val characterAp: Int,
+ val characterBp: Int?,
+ val characterDp: Int,
+ val characterHp: Int,
+ val steps: Int,
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt b/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt
index 463d923..3cb7831 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt
@@ -31,14 +31,16 @@ object CharacterDtos {
val nameSpriteWidth: Int,
val nameSpriteHeight: Int,
val isBemCard: Boolean,
- val isInAdventure: Boolean
+ val isInAdventure: Boolean,
+ val active: Boolean
)
data class CardCharacterInfo(
- val cardId: Int,
+ val cardId: Long,
val charId: Int,
val stage: Int,
- val attribute: NfcCharacter.Attribute
+ val attribute: NfcCharacter.Attribute,
+ val currentStage: Int
)
data class TransformationHistory(
@@ -113,4 +115,14 @@ object CharacterDtos {
val changeTimerHours: 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
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt
index 76d9009..013b083 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/AppNavigation.kt
@@ -34,6 +34,7 @@ import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImp
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreen
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
+import com.github.nacabaro.vbhelper.screens.cardScreen.CardAdventureScreen
import com.github.nacabaro.vbhelper.screens.cardScreen.CardScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.settingsScreen.CreditsScreen
import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewerControllerImpl
@@ -145,7 +146,7 @@ fun AppNavigation(
if (cardId != null) {
CardViewScreen(
navController = navController,
- dimId = cardId.toLong()
+ cardId = cardId.toLong()
)
}
}
@@ -177,6 +178,17 @@ fun AppNavigation(
navController = navController
)
}
+ composable(NavigationItems.CardAdventure.route) {
+ val cardId = it.arguments?.getString("cardId")
+ if (cardId != null) {
+ CardAdventureScreen(
+ navController = navController,
+ cardId = cardId.toLong(),
+ cardScreenController = applicationNavigationHandlers
+ .cardScreenController
+ )
+ }
+ }
}
}
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt
index 623ae8a..ca187ea 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/navigation/NavigationItems.kt
@@ -11,6 +11,7 @@ sealed class NavigationItems (
object Battles : NavigationItems("Battle", R.drawable.baseline_swords_24, "Battle")
object Home : NavigationItems("Home", R.drawable.baseline_cottage_24, "Home")
object Dex : NavigationItems("Dex", R.drawable.baseline_menu_book_24, "Dex")
+ object CardAdventure : NavigationItems("CardAdventure/{cardId}", R.drawable.baseline_fort_24, "Card adventure")
object Storage : NavigationItems("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
object Settings : NavigationItems("Settings", R.drawable.baseline_settings_24, "Settings")
object Viewer : NavigationItems("Viewer", R.drawable.baseline_image_24, "Viewer")
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreen.kt
index 98f67cf..d7511ae 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreen.kt
@@ -9,12 +9,11 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
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.utils.BitmapData
import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
import java.time.Instant
@Composable
@@ -37,16 +35,17 @@ fun AdventureScreen(
navController: NavController,
storageScreenController: AdventureScreenControllerImpl
) {
- val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper
val database = application.container.db
val storageRepository = StorageRepository(database)
- val characterList = remember {
- mutableStateOf>(emptyList())
- }
+ val characterList by storageRepository.getAdventureCharacters().collectAsState(emptyList())
+
var obtainedItem by remember {
mutableStateOf(null)
}
+ var obtainedCurrency by remember {
+ mutableStateOf(0)
+ }
val currentTime by produceState(initialValue = Instant.now().epochSecond) {
while (true) {
@@ -59,13 +58,6 @@ fun AdventureScreen(
mutableStateOf(null)
}
- LaunchedEffect(storageRepository) {
- coroutineScope.launch {
- characterList.value = storageRepository
- .getAdventureCharacters()
- }
- }
-
Scaffold(
topBar = {
TopBanner(
@@ -76,7 +68,7 @@ fun AdventureScreen(
)
}
) { contentPadding ->
- if (characterList.value.isEmpty()) {
+ if (characterList.isEmpty()) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
@@ -91,7 +83,7 @@ fun AdventureScreen(
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
) {
- items(characterList.value) {
+ items(characterList) {
AdventureEntry(
icon = BitmapData(
bitmap = it.spriteIdle,
@@ -102,8 +94,9 @@ fun AdventureScreen(
onClick = {
if (it.finishesAdventure < currentTime) {
storageScreenController
- .getItemFromAdventure(it.id) { adventureResult ->
+ .getItemFromAdventure(it.id) { adventureResult, generatedCurrency ->
obtainedItem = adventureResult
+ obtainedCurrency = generatedCurrency
}
} else {
cancelAdventureDialog = it
@@ -118,6 +111,7 @@ fun AdventureScreen(
if (obtainedItem != null) {
ObtainedItemDialog(
obtainedItem = obtainedItem!!,
+ obtainedCurrency = obtainedCurrency,
onClickDismiss = {
obtainedItem = null
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenController.kt
index 11d70f6..ed29746 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenController.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenController.kt
@@ -4,6 +4,6 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
interface AdventureScreenController {
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)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt
index 535d1f4..1e9bb05 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/adventureScreen/AdventureScreenControllerImpl.kt
@@ -6,6 +6,7 @@ import androidx.lifecycle.lifecycleScope
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.ItemDtos
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlin.math.roundToInt
import kotlin.random.Random
@@ -37,19 +38,29 @@ class AdventureScreenControllerImpl(
override fun getItemFromAdventure(
characterId: Long,
- onResult: (ItemDtos.PurchasedItem) -> Unit
+ onResult: (ItemDtos.PurchasedItem, Int) -> Unit
) {
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
database
.adventureDao()
.deleteAdventure(characterId)
+ val generatedCurrency = generateRandomCurrency()
+
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) {
componentActivity.lifecycleScope.launch(Dispatchers.IO) {
database
@@ -77,6 +88,7 @@ class AdventureScreenControllerImpl(
val randomItem = database
.itemDao()
.getAllItems()
+ .first()
.random()
val random = ((Random.nextFloat() * character.stage) + 3).roundToInt()
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardAdventureEntry.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardAdventureEntry.kt
new file mode 100644
index 0000000..8927f26
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardAdventureEntry.kt
@@ -0,0 +1,122 @@
+package com.github.nacabaro.vbhelper.screens.cardScreen
+
+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.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 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 com.github.nacabaro.vbhelper.dtos.CardDtos
+import com.github.nacabaro.vbhelper.utils.BitmapData
+import com.github.nacabaro.vbhelper.utils.getImageBitmap
+
+@Composable
+fun CardAdventureEntry(
+ cardAdventureEntry: CardDtos.CardAdventureWithSprites,
+ obscure: Boolean
+) {
+ val charaImageBitmapData = BitmapData(
+ bitmap = cardAdventureEntry.characterIdleSprite,
+ width = cardAdventureEntry.characterIdleSpriteWidth,
+ height = cardAdventureEntry.characterIdleSpriteHeight
+ ).getImageBitmap(
+ context = LocalContext.current,
+ multiplier = 4,
+ obscure = obscure
+ )
+
+ val nameImageBitmapData = BitmapData(
+ bitmap = cardAdventureEntry.characterName,
+ width = cardAdventureEntry.characterNameWidth,
+ height = cardAdventureEntry.characterNameHeight
+ ).getImageBitmap(
+ context = LocalContext.current,
+ multiplier = 3,
+ obscure = obscure
+ )
+
+ Card (
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(8.dp)
+ ) {
+ Row (
+ modifier = Modifier
+ .padding(8.dp)
+ ){
+ 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(8.dp))
+
+ Column {
+ if (!obscure) {
+ Image(
+ bitmap = nameImageBitmapData.imageBitmap,
+ contentDescription = "Icon",
+ modifier = Modifier
+ .width(nameImageBitmapData.dpWidth)
+ .height(nameImageBitmapData.dpHeight),
+ filterQuality = FilterQuality.None
+ )
+
+ Spacer(modifier = Modifier.padding(4.dp))
+
+ Text(
+ text = "HP: ${cardAdventureEntry.characterHp}, DP: ${cardAdventureEntry.characterDp}, AP: ${cardAdventureEntry.characterAp}"
+ )
+ if (cardAdventureEntry.characterBp != null) {
+ Text(text = "BP: ${cardAdventureEntry.characterBp}")
+ }
+ Text(text = "Steps: ${cardAdventureEntry.steps}")
+ } else {
+ Text(text = "????????????????")
+ Text(
+ text = "HP: -, BP: -, AP: -"
+ )
+ if (cardAdventureEntry.characterBp != null) {
+ Text(text = "DP: -")
+ }
+ Text(text = "Steps: -")
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardAdventureScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardAdventureScreen.kt
new file mode 100644
index 0000000..6f5527a
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardAdventureScreen.kt
@@ -0,0 +1,51 @@
+package com.github.nacabaro.vbhelper.screens.cardScreen
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.navigation.NavController
+import com.github.nacabaro.vbhelper.components.TopBanner
+
+@Composable
+fun CardAdventureScreen(
+ navController: NavController,
+ cardScreenController: CardScreenControllerImpl,
+ cardId: Long
+) {
+ val cardAdventureMissions by cardScreenController
+ .getCardAdventureMissions(cardId)
+ .collectAsState(emptyList())
+ val currentCardAdventure by cardScreenController
+ .getCardProgress(cardId)
+ .collectAsState(0)
+
+ Scaffold (
+ topBar = {
+ TopBanner(
+ text = "Adventure missions",
+ onBackClick = {
+ navController.popBackStack()
+ }
+ )
+ }
+ ) { contentPadding ->
+ Column (
+ modifier = Modifier
+ .padding(top = contentPadding.calculateTopPadding())
+ .verticalScroll(state = rememberScrollState())
+ ) {
+ cardAdventureMissions.mapIndexed { index, it ->
+ CardAdventureEntry(
+ cardAdventureEntry = it,
+ obscure = index > currentCardAdventure - 1
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenController.kt
index d47d888..836746f 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenController.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenController.kt
@@ -1,6 +1,13 @@
package com.github.nacabaro.vbhelper.screens.cardScreen
+import com.github.nacabaro.vbhelper.dtos.CardDtos
+import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
+
interface CardScreenController {
fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit)
fun deleteCard(cardId: Long, onDeleted: () -> Unit)
+ fun getCardAdventureMissions(cardId: Long): Flow>
+ fun getCardProgress(cardId: Long): Flow
+ fun getFusionsForCharacters(characterId: Long): Flow>
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenControllerImpl.kt
index 0e54d15..ded0375 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenControllerImpl.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardScreenControllerImpl.kt
@@ -3,6 +3,9 @@ package com.github.nacabaro.vbhelper.screens.cardScreen
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.github.nacabaro.vbhelper.di.VBHelper
+import com.github.nacabaro.vbhelper.dtos.CardDtos
+import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
class CardScreenControllerImpl(
@@ -11,7 +14,6 @@ class CardScreenControllerImpl(
private val application = componentActivity.applicationContext as VBHelper
private val database = application.container.db
-
override fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit) {
componentActivity.lifecycleScope.launch {
database
@@ -31,4 +33,23 @@ class CardScreenControllerImpl(
onDeleted()
}
}
+
+ override fun getCardAdventureMissions(cardId: Long): Flow> {
+ return database
+ .cardAdventureDao()
+ .getAdventureForCard(cardId)
+ }
+
+ override fun getCardProgress(cardId: Long): Flow {
+ return database
+ .cardProgressDao()
+ .getCardProgress(cardId)
+ }
+
+ override fun getFusionsForCharacters(characterId: Long): Flow> {
+ return database
+ .cardFusionsDao()
+ .getFusionsForCharacter(characterId)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardViewScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardViewScreen.kt
index 330293b..da95460 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardViewScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardViewScreen.kt
@@ -5,10 +5,10 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.utils.BitmapData
@@ -16,40 +16,39 @@ import com.github.nacabaro.vbhelper.components.CharacterEntry
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.DexCharaDetailsDialog
import com.github.nacabaro.vbhelper.source.DexRepository
-import kotlinx.coroutines.launch
@Composable
fun CardViewScreen(
navController: NavController,
- dimId: Long
+ cardId: Long
) {
- val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper
val dexRepository = DexRepository(application.container.db)
- val characterList = remember { mutableStateOf>(emptyList()) }
- val cardPossibleTransformations = remember { mutableStateOf>(emptyList()) }
+ val characterList by dexRepository.getCharactersByCardId(cardId).collectAsState(emptyList())
val selectedCharacter = remember { mutableStateOf(null) }
- LaunchedEffect(dexRepository) {
- coroutineScope.launch {
- val newCharacterList = dexRepository.getCharactersByCardId(dimId)
- characterList.value = newCharacterList
-
- val newCardPossibleTransformations = dexRepository.getCardPossibleTransformations(dimId)
- cardPossibleTransformations.value = newCardPossibleTransformations
- }
- }
-
Scaffold (
topBar = {
TopBanner(
text = "Discovered characters",
onBackClick = {
navController.popBackStack()
+ },
+ onAdventureClick = {
+ navController
+ .navigate(route = NavigationItems
+ .CardAdventure
+ .route
+ .replace(
+ "{cardId}",
+ cardId.toString()
+ )
+ )
}
)
}
@@ -58,7 +57,7 @@ fun CardViewScreen(
columns = GridCells.Fixed(3),
contentPadding = contentPadding
) {
- items(characterList.value) { character ->
+ items(characterList) { character ->
CharacterEntry(
onClick = {
selectedCharacter.value = character
@@ -76,7 +75,6 @@ fun CardViewScreen(
if (selectedCharacter.value != null) {
DexCharaDetailsDialog(
currentChara = selectedCharacter.value!!,
- possibleTransformations = cardPossibleTransformations.value,
obscure = selectedCharacter.value!!.discoveredOn == null,
onClickClose = {
selectedCharacter.value = null
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardsScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardsScreen.kt
index e639444..fcb24b5 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardsScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/CardsScreen.kt
@@ -7,11 +7,10 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
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.CardRenameDialog
import com.github.nacabaro.vbhelper.source.DexRepository
-import kotlinx.coroutines.launch
@Composable
fun CardsScreen(
navController: NavController,
cardScreenController: CardScreenControllerImpl
) {
- val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper
val dexRepository = DexRepository(application.container.db)
- val cardList = remember { mutableStateOf>(emptyList()) }
+ val cardList by dexRepository.getAllDims().collectAsState(emptyList())
val selectedCard = remember { mutableStateOf(null) }
var clickedDelete by remember { mutableStateOf(false) }
@@ -43,13 +40,6 @@ fun CardsScreen(
var modifyCards by remember { mutableStateOf(false) }
- LaunchedEffect(dexRepository) {
- coroutineScope.launch {
- val newDimList = dexRepository.getAllDims()
- cardList.value = newDimList
- }
- }
-
Scaffold (
topBar = {
TopBanner(
@@ -64,7 +54,7 @@ fun CardsScreen(
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
) {
- items(cardList.value) {
+ items(cardList) {
CardEntry(
name = it.cardName,
logo = BitmapData(
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaDetailsDialog.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaDetailsDialog.kt
index 92beb74..364982e 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaDetailsDialog.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaDetailsDialog.kt
@@ -16,6 +16,11 @@ import androidx.compose.material3.MaterialTheme
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.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
@@ -23,7 +28,9 @@ 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.di.VBHelper
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.getImageBitmap
@@ -31,14 +38,25 @@ import com.github.nacabaro.vbhelper.utils.getImageBitmap
@Composable
fun DexCharaDetailsDialog(
currentChara: CharacterDtos.CardCharaProgress,
- possibleTransformations: List,
obscure: Boolean,
onClickClose: () -> Unit
) {
val nameMultiplier = 3
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) {
1 -> "II"
@@ -204,12 +222,40 @@ fun DexCharaDetailsDialog(
}
}
- Button(
- onClick = onClickClose
- ) {
- Text("Close")
+ Row {
+ if (currentCharaPossibleFusions.isNotEmpty()) {
+ Button(
+ 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
+ )
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaFusionsDialog.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaFusionsDialog.kt
new file mode 100644
index 0000000..be2296d
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/cardScreen/dialogs/DexCharaFusionsDialog.kt
@@ -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,
+ 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")
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreen.kt
index 4a5d3a0..7cd4515 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreen.kt
@@ -1,6 +1,5 @@
package com.github.nacabaro.vbhelper.screens.homeScreens
-import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@@ -56,6 +55,7 @@ fun HomeScreen(
var adventureMissionsFinished by rememberSaveable { mutableStateOf(false) }
var betaWarning by rememberSaveable { mutableStateOf(true) }
var collectedItem by remember { mutableStateOf(null) }
+ var collectedCurrency by remember { mutableStateOf(null) }
LaunchedEffect(storageRepository, activeMon, collectedItem) {
withContext(Dispatchers.IO) {
@@ -92,7 +92,6 @@ fun HomeScreen(
}
) { contentPadding ->
if (activeMon.value == null || (beData.value == null && vbData.value == null) || transformationHistory.value == null) {
- Log.d("TetTet", "Something is null")
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
@@ -103,7 +102,6 @@ fun HomeScreen(
Text(text = "Nothing to see here")
}
} else {
- Log.d("TetTet", "Something is not null")
if (activeMon.value!!.isBemCard) {
BEBEmHomeScreen(
activeMon = activeMon.value!!,
@@ -126,8 +124,9 @@ fun HomeScreen(
contentPadding = contentPadding,
specialMissions = vbSpecialMissions.value,
homeScreenController = homeScreenController,
- onClickCollect = { item ->
+ onClickCollect = { item, currency ->
collectedItem = item
+ collectedCurrency = currency
}
)
}
@@ -137,8 +136,10 @@ fun HomeScreen(
if (collectedItem != null) {
ObtainedItemDialog(
obtainedItem = collectedItem!!,
+ obtainedCurrency = collectedCurrency!!,
onClickDismiss = {
collectedItem = null
+ collectedCurrency = null
}
)
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenController.kt
index b24f8b2..1c0093b 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenController.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenController.kt
@@ -5,5 +5,5 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
interface HomeScreenController {
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)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt
index 5169263..e8824e8 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/HomeScreenControllerImpl.kt
@@ -5,6 +5,7 @@ import androidx.lifecycle.lifecycleScope
import com.github.cfogrady.vbnfc.vb.SpecialMission
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.ItemDtos
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.time.Instant
import kotlin.math.roundToInt
@@ -22,6 +23,7 @@ class HomeScreenControllerImpl(
val adventureCharacters = database
.adventureDao()
.getAdventureCharacters()
+ .first()
val finishedAdventureCharacters = adventureCharacters.filter { character ->
character.finishesAdventure <= currentTime
@@ -31,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 {
database
.specialMissionDao()
@@ -41,6 +43,7 @@ class HomeScreenControllerImpl(
val randomItem = database
.itemDao()
.getAllItems()
+ .first()
.random()
val randomItemAmount = (Random.nextFloat() * 5).roundToInt()
@@ -62,9 +65,13 @@ class HomeScreenControllerImpl(
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 {
- onCleared(null)
+ onCleared(null, null)
}
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/VBDiMHomeScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/VBDiMHomeScreen.kt
index 74dd98d..eeb9062 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/VBDiMHomeScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/homeScreens/screens/VBDiMHomeScreen.kt
@@ -34,7 +34,7 @@ fun VBDiMHomeScreen(
homeScreenController: HomeScreenControllerImpl,
transformationHistory: List,
contentPadding: PaddingValues,
- onClickCollect: (ItemDtos.PurchasedItem?) -> Unit
+ onClickCollect: (ItemDtos.PurchasedItem?, Int?) -> Unit
) {
Column(
modifier = Modifier
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt
index 26be571..5b2b884 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ChooseCharacterScreen.kt
@@ -24,6 +24,7 @@ import com.github.nacabaro.vbhelper.dtos.CharacterDtos
import com.github.nacabaro.vbhelper.dtos.ItemDtos
import com.github.nacabaro.vbhelper.source.StorageRepository
import com.github.nacabaro.vbhelper.utils.BitmapData
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
@@ -35,7 +36,7 @@ fun ChooseCharacterScreen(
) {
val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper
- val storageRepository = StorageRepository(application.container.db)
+ val storageRepository = StorageRepository(application.container.db, )
val characterList = remember {
mutableStateOf>(emptyList())
}
@@ -57,7 +58,7 @@ fun ChooseCharacterScreen(
characterList.value = storageRepository.getVBCharacters()
}
else -> {
- characterList.value = storageRepository.getAllCharacters()
+ characterList.value = storageRepository.getAllCharacters().first()
}
}
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt
new file mode 100644
index 0000000..3bd3e2d
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemDialog.kt
@@ -0,0 +1,164 @@
+package com.github.nacabaro.vbhelper.screens.itemsScreen
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+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.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Button
+import androidx.compose.material3.Card
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.Dialog
+import androidx.compose.ui.window.DialogProperties
+import com.github.nacabaro.vbhelper.R
+import com.github.nacabaro.vbhelper.domain.items.ItemType
+import com.github.nacabaro.vbhelper.dtos.ItemDtos
+import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
+
+@Composable
+fun ItemDialog(
+ item: ItemDtos.ItemsWithQuantities,
+ onClickCancel: () -> Unit,
+ onClickUse: (() -> Unit)? = null,
+ onClickPurchase: (() -> Unit)? = null,
+) {
+ Dialog(
+ onDismissRequest = onClickCancel,
+ properties = DialogProperties(
+ dismissOnBackPress = true,
+ dismissOnClickOutside = true
+ )
+ ) {
+ Card (
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ ) {
+ Column (
+ modifier = Modifier
+ .padding(16.dp)
+ ) {
+ Row {
+ Box(modifier = Modifier) {
+ // Background image (full size)
+ Icon(
+ painter = painterResource(id = getIconResource(item.itemIcon)),
+ contentDescription = null,
+ modifier = Modifier
+ .size(96.dp)
+ .align(Alignment.Center)
+ )
+ Icon(
+ painter = painterResource(id = getLengthResource(item.itemLength)),
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.outline,
+ modifier = Modifier
+ .size(64.dp) // Set the size of the overlay image
+ .align(Alignment.BottomEnd) // Align to the top end (top-right corner)
+ )
+ }
+ Column (
+ modifier = Modifier
+ .padding(16.dp)
+ ) {
+ Text(
+ fontSize = MaterialTheme.typography.titleLarge.fontSize,
+ text = item.name,
+ modifier = Modifier
+ .fillMaxWidth()
+ )
+ }
+ }
+ Text(
+ textAlign = TextAlign.Center,
+ fontSize = MaterialTheme.typography.bodyMedium.fontSize,
+ fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
+ text = item.description,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(4.dp)
+ )
+ if (onClickPurchase != null) {
+ Text(
+ textAlign = TextAlign.Center,
+ fontSize = MaterialTheme.typography.bodySmall.fontSize,
+ fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
+ text = "Costs ${item.price} credits",
+ modifier = Modifier
+ .fillMaxWidth()
+ )
+ }
+ Text(
+ textAlign = TextAlign.Center,
+ fontSize = MaterialTheme.typography.bodySmall.fontSize,
+ fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
+ text = "You have ${item.quantity} of this item",
+ modifier = Modifier
+ .fillMaxWidth()
+ )
+
+ Row (
+ horizontalArrangement = Arrangement.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ ) {
+ if (onClickUse != null) {
+ Button(
+ onClick = onClickUse
+ ) {
+ Text("Use item")
+ }
+ }
+
+ if (onClickPurchase != null) {
+ Button(
+ onClick = onClickPurchase
+ ) {
+ Text("Purchase")
+ }
+ }
+
+ Spacer(modifier = Modifier.size(8.dp))
+ Button(
+ onClick = onClickCancel
+ ) {
+ Text("Cancel")
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+@Preview(showBackground = true)
+fun PreviewItemDialog() {
+ VBHelperTheme {
+ ItemDialog(
+ item = ItemDtos.ItemsWithQuantities(
+ name = "AP Training x3 (60 min)",
+ description = "Boosts AP during training (for 60 minutes)",
+ itemIcon = R.drawable.baseline_attack_24,
+ itemLength = R.drawable.baseline_60_min_timer,
+ quantity = 19,
+ id = 1,
+ price = 500,
+ itemType = ItemType.BEITEM
+ ),
+ onClickUse = { },
+ onClickCancel = { }
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt
index 7822bc0..cd4645c 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemElement.kt
@@ -1,36 +1,23 @@
package com.github.nacabaro.vbhelper.screens.itemsScreen
-import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
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.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Dialog
-import androidx.compose.ui.window.DialogProperties
-import com.github.nacabaro.vbhelper.R
-import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
+import com.github.nacabaro.vbhelper.dtos.ItemDtos
@Composable
fun ItemElement(
- itemIcon: Int,
- lengthIcon: Int,
+ item: ItemDtos.ItemsWithQuantities,
modifier: Modifier = Modifier,
onClick: (() -> Unit) = { }
) {
@@ -41,7 +28,7 @@ fun ItemElement(
) {
Box(modifier = Modifier.fillMaxSize()) {
Icon(
- painter = painterResource(id = itemIcon),
+ painter = painterResource(id = getIconResource(item.itemIcon)),
contentDescription = null,
modifier = Modifier
.size(96.dp)
@@ -49,164 +36,14 @@ fun ItemElement(
.padding(16.dp)
)
Icon(
- painter = painterResource(id = lengthIcon),
+ painter = painterResource(id = getLengthResource(item.itemLength)),
contentDescription = null,
tint = MaterialTheme.colorScheme.surfaceTint,
modifier = Modifier
- .size(48.dp) // Set the size of the overlay image
- .align(Alignment.TopStart) // Align to the top end (top-right corner)
+ .size(48.dp)
+ .align(Alignment.TopStart)
.padding(8.dp)
)
}
}
}
-
-@Composable
-fun ItemDialog(
- name: String,
- description: String,
- itemIcon: Int,
- lengthIcon: Int,
- amount: Int,
- onClickUse: () -> Unit,
- onClickCancel: () -> Unit
-) {
- Dialog(
- onDismissRequest = onClickCancel,
- properties = DialogProperties(
- dismissOnBackPress = true,
- dismissOnClickOutside = true
- )
- ) {
- Card (
- modifier = Modifier
- .fillMaxWidth()
- .padding(16.dp)
- ) {
- Column (
- modifier = Modifier
- .padding(16.dp)
- ) {
- Row {
- Box(modifier = Modifier) {
- // Background image (full size)
- Icon(
- painter = painterResource(id = itemIcon),
- contentDescription = null,
- modifier = Modifier
- .size(96.dp)
- .align(Alignment.Center)
- )
- Icon(
- painter = painterResource(id = lengthIcon),
- contentDescription = null,
- tint = MaterialTheme.colorScheme.outline,
- modifier = Modifier
- .size(64.dp) // Set the size of the overlay image
- .align(Alignment.BottomEnd) // Align to the top end (top-right corner)
- )
- }
- Column (
- modifier = Modifier
- .padding(16.dp)
- ) {
- Text(
- fontSize = MaterialTheme.typography.titleLarge.fontSize,
- text = name,
- modifier = Modifier
- .fillMaxWidth()
- )
- }
- }
- Text(
- textAlign = TextAlign.Center,
- fontSize = MaterialTheme.typography.bodyMedium.fontSize,
- fontFamily = MaterialTheme.typography.bodyMedium.fontFamily,
- text = description,
- modifier = Modifier
- .fillMaxWidth()
- .padding(4.dp)
- )
- Text(
- textAlign = TextAlign.Center,
- fontSize = MaterialTheme.typography.bodySmall.fontSize,
- fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
- text = "You have $amount of this item",
- modifier = Modifier
- .fillMaxWidth()
- .padding(8.dp)
- )
- Row (
- horizontalArrangement = Arrangement.Center,
- modifier = Modifier
- .fillMaxWidth()
- ) {
- Button(
- onClick = onClickUse
- ) {
- Text("Use item")
- }
- Spacer(modifier = Modifier.size(8.dp))
- Button(
- onClick = onClickCancel
- ) {
- Text("Cancel")
- }
- }
- }
- }
- }
-}
-
-fun getIconResource(index: Int): Int {
- return when (index) {
- ItemsScreenControllerImpl.ItemTypes.PPTraining.id -> R.drawable.baseline_agility_24
- ItemsScreenControllerImpl.ItemTypes.APTraining.id -> R.drawable.baseline_attack_24
- ItemsScreenControllerImpl.ItemTypes.HPTraining.id -> R.drawable.baseline_shield_24
- ItemsScreenControllerImpl.ItemTypes.BPTraining.id -> R.drawable.baseline_trophy_24
- ItemsScreenControllerImpl.ItemTypes.AllTraining.id -> R.drawable.baseline_arrow_up_24
- 6 -> R.drawable.baseline_timer_24
- 7 -> R.drawable.baseline_rank_24
- 8 -> R.drawable.baseline_vitals_24
- else -> R.drawable.baseline_question_mark_24
- }
-}
-
-fun getLengthResource(index: Int): Int {
- return when (index) {
- 15 -> R.drawable.baseline_15_min_timer
- 30 -> R.drawable.baseline_30_min_timer
- 60 -> R.drawable.baseline_60_min_timer
- -60 -> R.drawable.baseline_60_min_timer
- 300 -> R.drawable.baseline_5_hour_timer
- 600 -> R.drawable.baseline_10_hour_timer
- -720 -> R.drawable.baseline_12_hour_timer
- -1440 -> R.drawable.baseline_24_hour_timer
- 6000 -> R.drawable.baseline_reset_24
- 1000 -> R.drawable.baseline_single_arrow_up
- 2500 -> R.drawable.baseline_double_arrow_up
- 5000 -> R.drawable.baseline_triple_arrow_up
- 9999 -> R.drawable.baseline_health_24
- -500 -> R.drawable.baseline_single_arrow_down
- -1000 -> R.drawable.baseline_double_arrow_down
- -2500 -> R.drawable.baseline_triple_arrow_down
- -9999 -> R.drawable.baseline_reset_24
- else -> R.drawable.baseline_question_mark_24
- }
-}
-
-@Composable
-@Preview(showBackground = true)
-fun PreviewItemDialog() {
- VBHelperTheme {
- ItemDialog(
- name = "AP Training x3 (60 min)",
- description = "Boosts AP during training (for 60 minutes)",
- itemIcon = R.drawable.baseline_attack_24,
- lengthIcon = R.drawable.baseline_60_min_timer,
- onClickUse = { },
- onClickCancel = { },
- amount = 19
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt
new file mode 100644
index 0000000..b0d9e8a
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemIcons.kt
@@ -0,0 +1,40 @@
+package com.github.nacabaro.vbhelper.screens.itemsScreen
+
+import com.github.nacabaro.vbhelper.R
+
+fun getIconResource(index: Int): Int {
+ return when (index) {
+ ItemsScreenControllerImpl.ItemTypes.PPTraining.id -> R.drawable.baseline_agility_24
+ ItemsScreenControllerImpl.ItemTypes.APTraining.id -> R.drawable.baseline_attack_24
+ ItemsScreenControllerImpl.ItemTypes.HPTraining.id -> R.drawable.baseline_shield_24
+ ItemsScreenControllerImpl.ItemTypes.BPTraining.id -> R.drawable.baseline_trophy_24
+ ItemsScreenControllerImpl.ItemTypes.AllTraining.id -> R.drawable.baseline_arrow_up_24
+ 6 -> R.drawable.baseline_timer_24
+ 7 -> R.drawable.baseline_rank_24
+ 8 -> R.drawable.baseline_vitals_24
+ else -> R.drawable.baseline_question_mark_24
+ }
+}
+
+fun getLengthResource(index: Int): Int {
+ return when (index) {
+ 15 -> R.drawable.baseline_15_min_timer
+ 30 -> R.drawable.baseline_30_min_timer
+ 60 -> R.drawable.baseline_60_min_timer
+ -60 -> R.drawable.baseline_60_min_timer
+ 300 -> R.drawable.baseline_5_hour_timer
+ 600 -> R.drawable.baseline_10_hour_timer
+ -720 -> R.drawable.baseline_12_hour_timer
+ -1440 -> R.drawable.baseline_24_hour_timer
+ 6000 -> R.drawable.baseline_reset_24
+ 1000 -> R.drawable.baseline_single_arrow_up
+ 2500 -> R.drawable.baseline_double_arrow_up
+ 5000 -> R.drawable.baseline_triple_arrow_up
+ 9999 -> R.drawable.baseline_health_24
+ -500 -> R.drawable.baseline_single_arrow_down
+ -1000 -> R.drawable.baseline_double_arrow_down
+ -2500 -> R.drawable.baseline_triple_arrow_down
+ -9999 -> R.drawable.baseline_reset_24
+ else -> R.drawable.baseline_question_mark_24
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt
index 032303b..4d4533c 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ItemsStore.kt
@@ -1,25 +1,35 @@
package com.github.nacabaro.vbhelper.screens.itemsScreen
+import android.widget.Toast
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
+import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.ItemDtos
+import com.github.nacabaro.vbhelper.source.CurrencyRepository
import com.github.nacabaro.vbhelper.source.ItemsRepository
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
@Composable
fun ItemsStore(
@@ -27,45 +37,98 @@ fun ItemsStore(
) {
val application = LocalContext.current.applicationContext as VBHelper
val itemsRepository = ItemsRepository(application.container.db)
- val myItems = remember { mutableStateOf(emptyList()) }
+ val myItems by itemsRepository.getAllItems().collectAsState(emptyList())
+
var selectedElementIndex by remember { mutableStateOf(null) }
- LaunchedEffect(itemsRepository) {
- withContext(Dispatchers.IO) {
- myItems.value = itemsRepository.getAllItems()
- }
- }
+ val currencyRepository = application.container.currencyRepository
+ val currentCurrency = currencyRepository.currencyValue.collectAsState(0)
- if (myItems.value.isEmpty()) {
- Text("No items")
- } else {
- LazyVerticalGrid(
- columns = GridCells.Fixed(3),
- modifier = Modifier
+ val scope = rememberCoroutineScope()
+
+ if (myItems.isEmpty()) {
+ Column(
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.fillMaxSize()
) {
- items(myItems.value) { index ->
- ItemElement(
- itemIcon = getIconResource(index.itemIcon),
- lengthIcon = getLengthResource(index.itemLength),
+ Text("No items")
+ }
+ } else {
+ Column() {
+ Card(
+ modifier = Modifier
+ .padding(8.dp)
+ .fillMaxWidth()
+ ) {
+ Text(
+ text = "${currentCurrency.value} credits",
modifier = Modifier
- .padding(8.dp),
- onClick = {
- selectedElementIndex = myItems.value.indexOf(index)
- }
+ .padding(8.dp)
)
}
- }
- if (selectedElementIndex != null) {
- ItemDialog(
- name = myItems.value[selectedElementIndex!!].name,
- description = myItems.value[selectedElementIndex!!].description,
- itemIcon = getIconResource(myItems.value[selectedElementIndex!!].itemIcon),
- lengthIcon = getLengthResource(myItems.value[selectedElementIndex!!].itemLength),
- amount = myItems.value[selectedElementIndex!!].quantity,
- onClickUse = { },
- onClickCancel = { selectedElementIndex = null }
- )
+ LazyVerticalGrid(
+ columns = GridCells.Fixed(3),
+ modifier = Modifier
+ ) {
+ items(myItems) { index ->
+ ItemElement(
+ item = index,
+ modifier = Modifier
+ .padding(8.dp),
+ onClick = {
+ selectedElementIndex = myItems.indexOf(index)
+ }
+ )
+ }
+ }
}
}
+
+
+ if (selectedElementIndex != null) {
+ ItemDialog(
+ item = myItems[selectedElementIndex!!],
+ onClickPurchase = {
+ scope.launch {
+ Toast.makeText(
+ application.applicationContext,
+ purchaseItem(
+ application.container.db,
+ myItems[selectedElementIndex!!],
+ currencyRepository
+ ),
+ Toast.LENGTH_SHORT
+ ).show(
+ )
+ }
+ },
+ onClickCancel = { selectedElementIndex = null }
+ )
+ }
+}
+
+suspend fun purchaseItem(
+ db: AppDatabase,
+ item: ItemDtos.ItemsWithQuantities,
+ currencyRepository: CurrencyRepository
+): String {
+ if (currencyRepository.currencyValue.first() < item.price) {
+ return "Not enough credits"
+ } else {
+ db
+ .itemDao()
+ .purchaseItem(
+ item.id,
+ 1
+ )
+
+ currencyRepository
+ .setCurrencyValue(
+ currencyRepository.currencyValue.first() - item.price
+ )
+
+ return "Purchase successful!"
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt
index 55b835f..39479a8 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/MyItems.kt
@@ -9,7 +9,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -20,11 +20,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.di.VBHelper
-import com.github.nacabaro.vbhelper.dtos.ItemDtos
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.source.ItemsRepository
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
@Composable
fun MyItems(
@@ -32,16 +29,11 @@ fun MyItems(
) {
val application = LocalContext.current.applicationContext as VBHelper
val itemsRepository = ItemsRepository(application.container.db)
- val myItems = remember { mutableStateOf(emptyList()) }
+ val myItems by itemsRepository.getUserItems().collectAsState(emptyList())
+
var selectedElementIndex by remember { mutableStateOf(null) }
- LaunchedEffect(itemsRepository) {
- withContext(Dispatchers.IO) {
- myItems.value = itemsRepository.getUserItems()
- }
- }
-
- if (myItems.value.isEmpty()) {
+ if (myItems.isEmpty()) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
@@ -54,14 +46,13 @@ fun MyItems(
columns = GridCells.Fixed(3),
modifier = Modifier
) {
- items(myItems.value) { index ->
+ items(myItems) { index ->
ItemElement(
- itemIcon = getIconResource(index.itemIcon),
- lengthIcon = getLengthResource(index.itemLength),
+ item = index,
modifier = Modifier
.padding(8.dp),
onClick = {
- selectedElementIndex = myItems.value.indexOf(index)
+ selectedElementIndex = myItems.indexOf(index)
}
)
}
@@ -69,11 +60,7 @@ fun MyItems(
if (selectedElementIndex != null) {
ItemDialog(
- name = myItems.value[selectedElementIndex!!].name,
- description = myItems.value[selectedElementIndex!!].description,
- itemIcon = getIconResource(myItems.value[selectedElementIndex!!].itemIcon),
- lengthIcon = getLengthResource(myItems.value[selectedElementIndex!!].itemLength),
- amount = myItems.value[selectedElementIndex!!].quantity,
+ item = myItems[selectedElementIndex!!],
onClickUse = {
navController
.navigate(
@@ -81,7 +68,7 @@ fun MyItems(
.ApplyItem.route
.replace(
"{itemId}",
- myItems.value[selectedElementIndex!!].id.toString()
+ myItems[selectedElementIndex!!].id.toString()
)
)
selectedElementIndex = null
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ObtainedItemDialog.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ObtainedItemDialog.kt
index c740018..9fbe416 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ObtainedItemDialog.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/itemsScreen/ObtainedItemDialog.kt
@@ -23,6 +23,7 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
@Composable
fun ObtainedItemDialog(
obtainedItem: ItemDtos.PurchasedItem,
+ obtainedCurrency: Int,
onClickDismiss: () -> Unit
) {
Dialog(
@@ -84,7 +85,16 @@ fun ObtainedItemDialog(
text = "You have obtained ${obtainedItem.itemAmount} of this item",
modifier = Modifier
.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(
onClick = onClickDismiss,
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ChooseConnectionScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ChooseConnectionScreen.kt
new file mode 100644
index 0000000..34180ba
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ChooseConnectionScreen.kt
@@ -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)
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt
index a58b2b2..8dec3b6 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt
@@ -1,38 +1,24 @@
package com.github.nacabaro.vbhelper.screens.scanScreen
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.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.Alignment
-import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
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.compose.rememberNavController
import com.github.cfogrady.vbnfc.data.NfcCharacter
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.domain.card.Card
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.isMissingSecrets
import com.github.nacabaro.vbhelper.source.proto.Secrets
@@ -55,8 +41,6 @@ fun ScanScreen(
val storageRepository = StorageRepository(application.container.db)
var nfcCharacter by remember { mutableStateOf(null) }
- var cardsRead by remember { mutableStateOf?>(null) }
-
val context = LocalContext.current
LaunchedEffect(storageRepository) {
@@ -73,143 +57,33 @@ fun ScanScreen(
}
}
- var readingScreen by remember { mutableStateOf(false) }
var writingScreen by remember { mutableStateOf(false) }
- var cardSelectScreen by remember { mutableStateOf(false) }
- var isDoneReadingCharacter by remember { mutableStateOf(false) }
- var isDoneSendingCard by remember { mutableStateOf(false) }
- var isDoneWritingCharacter by remember { mutableStateOf(false) }
+ var readingScreen 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()
- }
- }
- }
-
- 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") {
+ if (writingScreen && nfcCharacter != null && characterId != null) {
+ WritingScreen(
+ scanScreenController = scanScreenController,
+ nfcCharacter = nfcCharacter!!,
+ characterId = characterId,
+ onComplete = {
writingScreen = false
- scanScreenController.cancelRead()
- }
- } else if (!isDoneWritingCharacter) {
- ReadingCharacterScreen("Writing character") {
- isDoneSendingCard = false
+ navController.navigate(NavigationItems.Home.route)
+ },
+ onCancel = {
writingScreen = false
- scanScreenController.cancelRead()
+ navController.navigate(NavigationItems.Home.route)
}
- }
- } else if (cardSelectScreen) {
- ChooseCard(
- cards = cardsRead!!,
- onCardSelected = { card ->
- cardSelectScreen = false
- scanScreenController.flushCharacter(card.id)
+ )
+ } else if (readingScreen) {
+ ReadingScreen(
+ scanScreenController = scanScreenController,
+ onCancel = {
+ readingScreen = false
+ navController.navigate(NavigationItems.Home.route)
+ },
+ onComplete = {
+ readingScreen = false
+ navController.navigate(NavigationItems.Home.route)
}
)
} 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)
@Composable
fun ScanScreenPreview() {
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt
index a398aae..dcc85a3 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt
@@ -1,13 +1,11 @@
package com.github.nacabaro.vbhelper.screens.scanScreen.converters
-import android.util.Log
import androidx.activity.ComponentActivity
import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.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.SpecialMissions
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
@@ -152,15 +150,13 @@ class FromNfcConverter (
nfcCharacter: NfcCharacter,
cardData: Card
) {
- val currentCardProgress = CardProgress(
- cardId = cardData.id,
- currentStage = nfcCharacter.nextAdventureMissionStage.toInt(),
- unlocked = nfcCharacter.nextAdventureMissionStage.toInt() > cardData.stageCount
- )
-
database
.cardProgressDao()
- .updateDimProgress(currentCardProgress)
+ .updateCardProgress(
+ currentStage = nfcCharacter.nextAdventureMissionStage.toInt(),
+ cardId = cardData.id,
+ unlocked = nfcCharacter.nextAdventureMissionStage.toInt() > cardData.stageCount,
+ )
}
@@ -252,10 +248,11 @@ class FromNfcConverter (
) {
val vitalsHistoryWatch = nfcCharacter.vitalHistory
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(
charId = characterId,
- year = historyElement.year.toInt(),
+ year = year,
month = historyElement.month.toInt(),
day = historyElement.day.toInt(),
vitalPoints = historyElement.vitalsGained.toInt()
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt
index 624f87a..2078238 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt
@@ -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.dtos.CharacterDtos
import com.github.nacabaro.vbhelper.utils.DeviceType
+import kotlinx.coroutines.flow.first
import java.util.Date
class ToNfcConverter(
@@ -38,14 +39,10 @@ class ToNfcConverter(
.characterDao()
.getCharacterInfo(userCharacter.charId)
- val currentCardStage = database
- .cardProgressDao()
- .getCardProgress(characterInfo.cardId)
-
return if (userCharacter.characterType == DeviceType.BEDevice)
- nfcToBENfc(characterId, characterInfo, currentCardStage, userCharacter)
+ nfcToBENfc(characterId, characterInfo, userCharacter)
else
- nfcToVBNfc(characterId, characterInfo, currentCardStage, userCharacter)
+ nfcToVBNfc(characterId, characterInfo, userCharacter)
}
@@ -53,7 +50,6 @@ class ToNfcConverter(
private suspend fun nfcToVBNfc(
characterId: Long,
characterInfo: CharacterDtos.CardCharacterInfo,
- currentCardStage: Int,
userCharacter: UserCharacter
): VBNfcCharacter {
val vbData = database
@@ -70,7 +66,7 @@ class ToNfcConverter(
stage = characterInfo.stage.toByte(),
attribute = characterInfo.attribute,
ageInDays = userCharacter.ageInDays.toByte(),
- nextAdventureMissionStage = currentCardStage.toByte(),
+ nextAdventureMissionStage = characterInfo.currentStage.toByte(),
mood = userCharacter.mood.toByte(),
vitalPoints = userCharacter.vitalPoints.toUShort(),
transformationCountdownInMinutes = userCharacter.transformationCountdown.toUShort(),
@@ -101,6 +97,7 @@ class ToNfcConverter(
val cardData = database
.cardDao()
.getCardByCharacterId(userCharacter.id)
+ .first()
val appReserved = Array(3) {
0u
@@ -173,7 +170,6 @@ class ToNfcConverter(
private suspend fun nfcToBENfc(
characterId: Long,
characterInfo: CharacterDtos.CardCharacterInfo,
- currentCardStage: Int,
userCharacter: UserCharacter
): BENfcCharacter {
val beData = database
@@ -188,7 +184,7 @@ class ToNfcConverter(
stage = characterInfo.stage.toByte(),
attribute = characterInfo.attribute,
ageInDays = userCharacter.ageInDays.toByte(),
- nextAdventureMissionStage = currentCardStage.toByte(),
+ nextAdventureMissionStage = characterInfo.currentStage.toByte(),
mood = userCharacter.mood.toByte(),
vitalPoints = userCharacter.vitalPoints.toUShort(),
itemEffectMentalStateValue = beData.itemEffectMentalStateValue.toByte(),
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ReadingCharacter.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ActionScreen.kt
similarity index 85%
rename from app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ReadingCharacter.kt
rename to app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ActionScreen.kt
index 89ce2ed..8d216f2 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ReadingCharacter.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ActionScreen.kt
@@ -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.Column
@@ -14,13 +14,16 @@ import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.components.TopBanner
@Composable
-fun ReadingCharacterScreen(
+fun ActionScreen(
topBannerText: String,
onClickCancel: () -> Unit,
) {
Scaffold (
topBar = {
- TopBanner(topBannerText)
+ TopBanner(
+ text = topBannerText,
+ onBackClick = onClickCancel
+ )
}
) { innerPadding ->
Column (
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ReadCharacterScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ReadCharacterScreen.kt
new file mode 100644
index 0000000..757cc49
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ReadCharacterScreen.kt
@@ -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")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ReadingScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ReadingScreen.kt
new file mode 100644
index 0000000..58432ce
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/ReadingScreen.kt
@@ -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?>(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)
+ }
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WriteCardScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WriteCardScreen.kt
new file mode 100644
index 0000000..db47745
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WriteCardScreen.kt
@@ -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")
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WriteCharacterScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WriteCharacterScreen.kt
new file mode 100644
index 0000000..abd2606
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WriteCharacterScreen.kt
@@ -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")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WritingScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WritingScreen.kt
new file mode 100644
index 0000000..9680f41
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/screens/WritingScreen.kt
@@ -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()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt
index 47ad33f..691e610 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreen.kt
@@ -1,5 +1,7 @@
package com.github.nacabaro.vbhelper.screens.settingsScreen
+import android.content.Intent
+import android.net.Uri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -13,6 +15,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -25,6 +28,8 @@ fun SettingsScreen(
navController: NavController,
settingsScreenController: SettingsScreenControllerImpl,
) {
+ val context = LocalContext.current
+
Scaffold (
topBar = {
TopBanner(
@@ -44,19 +49,22 @@ fun SettingsScreen(
.verticalScroll(rememberScrollState())
) {
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()
}
SettingsSection("DiM/BEm management")
SettingsEntry(title = "Import card", description = "Import DiM/BEm card file") {
settingsScreenController.onClickImportCard()
}
- SettingsEntry(title = "Rename DiM/BEm", description = "Set card name") { }
SettingsSection("About and credits")
SettingsEntry(title = "Credits", description = "Credits") {
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")
SettingsEntry(title = "Export data", description = "Export application database") {
settingsScreenController.onClickOpenDirectory()
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt
index 95b2437..dd78c14 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt
@@ -3,36 +3,24 @@ package com.github.nacabaro.vbhelper.screens.settingsScreen
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import android.net.Uri
-import android.provider.OpenableColumns
-import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
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.di.VBHelper
-import com.github.nacabaro.vbhelper.domain.characters.Sprite
-import com.github.nacabaro.vbhelper.domain.card.Card
-import com.github.nacabaro.vbhelper.domain.card.CardProgress
-import com.github.nacabaro.vbhelper.domain.card.CharacterData
+import com.github.nacabaro.vbhelper.screens.settingsScreen.controllers.CardImportController
+import com.github.nacabaro.vbhelper.screens.settingsScreen.controllers.DatabaseManagementController
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter
import com.github.nacabaro.vbhelper.source.SecretsImporter
import com.github.nacabaro.vbhelper.source.SecretsRepository
import com.github.nacabaro.vbhelper.source.proto.Secrets
import kotlinx.coroutines.Dispatchers
-import java.io.File
-import java.io.InputStream
-import java.io.OutputStream
class SettingsScreenControllerImpl(
private val context: ComponentActivity,
): SettingsScreenController {
- private val roomDbName = "internalDb"
private val filePickerLauncher: ActivityResultLauncher
private val filePickerOpenerLauncher: ActivityResultLauncher>
private val filePickerApk: ActivityResultLauncher>
@@ -41,13 +29,17 @@ class SettingsScreenControllerImpl(
private val application = context.applicationContext as VBHelper
private val secretsRepository: SecretsRepository = application.container.dataStoreSecretsRepository
private val database: AppDatabase = application.container.db
+ private val databaseManagementController = DatabaseManagementController(
+ componentActivity = context,
+ application = application
+ )
init {
filePickerLauncher = context.registerForActivityResult(
ActivityResultContracts.CreateDocument("application/octet-stream")
) { uri ->
if (uri != null) {
- exportDatabase(uri)
+ databaseManagementController.exportDatabase(uri)
} else {
context.runOnUiThread {
Toast.makeText(context, "No destination selected", Toast.LENGTH_SHORT)
@@ -60,7 +52,7 @@ class SettingsScreenControllerImpl(
ActivityResultContracts.OpenDocument()
) { uri ->
if (uri != null) {
- importDatabase(uri)
+ databaseManagementController.importDatabase(uri)
} else {
context.runOnUiThread {
Toast.makeText(context, "No source selected", Toast.LENGTH_SHORT).show()
@@ -109,212 +101,14 @@ class SettingsScreenControllerImpl(
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()
-
- 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(
- CharacterData(
- 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 fun updateCardProgress(
- cardId: Long,
- ) {
- val cardProgress = CardProgress(
- cardId = cardId,
- currentStage = 0,
- unlocked = false
- )
-
- database
- .cardProgressDao()
- .updateDimProgress(cardProgress)
- }
-
private fun importCard(uri: Uri) {
context.lifecycleScope.launch(Dispatchers.IO) {
val contentResolver = context.contentResolver
val inputStream = contentResolver.openInputStream(uri)
inputStream.use { fileReader ->
- 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)
+ val cardImportController = CardImportController(database)
+ cardImportController.importCard(fileReader)
}
inputStream?.close()
@@ -324,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) {
context.lifecycleScope.launch(Dispatchers.IO) {
context.contentResolver.openInputStream(uri).use {
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/controllers/CardImportController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/controllers/CardImportController.kt
new file mode 100644
index 0000000..1626405
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/controllers/CardImportController.kt
@@ -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()
+
+ 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
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/controllers/DatabaseManagementController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/controllers/DatabaseManagementController.kt
new file mode 100644
index 0000000..f3fb931
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/controllers/DatabaseManagementController.kt
@@ -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
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageDialog.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageDialog.kt
index 9b0b1db..eebb1e6 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageDialog.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageDialog.kt
@@ -38,6 +38,7 @@ import kotlinx.coroutines.launch
fun StorageDialog(
characterId: Long,
onDismissRequest: () -> Unit,
+ onClickDelete: () -> Unit,
onSendToBracelet: () -> Unit,
onClickSetActive: () -> Unit,
onClickSendToAdventure: (time: Long) -> Unit
@@ -141,6 +142,13 @@ fun StorageDialog(
) {
Text(text = "Send on adventure")
}
+ Button(
+ modifier = Modifier
+ .fillMaxWidth(),
+ onClick = onClickDelete
+ ) {
+ Text(text = "Delete character")
+ }
Button(
modifier = Modifier
.fillMaxWidth(),
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreen.kt
index b5736bb..9a7bde8 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreen.kt
@@ -1,5 +1,6 @@
package com.github.nacabaro.vbhelper.screens.storageScreen
+import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.gestures.Orientation
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.items
import androidx.compose.foundation.rememberScrollState
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
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.TopBanner
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.screens.adventureScreen.AdventureScreenControllerImpl
import com.github.nacabaro.vbhelper.source.StorageRepository
import com.github.nacabaro.vbhelper.utils.BitmapData
-import kotlinx.coroutines.launch
@Composable
@@ -42,18 +42,11 @@ fun StorageScreen(
storageScreenController: StorageScreenControllerImpl,
adventureScreenController: AdventureScreenControllerImpl
) {
- val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper
val storageRepository = StorageRepository(application.container.db)
- val monList = remember { mutableStateOf>(emptyList()) }
- var selectedCharacter by remember { mutableStateOf(null) }
+ val characterList by storageRepository.getAllCharacters().collectAsState(initial = emptyList())
- LaunchedEffect(storageRepository, selectedCharacter) {
- coroutineScope.launch {
- val characterList = storageRepository.getAllCharacters()
- monList.value = characterList
- }
- }
+ var selectedCharacter by remember { mutableStateOf(null) }
Scaffold (
topBar = {
@@ -65,7 +58,7 @@ fun StorageScreen(
)
}
) { contentPadding ->
- if (monList.value.isEmpty()) {
+ if (characterList.isEmpty()) {
Column (
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
@@ -86,7 +79,7 @@ fun StorageScreen(
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
.padding(top = contentPadding.calculateTopPadding())
) {
- items(monList.value) { index ->
+ items(characterList) { index ->
CharacterEntry(
icon = BitmapData(
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
)
selectedCharacter = null
+ },
+ onClickDelete = {
+ storageScreenController
+ .deleteCharacter(
+ characterId = selectedCharacter!!,
+ onCompletion = {
+ Log.d("StorageScreen", "Character deleted")
+ }
+ )
+ selectedCharacter = null
}
)
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenController.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenController.kt
index b958c18..a37cbb0 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenController.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenController.kt
@@ -2,4 +2,5 @@ package com.github.nacabaro.vbhelper.screens.storageScreen
interface StorageScreenController {
fun setActive(characterId: Long, onCompletion: () -> Unit)
+ fun deleteCharacter(characterId: Long, onCompletion: () -> Unit)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenControllerImpl.kt
index 4473d4d..3eaf31d 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenControllerImpl.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/storageScreen/StorageScreenControllerImpl.kt
@@ -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()
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt
new file mode 100644
index 0000000..42fc61a
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/CurrencyRepository.kt
@@ -0,0 +1,28 @@
+package com.github.nacabaro.vbhelper.source
+
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.intPreferencesKey
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+class CurrencyRepository (
+ private val dataStore: DataStore
+) {
+
+ private companion object {
+ val CURRENCY_VALUE = intPreferencesKey("currency_value")
+ }
+
+ val currencyValue: Flow = dataStore.data
+ .map { preferences ->
+ preferences[CURRENCY_VALUE] ?: 10000
+ }
+
+ suspend fun setCurrencyValue(newValue: Int) {
+ dataStore.edit { preferences ->
+ preferences[CURRENCY_VALUE] = newValue
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt
index dcec614..585392c 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt
@@ -3,19 +3,24 @@ package com.github.nacabaro.vbhelper.source
import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.dtos.CharacterDtos
+import kotlinx.coroutines.flow.Flow
class DexRepository (
private val db: AppDatabase
) {
- suspend fun getAllDims(): List {
+ fun getAllDims(): Flow> {
return db.dexDao().getCardsWithProgress()
}
- suspend fun getCharactersByCardId(cardId: Long): List {
+ fun getCharactersByCardId(cardId: Long): Flow> {
return db.dexDao().getSingleCardProgress(cardId)
}
- suspend fun getCardPossibleTransformations(cardId: Long): List {
- return db.characterDao().getEvolutionRequirementsForCard(cardId)
+ fun getCharacterPossibleTransformations(characterId: Long): Flow> {
+ return db.characterDao().getEvolutionRequirementsForCard(characterId)
+ }
+
+ fun getCharacterPossibleFusions(characterId: Long): Flow> {
+ return db.cardFusionsDao().getFusionsForCharacter(characterId)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt
index 8d6d705..e93a49b 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/ItemsRepository.kt
@@ -1,17 +1,17 @@
package com.github.nacabaro.vbhelper.source
import com.github.nacabaro.vbhelper.database.AppDatabase
-import com.github.nacabaro.vbhelper.domain.items.Items
import com.github.nacabaro.vbhelper.dtos.ItemDtos
+import kotlinx.coroutines.flow.Flow
class ItemsRepository(
private val db: AppDatabase
) {
- suspend fun getAllItems(): List {
+ fun getAllItems(): Flow> {
return db.itemDao().getAllItems()
}
- suspend fun getUserItems(): List {
+ fun getUserItems(): Flow> {
return db.itemDao().getAllUserItems()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/ScanRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/ScanRepository.kt
new file mode 100644
index 0000000..4bc05f4
--- /dev/null
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/ScanRepository.kt
@@ -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 {
+ return database.cardDao().getCardByCharacterId(characterId)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt
index 61aff4a..f74da0d 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt
@@ -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.dtos.CharacterDtos
import com.github.nacabaro.vbhelper.dtos.ItemDtos
+import kotlinx.coroutines.flow.Flow
class StorageRepository (
private val db: AppDatabase
) {
- suspend fun getAllCharacters(): List {
+ fun getAllCharacters(): Flow> {
return db.userCharacterDao().getAllCharacters()
}
@@ -46,7 +47,7 @@ class StorageRepository (
return db.userCharacterDao().deleteCharacterById(id)
}
- suspend fun getAdventureCharacters(): List {
+ fun getAdventureCharacters(): Flow> {
return db.adventureDao().getAdventureCharacters()
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 2754f1b..1db28ca 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,5 @@
[versions]
-agp = "8.12.2"
+agp = "8.13.1"
datastore = "1.1.2"
kotlin = "2.0.0"
coreKtx = "1.15.0"