mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-10-01 15:41:36 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8f441ba2b | ||
|
|
59033e6459 | ||
|
|
4736202838 | ||
|
|
08e3b844a4 | ||
|
|
fbbb8f6ad1 | ||
|
|
859786c7f3 | ||
|
|
2f0555484e | ||
|
|
2f4bc9dba6 | ||
|
|
aa0f4241ea | ||
|
|
e9eedb7429 | ||
|
|
d40758dc02 |
@@ -46,6 +46,7 @@ dependencies {
|
|||||||
ksp(libs.androidx.room.compiler)
|
ksp(libs.androidx.room.compiler)
|
||||||
annotationProcessor(libs.androidx.room.compiler)
|
annotationProcessor(libs.androidx.room.compiler)
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
|
implementation("androidx.room:room-ktx:2.6.1")
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(platform(libs.androidx.compose.bom))
|
implementation(platform(libs.androidx.compose.bom))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".di.VBHelper"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|||||||
@@ -10,16 +10,32 @@ import android.widget.Toast
|
|||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import com.github.cfogrady.vbnfc.CryptographicTransformer
|
import androidx.compose.runtime.Composable
|
||||||
import com.github.cfogrady.vbnfc.TagCommunicator
|
import androidx.compose.runtime.getValue
|
||||||
import com.github.cfogrady.vbnfc.data.DeviceType
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import com.github.nacabaro.vbhelper.navigation.AppNavigation
|
import com.github.nacabaro.vbhelper.navigation.AppNavigation
|
||||||
|
import com.github.cfogrady.vbnfc.CryptographicTransformer
|
||||||
|
import com.github.cfogrady.vbnfc.R
|
||||||
|
import com.github.cfogrady.vbnfc.TagCommunicator
|
||||||
|
import com.github.cfogrady.vbnfc.be.BENfcCharacter
|
||||||
|
import com.github.cfogrady.vbnfc.data.DeviceType
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory
|
||||||
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private lateinit var nfcAdapter: NfcAdapter
|
private lateinit var nfcAdapter: NfcAdapter
|
||||||
private lateinit var deviceToCryptographicTransformers: Map<UShort, CryptographicTransformer>
|
private lateinit var deviceToCryptographicTransformers: Map<UShort, CryptographicTransformer>
|
||||||
|
|
||||||
|
private var nfcCharacter = MutableStateFlow<NfcCharacter?>(null)
|
||||||
|
|
||||||
// EXTRACTED DIRECTLY FROM EXAMPLE APP
|
// EXTRACTED DIRECTLY FROM EXAMPLE APP
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
deviceToCryptographicTransformers = getMapOfCryptographicTransformers()
|
deviceToCryptographicTransformers = getMapOfCryptographicTransformers()
|
||||||
@@ -32,24 +48,45 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
nfcAdapter = maybeNfcAdapter
|
nfcAdapter = maybeNfcAdapter
|
||||||
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
VBHelperTheme {
|
VBHelperTheme {
|
||||||
AppNavigation()
|
MainApplication()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MainApplication() {
|
||||||
|
var isDoneReadingCharacter by remember { mutableStateOf(false) }
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val storageRepository = application.container.db
|
||||||
|
AppNavigation(
|
||||||
|
isDoneReadingCharacter = isDoneReadingCharacter,
|
||||||
|
onClickRead = {
|
||||||
|
handleTag {
|
||||||
|
val character = it.receiveCharacter()
|
||||||
|
nfcCharacter.value = character
|
||||||
|
addCharacterScannedIntoDatabase()
|
||||||
|
isDoneReadingCharacter = true
|
||||||
|
"Done reading character"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClickScan = {
|
||||||
|
isDoneReadingCharacter = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// EXTRACTED DIRECTLY FROM EXAMPLE APP
|
// EXTRACTED DIRECTLY FROM EXAMPLE APP
|
||||||
private fun getMapOfCryptographicTransformers(): Map<UShort, CryptographicTransformer> {
|
private fun getMapOfCryptographicTransformers(): Map<UShort, CryptographicTransformer> {
|
||||||
return mapOf(
|
return mapOf(
|
||||||
Pair(DeviceType.VitalBraceletBEDeviceType,
|
Pair(DeviceType.VitalBraceletBEDeviceType,
|
||||||
CryptographicTransformer(readableHmacKey1 = resources.getString(com.github.cfogrady.vbnfc.R.string.password1),
|
CryptographicTransformer(readableHmacKey1 = resources.getString(R.string.password1),
|
||||||
readableHmacKey2 = resources.getString(com.github.cfogrady.vbnfc.R.string.password2),
|
readableHmacKey2 = resources.getString(R.string.password2),
|
||||||
aesKey = resources.getString(com.github.cfogrady.vbnfc.R.string.decryptionKey),
|
aesKey = resources.getString(R.string.decryptionKey),
|
||||||
substitutionCipher = resources.getIntArray(com.github.cfogrady.vbnfc.R.array.substitutionArray))),
|
substitutionCipher = resources.getIntArray(R.array.substitutionArray))),
|
||||||
// Pair(DeviceType.VitalSeriesDeviceType,
|
// Pair(DeviceType.VitalSeriesDeviceType,
|
||||||
// CryptographicTransformer(hmacKey1 = resources.getString(R.string.password1),
|
// CryptographicTransformer(hmacKey1 = resources.getString(R.string.password1),
|
||||||
// hmacKey2 = resources.getString(R.string.password2),
|
// hmacKey2 = resources.getString(R.string.password2),
|
||||||
@@ -110,4 +147,88 @@ class MainActivity : ComponentActivity() {
|
|||||||
nfcAdapter.disableReaderMode(this)
|
nfcAdapter.disableReaderMode(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
- Make it able to detect the different model of watches
|
||||||
|
- Support for regular VB
|
||||||
|
|
||||||
|
The good news is that the theory behind inserting to the database should be working
|
||||||
|
now, it's a matter of implementing the functionality to parse dim/bem cards and use my
|
||||||
|
domain model.
|
||||||
|
*/
|
||||||
|
private fun addCharacterScannedIntoDatabase() {
|
||||||
|
val beCharacter = nfcCharacter as MutableStateFlow<BENfcCharacter?>
|
||||||
|
val temporaryCharacterData = TemporaryCharacterData(
|
||||||
|
dimId = nfcCharacter.value!!.dimId.toInt(),
|
||||||
|
charIndex = nfcCharacter.value!!.charIndex.toInt(),
|
||||||
|
stage = nfcCharacter.value!!.stage.toInt(),
|
||||||
|
attribute = nfcCharacter.value!!.attribute,
|
||||||
|
ageInDays = nfcCharacter.value!!.ageInDays.toInt(),
|
||||||
|
nextAdventureMissionStage = nfcCharacter.value!!.nextAdventureMissionStage.toInt(),
|
||||||
|
mood = nfcCharacter.value!!.mood.toInt(),
|
||||||
|
vitalPoints = nfcCharacter.value!!.vitalPoints.toInt(),
|
||||||
|
transformationCountdown = nfcCharacter.value!!.transformationCountdown.toInt(),
|
||||||
|
injuryStatus = nfcCharacter.value!!.injuryStatus,
|
||||||
|
trophies = nfcCharacter.value!!.trophies.toInt(),
|
||||||
|
currentPhaseBattlesWon = nfcCharacter.value!!.currentPhaseBattlesWon.toInt(),
|
||||||
|
currentPhaseBattlesLost = nfcCharacter.value!!.currentPhaseBattlesLost.toInt(),
|
||||||
|
totalBattlesWon = nfcCharacter.value!!.totalBattlesWon.toInt(),
|
||||||
|
totalBattlesLost = nfcCharacter.value!!.totalBattlesLost.toInt(),
|
||||||
|
activityLevel = nfcCharacter.value!!.activityLevel.toInt(),
|
||||||
|
heartRateCurrent = nfcCharacter.value!!.heartRateCurrent.toInt()
|
||||||
|
)
|
||||||
|
|
||||||
|
val application = applicationContext as VBHelper
|
||||||
|
val storageRepository = application.container.db
|
||||||
|
val characterId: Long = storageRepository
|
||||||
|
.temporaryMonsterDao()
|
||||||
|
.insertCharacterData(temporaryCharacterData)
|
||||||
|
|
||||||
|
val temporaryBECharacterData = TemporaryBECharacterData(
|
||||||
|
id = characterId,
|
||||||
|
trainingHp = beCharacter.value!!.trainingHp.toInt(),
|
||||||
|
trainingAp = beCharacter.value!!.trainingAp.toInt(),
|
||||||
|
trainingBp = beCharacter.value!!.trainingBp.toInt(),
|
||||||
|
remainingTrainingTimeInMinutes = beCharacter.value!!.remainingTrainingTimeInMinutes.toInt(),
|
||||||
|
itemEffectActivityLevelValue = beCharacter.value!!.itemEffectActivityLevelValue.toInt(),
|
||||||
|
itemEffectMentalStateValue = beCharacter.value!!.itemEffectMentalStateValue.toInt(),
|
||||||
|
itemEffectMentalStateMinutesRemaining = beCharacter.value!!.itemEffectMentalStateMinutesRemaining.toInt(),
|
||||||
|
itemEffectActivityLevelMinutesRemaining = beCharacter.value!!.itemEffectActivityLevelMinutesRemaining.toInt(),
|
||||||
|
itemEffectVitalPointsChangeValue = beCharacter.value!!.itemEffectVitalPointsChangeValue.toInt(),
|
||||||
|
itemEffectVitalPointsChangeMinutesRemaining = beCharacter.value!!.itemEffectVitalPointsChangeMinutesRemaining.toInt(),
|
||||||
|
abilityRarity = beCharacter.value!!.abilityRarity,
|
||||||
|
abilityType = beCharacter.value!!.abilityType.toInt(),
|
||||||
|
abilityBranch = beCharacter.value!!.abilityBranch.toInt(),
|
||||||
|
abilityReset = beCharacter.value!!.abilityReset.toInt(),
|
||||||
|
rank = beCharacter.value!!.abilityReset.toInt(),
|
||||||
|
itemType = beCharacter.value!!.itemType.toInt(),
|
||||||
|
itemMultiplier = beCharacter.value!!.itemMultiplier.toInt(),
|
||||||
|
itemRemainingTime = beCharacter.value!!.itemRemainingTime.toInt(),
|
||||||
|
otp0 = "", //beCharacter.value!!.otp0.toString(),
|
||||||
|
otp1 = "", //beCharacter.value!!.otp1.toString(),
|
||||||
|
minorVersion = beCharacter.value!!.characterCreationFirmwareVersion.minorVersion.toInt(),
|
||||||
|
majorVersion = beCharacter.value!!.characterCreationFirmwareVersion.majorVersion.toInt(),
|
||||||
|
)
|
||||||
|
|
||||||
|
storageRepository
|
||||||
|
.temporaryMonsterDao()
|
||||||
|
.insertBECharacterData(temporaryBECharacterData)
|
||||||
|
|
||||||
|
val transformationHistoryWatch = beCharacter.value!!.transformationHistory
|
||||||
|
val domainTransformationHistory = transformationHistoryWatch.map { item ->
|
||||||
|
TemporaryTransformationHistory(
|
||||||
|
monId = characterId,
|
||||||
|
toCharIndex = item.toCharIndex.toInt(),
|
||||||
|
yearsSince1988 = item.yearsSince1988.toInt(),
|
||||||
|
month = item.month.toInt(),
|
||||||
|
day = item.day.toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
storageRepository
|
||||||
|
.temporaryMonsterDao()
|
||||||
|
.insertTransformationHistory(*domainTransformationHistory.toTypedArray())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,63 @@
|
|||||||
package com.github.nacabaro.vbhelper.components
|
package com.github.nacabaro.vbhelper.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.github.nacabaro.vbhelper.R
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TopBanner(
|
fun TopBanner(
|
||||||
text: String,
|
text: String,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
onGearClick: (() -> Unit)? = null,
|
||||||
|
onBackClick: (() -> Unit)? = null
|
||||||
|
) {
|
||||||
|
Box( // Use Box to overlay elements
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = 24.sp,
|
fontSize = 24.sp,
|
||||||
modifier = modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.align(Alignment.Center) // Center the text
|
||||||
.padding(16.dp)
|
)
|
||||||
|
if (onGearClick != null) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onGearClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterEnd) // Place gear icon at the end
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.baseline_settings_24), // Use a gear icon
|
||||||
|
contentDescription = "Settings"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onBackClick != null) {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBackClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterStart) // Place gear icon at the end
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.baseline_arrow_back_24), // Use a gear icon
|
||||||
|
contentDescription = "Settings"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.github.nacabaro.vbhelper.domain.Dim
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface DiMDao {
|
||||||
|
@Insert
|
||||||
|
suspend fun insertNewDim(dim: Dim)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Dim")
|
||||||
|
fun getAllDims(): Flow<List<Dim>>
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Upsert
|
||||||
|
import com.github.nacabaro.vbhelper.domain.DimProgress
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface DiMProgressDao {
|
||||||
|
@Upsert
|
||||||
|
suspend fun updateDimProgress(vararg dimProgress: DimProgress)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.github.nacabaro.vbhelper.domain.UserMonsters
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface UserMonstersDao {
|
||||||
|
@Insert
|
||||||
|
fun insertUserMonsters(userMonsters: UserMonsters)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM UserMonsters WHERE userId = :userId")
|
||||||
|
fun getUserMonsters(userId: Int): List<UserMonsters>
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface UserMonstersTransformationHistoryDao {
|
||||||
|
@Insert
|
||||||
|
fun insertTransformations(vararg transformations: TemporaryTransformationHistory)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.database
|
||||||
|
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_daos.TemporaryMonsterDao
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory
|
||||||
|
|
||||||
|
@Database(
|
||||||
|
version = 1,
|
||||||
|
entities = [
|
||||||
|
TemporaryCharacterData::class,
|
||||||
|
TemporaryBECharacterData::class,
|
||||||
|
TemporaryTransformationHistory::class
|
||||||
|
]
|
||||||
|
)
|
||||||
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
abstract fun temporaryMonsterDao(): TemporaryMonsterDao
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.di
|
||||||
|
|
||||||
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
|
|
||||||
|
interface AppContainer {
|
||||||
|
val db: AppDatabase
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Room
|
||||||
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
|
import com.github.nacabaro.vbhelper.di.AppContainer
|
||||||
|
|
||||||
|
class DefaultAppContainer(private val context: Context) : AppContainer {
|
||||||
|
override val db: AppDatabase by lazy {
|
||||||
|
Room.databaseBuilder(
|
||||||
|
context = context,
|
||||||
|
klass = AppDatabase::class.java,
|
||||||
|
"internalDb"
|
||||||
|
).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.di
|
||||||
|
|
||||||
|
import DefaultAppContainer
|
||||||
|
import android.app.Application
|
||||||
|
|
||||||
|
class VBHelper : Application() {
|
||||||
|
lateinit var container: DefaultAppContainer
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
container = DefaultAppContainer(applicationContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.dtos
|
||||||
|
|
||||||
|
class MonsterDataCombined {
|
||||||
|
}
|
||||||
@@ -11,10 +11,15 @@ import com.github.nacabaro.vbhelper.screens.BattlesScreen
|
|||||||
import com.github.nacabaro.vbhelper.screens.DexScreen
|
import com.github.nacabaro.vbhelper.screens.DexScreen
|
||||||
import com.github.nacabaro.vbhelper.screens.HomeScreen
|
import com.github.nacabaro.vbhelper.screens.HomeScreen
|
||||||
import com.github.nacabaro.vbhelper.screens.ScanScreen
|
import com.github.nacabaro.vbhelper.screens.ScanScreen
|
||||||
|
import com.github.nacabaro.vbhelper.screens.SettingsScreen
|
||||||
import com.github.nacabaro.vbhelper.screens.StorageScreen
|
import com.github.nacabaro.vbhelper.screens.StorageScreen
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppNavigation() {
|
fun AppNavigation(
|
||||||
|
onClickRead: () -> Unit,
|
||||||
|
onClickScan: () -> Unit,
|
||||||
|
isDoneReadingCharacter: Boolean
|
||||||
|
) {
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -32,17 +37,29 @@ fun AppNavigation() {
|
|||||||
BattlesScreen()
|
BattlesScreen()
|
||||||
}
|
}
|
||||||
composable(BottomNavItem.Home.route) {
|
composable(BottomNavItem.Home.route) {
|
||||||
HomeScreen()
|
HomeScreen(
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
}
|
}
|
||||||
composable(BottomNavItem.Storage.route) {
|
composable(BottomNavItem.Storage.route) {
|
||||||
StorageScreen()
|
StorageScreen()
|
||||||
}
|
}
|
||||||
composable(BottomNavItem.Scan.route) {
|
composable(BottomNavItem.Scan.route) {
|
||||||
ScanScreen()
|
onClickScan()
|
||||||
|
ScanScreen(
|
||||||
|
navController = navController,
|
||||||
|
onClickRead = onClickRead,
|
||||||
|
isDoneReadingCharacter = isDoneReadingCharacter
|
||||||
|
)
|
||||||
}
|
}
|
||||||
composable(BottomNavItem.Dex.route) {
|
composable(BottomNavItem.Dex.route) {
|
||||||
DexScreen()
|
DexScreen()
|
||||||
}
|
}
|
||||||
|
composable(BottomNavItem.Settings.route) {
|
||||||
|
SettingsScreen(
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ sealed class BottomNavItem (
|
|||||||
var label: String
|
var label: String
|
||||||
) {
|
) {
|
||||||
object Scan : BottomNavItem("Scan", R.drawable.baseline_nfc_24, "Scan")
|
object Scan : BottomNavItem("Scan", R.drawable.baseline_nfc_24, "Scan")
|
||||||
object Battles : BottomNavItem("Battles", R.drawable.baseline_swords_24, "Battles")
|
object Battles : BottomNavItem("Battle", R.drawable.baseline_swords_24, "Battle")
|
||||||
object Home : BottomNavItem("Home", R.drawable.baseline_cottage_24, "Home")
|
object Home : BottomNavItem("Home", R.drawable.baseline_cottage_24, "Home")
|
||||||
object Dex : BottomNavItem("Dex", R.drawable.baseline_menu_book_24, "Dex")
|
object Dex : BottomNavItem("Dex", R.drawable.baseline_menu_book_24, "Dex")
|
||||||
object Storage : BottomNavItem("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
|
object Storage : BottomNavItem("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
|
||||||
|
object Settings : BottomNavItem("Settings", R.drawable.baseline_settings_24, "Settings")
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,34 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens
|
package com.github.nacabaro.vbhelper.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.navigation.BottomNavItem
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen() {
|
fun HomeScreen(
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
Scaffold (
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "VB Helper",
|
||||||
|
onGearClick = {
|
||||||
|
navController.navigate(BottomNavItem.Settings.route)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { contentPadding ->
|
||||||
|
Box (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
) {
|
||||||
Text("Home Screen")
|
Text("Home Screen")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,15 +10,50 @@ import androidx.compose.material3.Button
|
|||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.navigation.BottomNavItem
|
||||||
|
import com.github.nacabaro.vbhelper.screens.scanScreen.ReadingCharacterScreen
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ScanScreen() {
|
fun ScanScreen(
|
||||||
|
navController: NavController,
|
||||||
|
onClickRead: () -> Unit,
|
||||||
|
isDoneReadingCharacter: Boolean
|
||||||
|
) {
|
||||||
|
var readingScreen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (isDoneReadingCharacter) {
|
||||||
|
readingScreen = false
|
||||||
|
navController.navigate(BottomNavItem.Home.route)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readingScreen) {
|
||||||
|
ReadingCharacterScreen { readingScreen = false }
|
||||||
|
} else {
|
||||||
|
ChooseConnectOption(
|
||||||
|
onClickRead = {
|
||||||
|
readingScreen = true
|
||||||
|
onClickRead()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ChooseConnectOption(
|
||||||
|
onClickRead: () -> Unit,
|
||||||
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { TopBanner(text = "Scan a Vital Bracelet") }
|
topBar = { TopBanner(text = "Scan a Vital Bracelet") }
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
@@ -31,7 +66,7 @@ fun ScanScreen() {
|
|||||||
) {
|
) {
|
||||||
ScanButton(
|
ScanButton(
|
||||||
text = "Vital Bracelet to App",
|
text = "Vital Bracelet to App",
|
||||||
onClick = {}
|
onClick = onClickRead
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
ScanButton(
|
ScanButton(
|
||||||
@@ -42,6 +77,7 @@ fun ScanScreen() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ScanButton(
|
fun ScanButton(
|
||||||
text: String,
|
text: String,
|
||||||
@@ -64,5 +100,9 @@ fun ScanButton(
|
|||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
fun ScanScreenPreview() {
|
fun ScanScreenPreview() {
|
||||||
ScanScreen()
|
ScanScreen(
|
||||||
|
navController = rememberNavController(),
|
||||||
|
onClickRead = { },
|
||||||
|
isDoneReadingCharacter = false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsScreen(
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
Scaffold (
|
||||||
|
topBar = {
|
||||||
|
TopBanner(
|
||||||
|
text = "Settings",
|
||||||
|
onBackClick = {
|
||||||
|
navController.popBackStack()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) { contentPadding ->
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
SettingsSection("General")
|
||||||
|
SettingsEntry(title = "Import VB key", description = "Import standard vital bracelet keys") { }
|
||||||
|
SettingsEntry(title = "Import VB Characters key", description = "Import standard vital bracelet keys") { }
|
||||||
|
SettingsEntry(title = "Import VB BE key", description = "Import standard vital bracelet keys") { }
|
||||||
|
SettingsEntry(title = "Import transform functions", description = "Import standard vital bracelet keys") { }
|
||||||
|
SettingsEntry(title = "Import decryption key", description = "Import standard vital bracelet keys") { }
|
||||||
|
SettingsSection("DiM/BEm management")
|
||||||
|
SettingsEntry(title = "Import DiM card", description = "Import DiM card file") { }
|
||||||
|
SettingsEntry(title = "Import BEm card", description = "Import BEm card file") { }
|
||||||
|
SettingsSection("About and credits")
|
||||||
|
SettingsEntry(title = "Credits", description = "Credits") { }
|
||||||
|
SettingsEntry(title = "About", description = "About") { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsEntry(
|
||||||
|
title: String,
|
||||||
|
description: String,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onClick() }
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text(text = title)
|
||||||
|
Text(
|
||||||
|
text = description,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = MaterialTheme.colorScheme.outline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsSection(
|
||||||
|
title: String
|
||||||
|
) {
|
||||||
|
Box (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,44 +1,112 @@
|
|||||||
package com.github.nacabaro.vbhelper.screens
|
package com.github.nacabaro.vbhelper.screens
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
import androidx.compose.foundation.gestures.scrollable
|
import androidx.compose.foundation.gestures.scrollable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardElevation
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
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.R
|
||||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
import com.github.nacabaro.vbhelper.di.VBHelper
|
||||||
|
import com.github.nacabaro.vbhelper.source.StorageRepository
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||||
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun StorageScreen() {
|
fun StorageScreen() {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
|
val monList = remember { mutableStateListOf<TemporaryCharacterData>() }
|
||||||
|
|
||||||
|
var selectedCharacter by remember { mutableStateOf<Long?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(storageRepository) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
monList.clear()
|
||||||
|
monList.addAll(storageRepository.getAllCharacters())
|
||||||
|
Log.d("StorageScreen", "Updated data: $monList")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("StorageScreen", "monList: $monList")
|
||||||
|
|
||||||
Scaffold (
|
Scaffold (
|
||||||
topBar = { TopBanner(text = "My Digimon") }
|
topBar = { TopBanner(text = "My Digimon") }
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
|
if (monList.isEmpty()) {
|
||||||
|
Column (
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(contentPadding)
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Nothing to see here",
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(3),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
|
.scrollable(state = rememberScrollState(), orientation = Orientation.Vertical)
|
||||||
.padding(top = contentPadding.calculateTopPadding())
|
.padding(top = contentPadding.calculateTopPadding())
|
||||||
) {
|
) {
|
||||||
items(100) { i ->
|
items(monList) { index ->
|
||||||
|
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
StorageEntry(
|
StorageEntry(
|
||||||
name = "Digimon $i",
|
name = index.dimId.toString() + " - " + index.charIndex.toString(),
|
||||||
icon = R.drawable.baseline_question_mark_24
|
icon = R.drawable.ic_launcher_foreground,
|
||||||
|
onClick = { selectedCharacter = index.id },
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(8.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (selectedCharacter != null) {
|
||||||
|
StorageDialog(
|
||||||
|
characterId = selectedCharacter!!,
|
||||||
|
onDismissRequest = { selectedCharacter = null }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,10 +116,12 @@ fun StorageScreen() {
|
|||||||
fun StorageEntry(
|
fun StorageEntry(
|
||||||
name: String,
|
name: String,
|
||||||
icon: Int,
|
icon: Int,
|
||||||
|
onClick: () -> Unit = {},
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Card(
|
Card(
|
||||||
shape = MaterialTheme.shapes.medium,
|
shape = MaterialTheme.shapes.medium,
|
||||||
|
onClick = onClick,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
) {
|
) {
|
||||||
@@ -76,3 +146,51 @@ fun StorageEntry(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun StorageDialog(
|
||||||
|
characterId: Long,
|
||||||
|
onDismissRequest: () -> Unit
|
||||||
|
) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val application = LocalContext.current.applicationContext as VBHelper
|
||||||
|
val storageRepository = StorageRepository(application.container.db)
|
||||||
|
val character = remember { mutableStateOf<TemporaryCharacterData?>(null) }
|
||||||
|
|
||||||
|
LaunchedEffect(storageRepository) {
|
||||||
|
coroutineScope.launch {
|
||||||
|
character.value = storageRepository.getSingleCharacter(characterId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
properties = DialogProperties(
|
||||||
|
dismissOnBackPress = true,
|
||||||
|
dismissOnClickOutside = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
) {
|
||||||
|
Column (
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
if (character.value != null) {
|
||||||
|
Text(
|
||||||
|
text = character.value?.toString() ?: "Loading...",
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = onDismissRequest
|
||||||
|
) {
|
||||||
|
Text(text = "Close")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.screens.scanScreen
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
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.unit.dp
|
||||||
|
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReadingCharacterScreen(
|
||||||
|
onClickCancel: () -> Unit,
|
||||||
|
) {
|
||||||
|
Scaffold (
|
||||||
|
topBar = {
|
||||||
|
TopBanner("Reading Character")
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Column (
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Text("Place your Vital Bracelet near the reader...")
|
||||||
|
Button(
|
||||||
|
onClick = onClickCancel,
|
||||||
|
modifier = Modifier.padding(16.dp)
|
||||||
|
) {
|
||||||
|
Text("Cancel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.source
|
||||||
|
|
||||||
|
import com.github.nacabaro.vbhelper.database.AppDatabase
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||||
|
|
||||||
|
class StorageRepository (
|
||||||
|
private val db: AppDatabase
|
||||||
|
) {
|
||||||
|
suspend fun getAllCharacters(): List<TemporaryCharacterData> {
|
||||||
|
return db.temporaryMonsterDao().getAllCharacters()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSingleCharacter(id: Long): TemporaryCharacterData {
|
||||||
|
return db.temporaryMonsterDao().getCharacter(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.temporary_daos
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData
|
||||||
|
import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface TemporaryMonsterDao {
|
||||||
|
@Insert
|
||||||
|
fun insertCharacterData(temporaryCharacterData: TemporaryCharacterData): Long
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertBECharacterData(temporaryBECharacterData: TemporaryBECharacterData)
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insertTransformationHistory(vararg transformationHistory: TemporaryTransformationHistory)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM TemporaryTransformationHistory WHERE monId = :monId")
|
||||||
|
fun getTransformationHistory(monId: Int): List<TemporaryTransformationHistory>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM TemporaryCharacterData")
|
||||||
|
suspend fun getAllCharacters(): List<TemporaryCharacterData>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM TemporaryCharacterData WHERE id = :id")
|
||||||
|
suspend fun getCharacter(id: Long): TemporaryCharacterData
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.temporary_domain
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import com.github.cfogrady.vbnfc.be.BENfcCharacter
|
||||||
|
import com.github.cfogrady.vbnfc.be.FirmwareVersion
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = TemporaryCharacterData::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["id"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
data class TemporaryBECharacterData (
|
||||||
|
@PrimaryKey(autoGenerate = true) val id: Long,
|
||||||
|
val trainingHp: Int,
|
||||||
|
val trainingAp: Int,
|
||||||
|
val trainingBp: Int,
|
||||||
|
val remainingTrainingTimeInMinutes: Int,
|
||||||
|
val itemEffectMentalStateValue: Int,
|
||||||
|
val itemEffectMentalStateMinutesRemaining: Int,
|
||||||
|
val itemEffectActivityLevelValue: Int,
|
||||||
|
val itemEffectActivityLevelMinutesRemaining: Int,
|
||||||
|
val itemEffectVitalPointsChangeValue: Int,
|
||||||
|
val itemEffectVitalPointsChangeMinutesRemaining: Int,
|
||||||
|
val abilityRarity: NfcCharacter.AbilityRarity,
|
||||||
|
val abilityType: Int,
|
||||||
|
val abilityBranch: Int,
|
||||||
|
val abilityReset: Int,
|
||||||
|
val rank: Int,
|
||||||
|
val itemType: Int,
|
||||||
|
val itemMultiplier: Int,
|
||||||
|
val itemRemainingTime: Int,
|
||||||
|
val otp0: String,
|
||||||
|
val otp1: String,
|
||||||
|
val minorVersion: Int,
|
||||||
|
val majorVersion: Int,
|
||||||
|
)
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.temporary_domain
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import com.github.cfogrady.vbnfc.data.NfcCharacter
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
data class TemporaryCharacterData (
|
||||||
|
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
||||||
|
val dimId: Int,
|
||||||
|
var charIndex: Int,
|
||||||
|
var stage: Int,
|
||||||
|
var attribute: NfcCharacter.Attribute,
|
||||||
|
var ageInDays: Int,
|
||||||
|
var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim
|
||||||
|
var mood: Int,
|
||||||
|
var vitalPoints: Int,
|
||||||
|
var transformationCountdown: Int,
|
||||||
|
var injuryStatus: NfcCharacter.InjuryStatus,
|
||||||
|
var trophies: Int,
|
||||||
|
var currentPhaseBattlesWon: Int,
|
||||||
|
var currentPhaseBattlesLost: Int,
|
||||||
|
var totalBattlesWon: Int,
|
||||||
|
var totalBattlesLost: Int,
|
||||||
|
var activityLevel: Int,
|
||||||
|
var heartRateCurrent: Int,
|
||||||
|
)
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.temporary_domain
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.ForeignKey
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(
|
||||||
|
foreignKeys = [
|
||||||
|
ForeignKey(
|
||||||
|
entity = TemporaryCharacterData::class,
|
||||||
|
parentColumns = ["id"],
|
||||||
|
childColumns = ["monId"],
|
||||||
|
onDelete = ForeignKey.CASCADE
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
// Bit lazy, will correct later...
|
||||||
|
data class TemporaryTransformationHistory (
|
||||||
|
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
||||||
|
val monId: Long,
|
||||||
|
val toCharIndex: Int,
|
||||||
|
val yearsSince1988: Int,
|
||||||
|
val month: Int,
|
||||||
|
val day: Int
|
||||||
|
)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
package com.github.nacabaro.vbhelper.vm
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -69,8 +69,9 @@ class TagCommunicator(
|
|||||||
checksumCalculator.checkChecksums(decryptedCharacterData)
|
checksumCalculator.checkChecksums(decryptedCharacterData)
|
||||||
val nfcCharacter = translator.parseNfcCharacter(decryptedCharacterData)
|
val nfcCharacter = translator.parseNfcCharacter(decryptedCharacterData)
|
||||||
Log.i(TAG, "Known Character Stats: $nfcCharacter")
|
Log.i(TAG, "Known Character Stats: $nfcCharacter")
|
||||||
Log.i(TAG, "Signaling operation complete")
|
// Not ready to lose any of my mons in this...
|
||||||
nfcData.transceive(translator.getOperationCommandBytes(header, OPERATION_TRANSFERRED_TO_APP))
|
//Log.i(TAG, "Signaling operation complete")
|
||||||
|
//nfcData.transceive(translator.getOperationCommandBytes(header, OPERATION_TRANSFERRED_TO_APP))
|
||||||
return nfcCharacter
|
return nfcCharacter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user