Initial commit of VBHelper

This commit is contained in:
Taveon Nelson 2026-04-18 17:19:34 -05:00
parent 5273bae7b6
commit e787ea4a19
9 changed files with 745 additions and 66 deletions

View File

@ -30,6 +30,7 @@ import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
private val onActivityLifecycleListeners = HashMap<String, ActivityLifecycleListener>() private val onActivityLifecycleListeners = HashMap<String, ActivityLifecycleListener>()
private var initialRoute: String? = null
private fun registerActivityLifecycleListener(key: String, activityLifecycleListener: ActivityLifecycleListener) { private fun registerActivityLifecycleListener(key: String, activityLifecycleListener: ActivityLifecycleListener) {
if( onActivityLifecycleListeners[key] != null) { if( onActivityLifecycleListeners[key] != null) {
@ -62,6 +63,8 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge() enableEdgeToEdge()
initialRoute = getInitialRouteFromIntent(intent)
setContent { setContent {
VBHelperTheme { VBHelperTheme {
MainApplication( MainApplication(
@ -72,7 +75,8 @@ class MainActivity : ComponentActivity() {
homeScreenController = homeScreenController, homeScreenController = homeScreenController,
storageScreenController = storageScreenController, storageScreenController = storageScreenController,
spriteViewerController = spriteViewerController, spriteViewerController = spriteViewerController,
cardScreenController = cardScreenController cardScreenController = cardScreenController,
initialRoute = initialRoute
) )
} }
} }
@ -100,6 +104,8 @@ class MainActivity : ComponentActivity() {
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent) super.onNewIntent(intent)
setIntent(intent) setIntent(intent)
initialRoute = getInitialRouteFromIntent(intent)
// Optionally, you may want to trigger navigation here if needed
handleImportIntent(intent) handleImportIntent(intent)
} }
@ -149,6 +155,17 @@ class MainActivity : ComponentActivity() {
} }
} }
private fun getInitialRouteFromIntent(intent: Intent?): String? {
if (intent == null) return null
val data = intent.data
if (intent.action == Intent.ACTION_VIEW && data != null) {
if (data.scheme == "vbhelper" && data.host == "auth") {
return "Battle"
}
}
return null
}
@Composable @Composable
private fun MainApplication( private fun MainApplication(
scanScreenController: ScanScreenControllerImpl, scanScreenController: ScanScreenControllerImpl,
@ -158,7 +175,8 @@ class MainActivity : ComponentActivity() {
storageScreenController: StorageScreenControllerImpl, storageScreenController: StorageScreenControllerImpl,
homeScreenController: HomeScreenControllerImpl, homeScreenController: HomeScreenControllerImpl,
spriteViewerController: SpriteViewerControllerImpl, spriteViewerController: SpriteViewerControllerImpl,
cardScreenController: CardScreenControllerImpl cardScreenController: CardScreenControllerImpl,
initialRoute: String? = null
) { ) {
AppNavigation( AppNavigation(
applicationNavigationHandlers = AppNavigationHandlers( applicationNavigationHandlers = AppNavigationHandlers(
@ -170,7 +188,8 @@ class MainActivity : ComponentActivity() {
homeScreenController, homeScreenController,
spriteViewerController, spriteViewerController,
cardScreenController cardScreenController
) ),
initialRoute = initialRoute
) )
} }

View File

@ -54,6 +54,7 @@ data class AppNavigationHandlers(
@Composable @Composable
fun AppNavigation( fun AppNavigation(
applicationNavigationHandlers: AppNavigationHandlers, applicationNavigationHandlers: AppNavigationHandlers,
initialRoute: String? = null
) { ) {
val navController = rememberNavController() val navController = rememberNavController()
@ -64,7 +65,7 @@ fun AppNavigation(
) { contentPadding -> ) { contentPadding ->
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = NavigationItems.Home.route, startDestination = initialRoute ?: NavigationItems.Home.route,
enterTransition = { enterTransition = {
fadeIn( fadeIn(
animationSpec = tween(200) animationSpec = tween(200)

View File

@ -30,12 +30,19 @@ fun BottomNavigationBar(navController: NavController) {
label = { Text(text = stringResource(item.label)) }, label = { Text(text = stringResource(item.label)) },
selected = currentRoute == item.route, selected = currentRoute == item.route,
onClick = { onClick = {
if (item == NavigationItems.Home) {
navController.navigate(NavigationItems.Home.route) {
popUpTo(0) { inclusive = false }
launchSingleTop = true
}
} else {
navController.navigate(item.route) { navController.navigate(item.route) {
popUpTo(navController.graph.startDestinationId) { saveState = true } popUpTo(navController.graph.startDestinationId) { saveState = true }
launchSingleTop = true launchSingleTop = true
restoreState = true restoreState = true
} }
} }
}
) )
} }
} }

View File

@ -47,14 +47,22 @@ class ScanScreenControllerImpl(
override fun onClickRead(secrets: Secrets, onComplete: ()->Unit, onMultipleCards: (List<Card>) -> Unit) { override fun onClickRead(secrets: Secrets, onComplete: ()->Unit, onMultipleCards: (List<Card>) -> Unit) {
handleTag(secrets) { tagCommunicator -> handleTag(secrets) { tagCommunicator ->
try {
val character = tagCommunicator.receiveCharacter() val character = tagCommunicator.receiveCharacter()
val resultMessage = characterFromNfc(character) { cards, nfcCharacter -> val resultMessage = characterFromNfc(character) { cards, nfcCharacter ->
lastScannedCharacter = nfcCharacter lastScannedCharacter = nfcCharacter
onMultipleCards(cards) onMultipleCards(cards)
} }
onComplete.invoke() onComplete.invoke()
resultMessage resultMessage
} catch (e: Exception) {
Log.e("NFC_READ", "Error reading character from NFC", e)
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_error_generic) + ": " + (e.message ?: e.javaClass.simpleName), Toast.LENGTH_LONG).show()
}
onComplete.invoke()
componentActivity.getString(R.string.scan_error_generic)
}
} }
} }

View File

@ -38,6 +38,8 @@ fun CreditsScreen(
SettingsEntry(title = "nacabaro", description = stringResource(R.string.credits_nacabaro_description)) { } SettingsEntry(title = "nacabaro", description = stringResource(R.string.credits_nacabaro_description)) { }
SettingsEntry(title = "lightheel", description = stringResource(R.string.credits_lightheel_description)) { } SettingsEntry(title = "lightheel", description = stringResource(R.string.credits_lightheel_description)) { }
SettingsEntry(title = "shvstrz", description = stringResource(R.string.credits_shvstrz_description)) { } SettingsEntry(title = "shvstrz", description = stringResource(R.string.credits_shvstrz_description)) { }
SettingsEntry(title = "redeyez", description = stringResource(R.string.credits_RedEyez_description)) { }
} }
} }
} }

