From a974bd366e8a906691f6f5d53c601bb1e365ef45 Mon Sep 17 00:00:00 2001 From: Nacho Date: Tue, 21 Jan 2025 13:02:45 +0100 Subject: [PATCH] Moved read character from watch to its corresponding controller --- .../github/nacabaro/vbhelper/MainActivity.kt | 131 +--------------- .../screens/homeScreens/HomeScreen.kt | 3 - .../scanScreen/ScanScreenControllerImpl.kt | 140 +++++++++++++++--- 3 files changed, 124 insertions(+), 150 deletions(-) diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt index cee99cb..039b322 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/MainActivity.kt @@ -7,25 +7,15 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.runtime.Composable import com.github.nacabaro.vbhelper.navigation.AppNavigation -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.device_data.BECharacterData -import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter import com.github.nacabaro.vbhelper.navigation.AppNavigationHandlers import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImpl import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenControllerImpl import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl import com.github.nacabaro.vbhelper.ui.theme.VBHelperTheme -import com.github.nacabaro.vbhelper.utils.DeviceType -import kotlinx.coroutines.flow.MutableStateFlow -import java.util.GregorianCalendar + class MainActivity : ComponentActivity() { - - private var nfcCharacter = MutableStateFlow(null) - private val onActivityLifecycleListeners = HashMap() private fun registerActivityLifecycleListener(key: String, activityLifecycleListener: ActivityLifecycleListener) { @@ -43,7 +33,6 @@ class MainActivity : ComponentActivity() { val application = applicationContext as VBHelper val scanScreenController = ScanScreenControllerImpl( application.container.dataStoreSecretsRepository.secretsFlow, - this::handleReceivedNfcCharacter, this, this::registerActivityLifecycleListener, this::unregisterActivityLifecycleListener @@ -98,122 +87,4 @@ class MainActivity : ComponentActivity() { ) ) } - - private fun handleReceivedNfcCharacter(character: NfcCharacter): String { - nfcCharacter.value = character - - val importStatus = addCharacterScannedIntoDatabase() - - return importStatus - } - - // - /* - TODO: - - 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(): String { - val application = applicationContext as VBHelper - val storageRepository = application.container.db - - val dimData = storageRepository - .dimDao() - .getDimById(nfcCharacter.value!!.dimId.toInt()) - - if (dimData == null) return "Card not found" - - val cardCharData = storageRepository - .characterDao() - .getCharacterByMonIndex(nfcCharacter.value!!.charIndex.toInt(), dimData.id) - - val characterData = UserCharacter( - charId = cardCharData.id, - 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!!.transformationCountdownInMinutes.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(), - characterType = when (nfcCharacter.value) { - is BENfcCharacter -> DeviceType.BEDevice - else -> DeviceType.VBDevice - }, - isActive = true - ) - - storageRepository - .userCharacterDao() - .clearActiveCharacter() - - val characterId: Long = storageRepository - .userCharacterDao() - .insertCharacterData(characterData) - - if (nfcCharacter.value is BENfcCharacter) { - val beCharacter = nfcCharacter.value as BENfcCharacter - val extraCharacterData = BECharacterData( - id = characterId, - trainingHp = beCharacter.trainingHp.toInt(), - trainingAp = beCharacter.trainingAp.toInt(), - trainingBp = beCharacter.trainingBp.toInt(), - remainingTrainingTimeInMinutes = beCharacter.remainingTrainingTimeInMinutes.toInt(), - itemEffectActivityLevelValue = beCharacter.itemEffectActivityLevelValue.toInt(), - itemEffectMentalStateValue = beCharacter.itemEffectMentalStateValue.toInt(), - itemEffectMentalStateMinutesRemaining = beCharacter.itemEffectMentalStateMinutesRemaining.toInt(), - itemEffectActivityLevelMinutesRemaining = beCharacter.itemEffectActivityLevelMinutesRemaining.toInt(), - itemEffectVitalPointsChangeValue = beCharacter.itemEffectVitalPointsChangeValue.toInt(), - itemEffectVitalPointsChangeMinutesRemaining = beCharacter.itemEffectVitalPointsChangeMinutesRemaining.toInt(), - abilityRarity = beCharacter.abilityRarity, - abilityType = beCharacter.abilityType.toInt(), - abilityBranch = beCharacter.abilityBranch.toInt(), - abilityReset = beCharacter.abilityReset.toInt(), - rank = beCharacter.abilityReset.toInt(), - itemType = beCharacter.itemType.toInt(), - itemMultiplier = beCharacter.itemMultiplier.toInt(), - itemRemainingTime = beCharacter.itemRemainingTime.toInt(), - otp0 = "", //beCharacter.value!!.otp0.toString(), - otp1 = "", //beCharacter.value!!.otp1.toString(), - minorVersion = beCharacter.characterCreationFirmwareVersion.minorVersion.toInt(), - majorVersion = beCharacter.characterCreationFirmwareVersion.majorVersion.toInt(), - ) - - storageRepository - .userCharacterDao() - .insertBECharacterData(extraCharacterData) - - val transformationHistoryWatch = beCharacter.transformationHistory - transformationHistoryWatch.map { item -> - if (item.toCharIndex.toInt() != 255) { - val date = GregorianCalendar(item.year.toInt(), item.month.toInt(), item.day.toInt()) - .time - .time - - storageRepository - .characterDao() - .insertTransformation(characterId, item.toCharIndex.toInt(), dimData.id, date) - - storageRepository - .dexDao() - .insertCharacter(item.toCharIndex.toInt(), dimData.id, date) - } - } - } else if (nfcCharacter.value is VBNfcCharacter) { - return "Not implemented yet" - } - - return "Done reading character!" - } } 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 35863a7..2ad2a19 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 @@ -72,7 +71,6 @@ fun HomeScreen( } } else { if (activeMon.value!!.isBemCard) { - Log.d("HomeScreen", "BEDeviceBEm") BEBEmHomeScreen( activeMon = activeMon.value!!, beData = beData.value!!, @@ -80,7 +78,6 @@ fun HomeScreen( contentPadding = contentPadding ) } else if (!activeMon.value!!.isBemCard && activeMon.value!!.characterType == DeviceType.BEDevice) { - Log.d("HomeScreen", "BEDevice") BEDiMHomeScreen( activeMon = activeMon.value!!, beData = beData.value!!, diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt index 99155bc..d7caf92 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt @@ -11,20 +11,26 @@ import android.widget.Toast import androidx.activity.ComponentActivity import androidx.lifecycle.lifecycleScope import com.github.cfogrady.vbnfc.TagCommunicator +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.ActivityLifecycleListener +import com.github.nacabaro.vbhelper.di.VBHelper +import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData +import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter import com.github.nacabaro.vbhelper.source.getCryptographicTransformerMap import com.github.nacabaro.vbhelper.source.isMissingSecrets import com.github.nacabaro.vbhelper.source.proto.Secrets +import com.github.nacabaro.vbhelper.utils.DeviceType import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch +import java.util.GregorianCalendar class ScanScreenControllerImpl( override val secretsFlow: Flow, - private val nfcHandler: (NfcCharacter)->String, - private val context: ComponentActivity, + private val componentActivity: ComponentActivity, private val registerActivityLifecycleListener: (String, ActivityLifecycleListener)->Unit, private val unregisterActivityLifecycleListener: (String)->Unit, ): ScanScreenController { @@ -32,9 +38,9 @@ class ScanScreenControllerImpl( private val nfcAdapter: NfcAdapter init { - val maybeNfcAdapter = NfcAdapter.getDefaultAdapter(context) + val maybeNfcAdapter = NfcAdapter.getDefaultAdapter(componentActivity) if (maybeNfcAdapter == null) { - Toast.makeText(context, "No NFC on device!", Toast.LENGTH_SHORT).show() + Toast.makeText(componentActivity, "No NFC on device!", Toast.LENGTH_SHORT).show() } nfcAdapter = maybeNfcAdapter checkSecrets() @@ -43,7 +49,7 @@ class ScanScreenControllerImpl( override fun onClickRead(secrets: Secrets, onComplete: ()->Unit) { handleTag(secrets) { tagCommunicator -> val character = tagCommunicator.receiveCharacter() - val resultMessage = nfcHandler(character) + val resultMessage = addCharacterScannedIntoDatabase(character) onComplete.invoke() resultMessage } @@ -51,7 +57,7 @@ class ScanScreenControllerImpl( override fun cancelRead() { if(nfcAdapter.isEnabled) { - nfcAdapter.disableReaderMode(context) + nfcAdapter.disableReaderMode(componentActivity) } } @@ -74,7 +80,7 @@ class ScanScreenControllerImpl( val options = Bundle() // Work around for some broken Nfc firmware implementations that poll the card too fast options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250) - nfcAdapter.enableReaderMode(context, buildOnReadTag(secrets, handlerFunc), NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, + nfcAdapter.enableReaderMode(componentActivity, buildOnReadTag(secrets, handlerFunc), NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, options ) } @@ -85,26 +91,26 @@ class ScanScreenControllerImpl( return { tag-> val nfcData = NfcA.get(tag) if (nfcData == null) { - context.runOnUiThread { - Toast.makeText(context, "Tag detected is not VB", Toast.LENGTH_SHORT).show() + componentActivity.runOnUiThread { + Toast.makeText(componentActivity, "Tag detected is not VB", Toast.LENGTH_SHORT).show() } } nfcData.connect() nfcData.use { val tagCommunicator = TagCommunicator.getInstance(nfcData, secrets.getCryptographicTransformerMap()) val successText = handlerFunc(tagCommunicator) - context.runOnUiThread { - Toast.makeText(context, successText, Toast.LENGTH_SHORT).show() + componentActivity.runOnUiThread { + Toast.makeText(componentActivity, successText, Toast.LENGTH_SHORT).show() } } } } private fun checkSecrets() { - context.lifecycleScope.launch(Dispatchers.IO) { - if(secretsFlow.stateIn(context.lifecycleScope).value.isMissingSecrets()) { - context.runOnUiThread { - Toast.makeText(context, "Missing Secrets. Go to settings and import Vital Arena APK", Toast.LENGTH_SHORT).show() + componentActivity.lifecycleScope.launch(Dispatchers.IO) { + if(secretsFlow.stateIn(componentActivity.lifecycleScope).value.isMissingSecrets()) { + componentActivity.runOnUiThread { + Toast.makeText(componentActivity, "Missing Secrets. Go to settings and import Vital Arena APK", Toast.LENGTH_SHORT).show() } } } @@ -141,7 +147,107 @@ class ScanScreenControllerImpl( // EXTRACTED DIRECTLY FROM EXAMPLE APP private fun showWirelessSettings() { - Toast.makeText(context, "NFC must be enabled", Toast.LENGTH_SHORT).show() - context.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS)) + Toast.makeText(componentActivity, "NFC must be enabled", Toast.LENGTH_SHORT).show() + componentActivity.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS)) + } + + private fun addCharacterScannedIntoDatabase(nfcCharacter: NfcCharacter): String { + val application = componentActivity.applicationContext as VBHelper + val storageRepository = application.container.db + + val dimData = storageRepository + .dimDao() + .getDimById(nfcCharacter.dimId.toInt()) + + if (dimData == null) return "Card not found" + + val cardCharData = storageRepository + .characterDao() + .getCharacterByMonIndex(nfcCharacter.charIndex.toInt(), dimData.id) + + val characterData = UserCharacter( + charId = cardCharData.id, + stage = nfcCharacter.stage.toInt(), + attribute = nfcCharacter.attribute, + ageInDays = nfcCharacter.ageInDays.toInt(), + nextAdventureMissionStage = nfcCharacter.nextAdventureMissionStage.toInt(), + mood = nfcCharacter.mood.toInt(), + vitalPoints = nfcCharacter.vitalPoints.toInt(), + transformationCountdown = nfcCharacter.transformationCountdownInMinutes.toInt(), + injuryStatus = nfcCharacter.injuryStatus, + trophies = nfcCharacter.trophies.toInt(), + currentPhaseBattlesWon = nfcCharacter.currentPhaseBattlesWon.toInt(), + currentPhaseBattlesLost = nfcCharacter.currentPhaseBattlesLost.toInt(), + totalBattlesWon = nfcCharacter.totalBattlesWon.toInt(), + totalBattlesLost = nfcCharacter.totalBattlesLost.toInt(), + activityLevel = nfcCharacter.activityLevel.toInt(), + heartRateCurrent = nfcCharacter.heartRateCurrent.toInt(), + characterType = when (nfcCharacter) { + is BENfcCharacter -> DeviceType.BEDevice + else -> DeviceType.VBDevice + }, + isActive = true + ) + + storageRepository + .userCharacterDao() + .clearActiveCharacter() + + val characterId: Long = storageRepository + .userCharacterDao() + .insertCharacterData(characterData) + + if (nfcCharacter is BENfcCharacter) { + val extraCharacterData = BECharacterData( + id = characterId, + trainingHp = nfcCharacter.trainingHp.toInt(), + trainingAp = nfcCharacter.trainingAp.toInt(), + trainingBp = nfcCharacter.trainingBp.toInt(), + remainingTrainingTimeInMinutes = nfcCharacter.remainingTrainingTimeInMinutes.toInt(), + itemEffectActivityLevelValue = nfcCharacter.itemEffectActivityLevelValue.toInt(), + itemEffectMentalStateValue = nfcCharacter.itemEffectMentalStateValue.toInt(), + itemEffectMentalStateMinutesRemaining = nfcCharacter.itemEffectMentalStateMinutesRemaining.toInt(), + itemEffectActivityLevelMinutesRemaining = nfcCharacter.itemEffectActivityLevelMinutesRemaining.toInt(), + itemEffectVitalPointsChangeValue = nfcCharacter.itemEffectVitalPointsChangeValue.toInt(), + itemEffectVitalPointsChangeMinutesRemaining = nfcCharacter.itemEffectVitalPointsChangeMinutesRemaining.toInt(), + abilityRarity = nfcCharacter.abilityRarity, + abilityType = nfcCharacter.abilityType.toInt(), + abilityBranch = nfcCharacter.abilityBranch.toInt(), + abilityReset = nfcCharacter.abilityReset.toInt(), + rank = nfcCharacter.abilityReset.toInt(), + itemType = nfcCharacter.itemType.toInt(), + itemMultiplier = nfcCharacter.itemMultiplier.toInt(), + itemRemainingTime = nfcCharacter.itemRemainingTime.toInt(), + otp0 = "", //nfcCharacter.value!!.otp0.toString(), + otp1 = "", //nfcCharacter.value!!.otp1.toString(), + minorVersion = nfcCharacter.characterCreationFirmwareVersion.minorVersion.toInt(), + majorVersion = nfcCharacter.characterCreationFirmwareVersion.majorVersion.toInt(), + ) + + storageRepository + .userCharacterDao() + .insertBECharacterData(extraCharacterData) + + val transformationHistoryWatch = nfcCharacter.transformationHistory + transformationHistoryWatch.map { item -> + if (item.toCharIndex.toInt() != 255) { + val date = GregorianCalendar(item.year.toInt(), item.month.toInt(), item.day.toInt()) + .time + .time + + storageRepository + .characterDao() + .insertTransformation(characterId, item.toCharIndex.toInt(), dimData.id, date) + + storageRepository + .dexDao() + .insertCharacter(item.toCharIndex.toInt(), dimData.id, date) + } + } + } else if (nfcCharacter is VBNfcCharacter) { + return "Not implemented yet" + } + + return "Done reading character!" } } \ No newline at end of file