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() {
private val onActivityLifecycleListeners = HashMap<String, ActivityLifecycleListener>()
private var initialRoute: String? = null
private fun registerActivityLifecycleListener(key: String, activityLifecycleListener: ActivityLifecycleListener) {
if( onActivityLifecycleListeners[key] != null) {
@ -62,6 +63,8 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
initialRoute = getInitialRouteFromIntent(intent)
setContent {
VBHelperTheme {
MainApplication(
@ -72,7 +75,8 @@ class MainActivity : ComponentActivity() {
homeScreenController = homeScreenController,
storageScreenController = storageScreenController,
spriteViewerController = spriteViewerController,
cardScreenController = cardScreenController
cardScreenController = cardScreenController,
initialRoute = initialRoute
)
}
}
@ -100,6 +104,8 @@ class MainActivity : ComponentActivity() {
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
initialRoute = getInitialRouteFromIntent(intent)
// Optionally, you may want to trigger navigation here if needed
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
private fun MainApplication(
scanScreenController: ScanScreenControllerImpl,
@ -158,7 +175,8 @@ class MainActivity : ComponentActivity() {
storageScreenController: StorageScreenControllerImpl,
homeScreenController: HomeScreenControllerImpl,
spriteViewerController: SpriteViewerControllerImpl,
cardScreenController: CardScreenControllerImpl
cardScreenController: CardScreenControllerImpl,
initialRoute: String? = null
) {
AppNavigation(
applicationNavigationHandlers = AppNavigationHandlers(
@ -170,7 +188,8 @@ class MainActivity : ComponentActivity() {
homeScreenController,
spriteViewerController,
cardScreenController
)
),
initialRoute = initialRoute
)
}

View File

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

View File

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

View File

@ -47,14 +47,22 @@ class ScanScreenControllerImpl(
override fun onClickRead(secrets: Secrets, onComplete: ()->Unit, onMultipleCards: (List<Card>) -> Unit) {
handleTag(secrets) { tagCommunicator ->
try {
val character = tagCommunicator.receiveCharacter()
val resultMessage = characterFromNfc(character) { cards, nfcCharacter ->
lastScannedCharacter = nfcCharacter
onMultipleCards(cards)
}
onComplete.invoke()
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 = "lightheel", description = stringResource(R.string.credits_lightheel_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,
onClickDelete: () -> Unit,
onSendToBracelet: () -> Unit,
onSendToVitalWear: () -> Unit,
onClickSetActive: () -> Unit,
onClickSendToAdventure: (time: Long) -> Unit
) {
@ -137,13 +136,6 @@ fun StorageDialog(
Text(text = stringResource(R.string.storage_set_active))
}
}
Button(
onClick = onSendToVitalWear,
modifier = Modifier
.fillMaxWidth()
) {
Text(text = stringResource(R.string.storage_send_to_vitalwear))
}
Button(
onClick = {
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 ->
adventureScreenController
.sendCharacterToAdventure(

View File

@ -48,8 +48,8 @@
</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_app_to_vb">App to Vital Bracelet (Send Digimon from VBHelper to 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">VBH to Watch</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>
@ -71,12 +71,12 @@
<string name="settings_import_apk_title">Import APK</string>
<string name="settings_import_apk_desc">
Import Secrets From Vital Arena 2.1.0 APK
Import Secrets From Vital Arena APK
</string>
<string name="settings_import_card_title">Import card</string>
<string name="settings_import_card_desc">
Import DiM/BEm card file
Import DiM/BEm
</string>
<string name="settings_credits_title">Credits</string>
@ -114,7 +114,9 @@
<string name="credits_shvstrz_description">
Designing the app icon in SVG.
</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_cancel">Cancel</string>
@ -194,7 +196,7 @@
<string name="card_entry_delete">Delete card</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_character_image_description">Character image</string>

File diff suppressed because one or more lines are too long