View File

@ -43,7 +43,6 @@ fun StorageDialog(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
onClickDelete: () -> Unit, onClickDelete: () -> Unit,
onSendToBracelet: () -> Unit, onSendToBracelet: () -> Unit,
onSendToVitalWear: () -> Unit,
onClickSetActive: () -> Unit, onClickSetActive: () -> Unit,
onClickSendToAdventure: (time: Long) -> Unit onClickSendToAdventure: (time: Long) -> Unit
) { ) {
@ -137,13 +136,6 @@ fun StorageDialog(
Text(text = stringResource(R.string.storage_set_active)) Text(text = stringResource(R.string.storage_set_active))
} }
} }
Button(
onClick = onSendToVitalWear,
modifier = Modifier
.fillMaxWidth()
) {
Text(text = stringResource(R.string.storage_send_to_vitalwear))
}
Button( Button(
onClick = { onClick = {
onSendToAdventureClicked = true onSendToAdventureClicked = true

View File

@ -137,21 +137,6 @@ fun StorageScreen(
) )
) )
}, },
onSendToVitalWear = {
try {
val intent = VitalWearCharacterExporter(application, application.container.db)
.buildShareIntent(selectedCharacter!!)
.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
application.startActivity(intent)
selectedCharacter = null
} catch (e: Exception) {
Toast.makeText(
application,
"Could not send character to VitalWear: ${e.message}",
Toast.LENGTH_LONG
).show()
}
},
onClickSendToAdventure = { time -> onClickSendToAdventure = { time ->
adventureScreenController adventureScreenController
.sendCharacterToAdventure( .sendCharacterToAdventure(

View File

@ -48,8 +48,8 @@
</string> </string>
<string name="scan_title">Scan a Vital Bracelet</string> <string name="scan_title">Scan a Vital Bracelet</string>
<string name="scan_vb_to_app">Vital Bracelet to App (Receive Digimon from Bandai Toys: Vital Bracelet, Vital Hero, BE Bracelet)</string> <string name="scan_vb_to_app">Watch to VBH</string>
<string name="scan_app_to_vb">App to Vital Bracelet (Send Digimon from VBHelper to Bandai Toys: Vital Bracelet, Vital Hero, BE Bracelet)</string> <string name="scan_app_to_vb">VBH to Watch</string>
<string name="scan_no_nfc_on_device">No NFC on device!</string> <string name="scan_no_nfc_on_device">No NFC on device!</string>
<string name="scan_tag_not_vb">Tag detected is not VB</string> <string name="scan_tag_not_vb">Tag detected is not VB</string>
@ -71,12 +71,12 @@
<string name="settings_import_apk_title">Import APK</string> <string name="settings_import_apk_title">Import APK</string>
<string name="settings_import_apk_desc"> <string name="settings_import_apk_desc">
Import Secrets From Vital Arena 2.1.0 APK Import Secrets From Vital Arena APK
</string> </string>
<string name="settings_import_card_title">Import card</string> <string name="settings_import_card_title">Import card</string>
<string name="settings_import_card_desc"> <string name="settings_import_card_desc">
Import DiM/BEm card file Import DiM/BEm
</string> </string>
<string name="settings_credits_title">Credits</string> <string name="settings_credits_title">Credits</string>
@ -114,7 +114,9 @@
<string name="credits_shvstrz_description"> <string name="credits_shvstrz_description">
Designing the app icon in SVG. Designing the app icon in SVG.
</string> </string>
<string name="credits_RedEyez_description">
Devout Debugger.
</string>
<string name="action_place_near_reader">Place your Vital Bracelet near the reader...</string> <string name="action_place_near_reader">Place your Vital Bracelet near the reader...</string>
<string name="action_cancel">Cancel</string> <string name="action_cancel">Cancel</string>
@ -194,7 +196,7 @@
<string name="card_entry_delete">Delete card</string> <string name="card_entry_delete">Delete card</string>
<string name="storage_my_characters_title">My characters</string> <string name="storage_my_characters_title">My characters</string>
<string name="storage_nothing_to_see_here">Nothing to see here</string> <string name="storage_nothing_to_see_here">Storage is Empty</string>
<string name="storage_in_adventure_toast">This character is in an adventure</string> <string name="storage_in_adventure_toast">This character is in an adventure</string>
<string name="storage_character_image_description">Character image</string> <string name="storage_character_image_description">Character image</string>

File diff suppressed because one or more lines are too long