Compare commits

...

3 Commits

Author SHA1 Message Date
6cce33c5f6
Merge pull request #44 from jeffersoncarlospedroso/feature/add-multilanguage-support
Add multilanguage support (i18n) initial implementation
2025-12-14 12:31:27 +01:00
jeffersoncarlospedroso
16fbfae0c2 feat(i18n): continue translation work 2025-12-11 22:38:43 +00:00
jeffersoncarlospedroso
0d174f1550 Add multilanguage support (i18n) initial implementation 2025-12-10 23:06:37 +00:00
35 changed files with 852 additions and 165 deletions

View File

@ -36,6 +36,8 @@ import com.github.cfogrady.vbnfc.vb.SpecialMission
import com.github.nacabaro.vbhelper.R
import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions
import com.github.nacabaro.vbhelper.utils.getObscuredBitmap
import androidx.compose.ui.res.stringResource
@Composable
fun CharacterEntry(
@ -134,11 +136,23 @@ fun SpecialMissionsEntry(
onClickCard: () -> Unit = { },
) {
val textValue = when (specialMission.missionType) {
SpecialMission.Type.NONE -> "No mission selected"
SpecialMission.Type.STEPS -> "Walk ${specialMission.goal} steps"
SpecialMission.Type.BATTLES -> "Battle ${specialMission.goal} times"
SpecialMission.Type.WINS -> "Win ${specialMission.goal} battles"
SpecialMission.Type.VITALS -> "Earn ${specialMission.goal} vitals"
SpecialMission.Type.NONE -> stringResource(R.string.special_mission_none)
SpecialMission.Type.STEPS -> stringResource(
R.string.special_mission_steps,
specialMission.goal
)
SpecialMission.Type.BATTLES -> stringResource(
R.string.special_mission_battles,
specialMission.goal
)
SpecialMission.Type.WINS -> stringResource(
R.string.special_mission_wins,
specialMission.goal
)
SpecialMission.Type.VITALS -> stringResource(
R.string.special_mission_vitals,
specialMission.goal
)
}
val progress = if (specialMission.status == SpecialMission.Status.COMPLETED) {
@ -149,10 +163,22 @@ fun SpecialMissionsEntry(
val completion = when (specialMission.missionType) {
SpecialMission.Type.NONE -> ""
SpecialMission.Type.STEPS -> "Walked $progress steps"
SpecialMission.Type.BATTLES -> "Battled $progress times"
SpecialMission.Type.WINS -> "Won $progress battles"
SpecialMission.Type.VITALS -> "Earned $progress vitals"
SpecialMission.Type.STEPS -> stringResource(
R.string.special_mission_steps_progress,
progress
)
SpecialMission.Type.BATTLES -> stringResource(
R.string.special_mission_battles_progress,
progress
)
SpecialMission.Type.WINS -> stringResource(
R.string.special_mission_wins_progress,
progress
)
SpecialMission.Type.VITALS -> stringResource(
R.string.special_mission_vitals_progress,
progress
)
}
val icon = when (specialMission.missionType) {
@ -193,7 +219,7 @@ fun SpecialMissionsEntry(
) {
Icon(
painter = painterResource(icon),
contentDescription = "Vitals",
contentDescription = stringResource(R.string.special_mission_icon_content_description),
modifier = Modifier
.fillMaxHeight()
.padding(16.dp)

View File

@ -8,7 +8,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.res.painterResource
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.compose.ui.res.stringResource
@Composable
fun BottomNavigationBar(navController: NavController) {
@ -26,8 +26,8 @@ fun BottomNavigationBar(navController: NavController) {
items.forEach { item ->
NavigationBarItem (
icon = { Icon(painter = painterResource(item.icon), contentDescription = item.label) },
label = { Text(item.label) },
icon = { Icon(painter = painterResource(item.icon), contentDescription = stringResource(item.label)) },
label = { Text(text = stringResource(item.label)) },
selected = currentRoute == item.route,
onClick = {
navController.navigate(item.route) {

View File

@ -1,25 +1,101 @@
package com.github.nacabaro.vbhelper.navigation
import com.github.nacabaro.vbhelper.R
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
sealed class NavigationItems (
var route: String,
var icon: Int,
var label: String
sealed class NavigationItems(
val route: String,
@DrawableRes val icon: Int,
@StringRes val label: Int
) {
object Scan : NavigationItems("Scan/{characterId}", R.drawable.baseline_nfc_24, "Scan")
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")
object CardView : NavigationItems("Card/{cardId}", R.drawable.baseline_image_24, "Card")
object Items : NavigationItems("Items", R.drawable.baseline_data_24, "Items")
object MyItems : NavigationItems("MyItems", R.drawable.baseline_data_24, "My items")
object ItemsStore : NavigationItems("ItemsStore", R.drawable.baseline_data_24, "Items store")
object ApplyItem : NavigationItems("ApplyItem/{itemId}", R.drawable.baseline_data_24, "Apply item")
object Adventure : NavigationItems("Adventure", R.drawable.baseline_fort_24, "Adventure")
object Credits : NavigationItems("Credits", R.drawable.baseline_data_24, "Credits")
object Scan : NavigationItems(
"Scan/{characterId}",
R.drawable.baseline_nfc_24,
R.string.nav_scan
)
object Battles : NavigationItems(
"Battle",
R.drawable.baseline_swords_24,
R.string.nav_battle
)
object Home : NavigationItems(
"Home",
R.drawable.baseline_cottage_24,
R.string.nav_home
)
object Dex : NavigationItems(
"Dex",
R.drawable.baseline_menu_book_24,
R.string.nav_dex
)
object CardAdventure : NavigationItems(
"CardAdventure/{cardId}",
R.drawable.baseline_fort_24,
R.string.nav_card_adventure
)
object Storage : NavigationItems(
"Storage",
R.drawable.baseline_catching_pokemon_24,
R.string.nav_storage
)
object Settings : NavigationItems(
"Settings",
R.drawable.baseline_settings_24,
R.string.nav_settings
)
object Viewer : NavigationItems(
"Viewer",
R.drawable.baseline_image_24,
R.string.nav_viewer
)
object CardView : NavigationItems(
"Card/{cardId}",
R.drawable.baseline_image_24,
R.string.nav_card
)
object Items : NavigationItems(
"Items",
R.drawable.baseline_data_24,
R.string.nav_items
)
object MyItems : NavigationItems(
"MyItems",
R.drawable.baseline_data_24,
R.string.nav_my_items
)
object ItemsStore : NavigationItems(
"ItemsStore",
R.drawable.baseline_data_24,
R.string.nav_items_store
)
object ApplyItem : NavigationItems(
"ApplyItem/{itemId}",
R.drawable.baseline_data_24,
R.string.nav_apply_item
)
object Adventure : NavigationItems(
"Adventure",
R.drawable.baseline_fort_24,
R.string.nav_adventure
)
object Credits : NavigationItems(
"Credits",
R.drawable.baseline_data_24,
R.string.nav_credits
)
}

View File

@ -10,13 +10,16 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.github.nacabaro.vbhelper.components.TopBanner
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun BattlesScreen() {
Scaffold (
topBar = {
TopBanner(
text = "Online battles"
text = stringResource(R.string.battles_online_title)
)
}
) { contentPadding ->
@ -27,7 +30,7 @@ fun BattlesScreen() {
.padding(top = contentPadding.calculateTopPadding())
.fillMaxSize()
) {
Text("Coming soon")
Text(stringResource(R.string.battles_coming_soon))
}
}
}

View File

@ -18,6 +18,7 @@ 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.res.stringResource
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.screens.itemsScreen.ObtainedItemDialog
import com.github.nacabaro.vbhelper.components.TopBanner
@ -29,6 +30,7 @@ import com.github.nacabaro.vbhelper.source.StorageRepository
import com.github.nacabaro.vbhelper.utils.BitmapData
import kotlinx.coroutines.delay
import java.time.Instant
import com.github.nacabaro.vbhelper.R
@Composable
fun AdventureScreen(
@ -61,7 +63,7 @@ fun AdventureScreen(
Scaffold(
topBar = {
TopBanner(
text = "Adventure",
text = stringResource(R.string.adventure_title),
onBackClick = {
navController.popBackStack()
}
@ -76,7 +78,7 @@ fun AdventureScreen(
.padding(top = contentPadding.calculateTopPadding())
.fillMaxSize()
) {
Text(text = "Nothing to see here")
Text(text = stringResource(R.string.adventure_empty_state))
}
} else {
LazyColumn(

View File

@ -11,6 +11,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun CardAdventureScreen(
@ -28,7 +31,7 @@ fun CardAdventureScreen(
Scaffold (
topBar = {
TopBanner(
text = "Adventure missions",
text = stringResource(R.string.card_adventure_missions_title),
onBackClick = {
navController.popBackStack()
}

View File

@ -24,6 +24,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.utils.getBitmap
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun CardEntry(
@ -75,7 +78,11 @@ fun CardEntry(
modifier = Modifier
)
Text(
text = "$obtainedCharacters of $totalCharacters characters obtained",
text = stringResource(
R.string.card_entry_characters_obtained,
obtainedCharacters,
totalCharacters
),
fontFamily = MaterialTheme.typography.labelSmall.fontFamily,
fontSize = MaterialTheme.typography.labelSmall.fontSize,
modifier = Modifier
@ -91,7 +98,7 @@ fun CardEntry(
) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = "Edit"
contentDescription = stringResource(R.string.card_entry_edit)
)
}
IconButton(
@ -99,7 +106,7 @@ fun CardEntry(
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Delete"
contentDescription = stringResource(R.string.card_entry_delete)
)
}
}

View File

@ -10,6 +10,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.components.CharacterEntry
@ -19,6 +20,8 @@ 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 com.github.nacabaro.vbhelper.R
@Composable
fun CardViewScreen(
@ -35,7 +38,7 @@ fun CardViewScreen(
Scaffold (
topBar = {
TopBanner(
text = "Discovered characters",
text = stringResource(R.string.card_view_discovered_characters),
onBackClick = {
navController.popBackStack()
},

View File

@ -24,6 +24,8 @@ 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 androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun CardsScreen(
@ -43,7 +45,7 @@ fun CardsScreen(
Scaffold (
topBar = {
TopBanner(
text = "My cards",
text = stringResource(R.string.cards_my_cards_title),
onModifyClick = {
modifyCards = !modifyCards
}

View File

@ -33,7 +33,8 @@ 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
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun DexCharaDetailsDialog(
@ -119,7 +120,7 @@ fun DexCharaDetailsDialog(
) {
Image(
bitmap = charaImageBitmapData.imageBitmap,
contentDescription = "Icon",
contentDescription = stringResource(R.string.dex_chara_icon_description),
modifier = Modifier
.size(charaImageBitmapData.dpWidth)
.padding(8.dp),
@ -138,7 +139,7 @@ fun DexCharaDetailsDialog(
Column {
Image(
bitmap = nameImageBitmapData.imageBitmap,
contentDescription = "Icon",
contentDescription = stringResource(R.string.dex_chara_name_icon_description),
modifier = Modifier
.width(nameImageBitmapData.dpWidth)
.height(nameImageBitmapData.dpHeight),
@ -147,17 +148,28 @@ fun DexCharaDetailsDialog(
Spacer(modifier = Modifier.padding(4.dp))
if (currentChara.baseHp != 65535) {
Text(
text = "HP: ${currentChara.baseHp}, BP: ${currentChara.baseBp}, AP: ${currentChara.baseAp}"
text = stringResource(
R.string.dex_chara_stats,
currentChara.baseHp,
currentChara.baseBp,
currentChara.baseAp
)
)
Text(
text = stringResource(
R.string.dex_chara_stage_attribute,
romanNumeralsStage,
currentChara.attribute.toString().substring(0, 2)
)
)
Text(text = "Stg: ${romanNumeralsStage}, Atr: ${currentChara.attribute.toString().substring(0, 2)}")
}
}
} else {
Column {
Text(text = "????????????????")
Text(stringResource(R.string.dex_chara_unknown_name))
Spacer(modifier = Modifier.padding(4.dp))
Text(text = "Stg: -, Atr: -")
Text(text = "HP: -, BP: -, AP: -")
Text(stringResource(R.string.dex_chara_stage_attribute_unknown))
Text(stringResource(R.string.dex_chara_stats_unknown))
}
}
}
@ -198,7 +210,7 @@ fun DexCharaDetailsDialog(
) {
Image(
bitmap = selectedCharaImageBitmap.imageBitmap,
contentDescription = "Icon",
contentDescription = stringResource(R.string.dex_chara_icon_description),
modifier = Modifier
.size(selectedCharaImageBitmap.dpWidth)
.padding(8.dp),
@ -214,8 +226,22 @@ fun DexCharaDetailsDialog(
.padding(16.dp)
)
Column {
Text("Tr: ${it.requiredTrophies}; Bt: ${it.requiredBattles}; Vr: ${it.requiredVitals}; Wr: ${it.requiredWinRate}%; Ct: ${it.changeTimerHours}h")
Text("AdvLvl ${it.requiredAdventureLevelCompleted + 1}")
Text(
text = stringResource(
R.string.dex_chara_requirements,
it.requiredTrophies,
it.requiredBattles,
it.requiredVitals,
it.requiredWinRate,
it.changeTimerHours
)
)
Text(
text = stringResource(
R.string.dex_chara_adventure_level,
it.requiredAdventureLevelCompleted + 1
)
)
}
}
}
@ -229,7 +255,7 @@ fun DexCharaDetailsDialog(
showFusions = true
}
) {
Text("Fusions")
Text(stringResource(R.string.dex_chara_fusions_button))
}
}
@ -241,7 +267,7 @@ fun DexCharaDetailsDialog(
Button(
onClick = onClickClose
) {
Text("Close")
Text(stringResource(R.string.dex_chara_close_button))
}
}
}

View File

@ -8,8 +8,10 @@ import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.github.nacabaro.vbhelper.R
@Composable
fun BetaWarning(
@ -19,26 +21,26 @@ fun BetaWarning(
onDismissRequest = onDismissRequest
) {
Card {
Column (
Column(
modifier = Modifier
.padding(16.dp)
) {
Text(
text = "This application is currently in alpha and it is not complete. Do not use to store important characters for you, as any future updates might delete all your characters. Sorry for the inconvenience!"
text = stringResource(R.string.beta_warning_message_main)
)
Spacer(modifier = Modifier.padding(8.dp))
Text(
text = "Application should work now with the original VB and the VH."
text = stringResource(R.string.beta_warning_message_compatibility)
)
Spacer(modifier = Modifier.padding(8.dp))
Text(
text = "Thank you for your understanding and patience. Sincerely, the dev team."
text = stringResource(R.string.beta_warning_message_thanks)
)
Spacer(modifier = Modifier.padding(8.dp))
Button(
onClick = onDismissRequest
) {
Text(text = "Dismiss")
Text(text = stringResource(R.string.beta_warning_button_dismiss))
}
}
}

View File

@ -19,6 +19,7 @@ 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.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@ -39,6 +40,7 @@ import com.github.nacabaro.vbhelper.screens.itemsScreen.ObtainedItemDialog
import com.github.nacabaro.vbhelper.source.StorageRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.github.nacabaro.vbhelper.R
@Composable
fun HomeScreen(
@ -81,7 +83,7 @@ fun HomeScreen(
Scaffold (
topBar = {
TopBanner(
text = "VB Helper",
text = stringResource(R.string.home_title),
onScanClick = {
navController.navigate(NavigationItems.Scan.route)
},
@ -99,7 +101,7 @@ fun HomeScreen(
.fillMaxSize()
.padding(top = contentPadding.calculateTopPadding())
) {
Text(text = "Nothing to see here")
Text(text = stringResource(R.string.adventure_empty_state))
}
} else {
if (activeMon.value!!.isBemCard) {
@ -154,7 +156,7 @@ fun HomeScreen(
.padding(16.dp)
) {
Text(
text = "One of your characters has finished their adventure mission!",
text = stringResource(R.string.home_adventure_mission_finished),
textAlign = TextAlign.Center
)
Button(
@ -165,7 +167,7 @@ fun HomeScreen(
.padding(8.dp)
.fillMaxWidth()
) {
Text(text = "Dismiss")
Text(text = stringResource(R.string.beta_warning_button_dismiss))
}
}
}

View File

@ -25,6 +25,8 @@ import com.github.nacabaro.vbhelper.dtos.ItemDtos
import com.github.nacabaro.vbhelper.screens.homeScreens.HomeScreenControllerImpl
import com.github.nacabaro.vbhelper.utils.BitmapData
import java.util.Locale
import androidx.compose.ui.res.stringResource
@Composable
fun VBDiMHomeScreen(
@ -65,7 +67,7 @@ fun VBDiMHomeScreen(
ItemDisplay(
icon = R.drawable.baseline_vitals_24,
textValue = activeMon.vitalPoints.toString(),
definition = "Vitals",
definition = stringResource(R.string.home_vbdim_vitals),
modifier = Modifier
.weight(0.5f)
.aspectRatio(1f)
@ -74,7 +76,7 @@ fun VBDiMHomeScreen(
ItemDisplay(
icon = R.drawable.baseline_trophy_24,
textValue = activeMon.trophies.toString(),
definition = "Trophies",
definition = stringResource(R.string.home_vbdim_trophies),
modifier = Modifier
.weight(0.5f)
.aspectRatio(1f)
@ -89,7 +91,7 @@ fun VBDiMHomeScreen(
ItemDisplay(
icon = R.drawable.baseline_mood_24,
textValue = activeMon.mood.toString(),
definition = "Mood",
definition = stringResource(R.string.home_vbdim_mood),
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
@ -102,7 +104,7 @@ fun VBDiMHomeScreen(
0 -> "${activeMon.transformationCountdown} m"
else -> "$transformationCountdownInHours h"
},
definition = "Next timer",
definition = stringResource(R.string.home_vbdim_next_timer),
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
@ -122,7 +124,7 @@ fun VBDiMHomeScreen(
) + " %" // Specify locale
}
},
definition = "Total battle win %",
definition = stringResource(R.string.home_vbdim_total_battle_win),
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
@ -142,7 +144,7 @@ fun VBDiMHomeScreen(
) + " %" // Specify locale
}
},
definition = "Current phase win %",
definition = stringResource(R.string.home_vbdim_current_phase_win),
modifier = Modifier
.weight(1f)
.aspectRatio(1f)
@ -165,7 +167,7 @@ fun VBDiMHomeScreen(
.padding(16.dp)
) {
Text(
text = "Special missions",
text = stringResource(R.string.home_vbdim_special_missions),
fontSize = 24.sp
)
}

View File

@ -15,6 +15,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.CharacterEntry
import com.github.nacabaro.vbhelper.components.TopBanner
@ -26,7 +27,7 @@ import com.github.nacabaro.vbhelper.source.StorageRepository
import com.github.nacabaro.vbhelper.utils.BitmapData
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import com.github.nacabaro.vbhelper.R
@Composable
fun ChooseCharacterScreen(
@ -69,7 +70,7 @@ fun ChooseCharacterScreen(
itemsScreenController.applyItem(itemId, selectedCharacter!!) {
Toast.makeText(
application.applicationContext,
"Item applied!",
application.getString(R.string.choose_character_item_applied),
Toast.LENGTH_SHORT
).show()
navController.popBackStack()
@ -80,7 +81,7 @@ fun ChooseCharacterScreen(
Scaffold(
topBar = {
TopBanner(
text = "Choose character",
text = stringResource(R.string.choose_character_title),
onBackClick = {
navController.popBackStack()
}

View File

@ -17,6 +17,7 @@ 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.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -27,6 +28,8 @@ 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,
@ -95,7 +98,10 @@ fun ItemDialog(
textAlign = TextAlign.Center,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
text = "Costs ${item.price} credits",
text = stringResource(
R.string.item_dialog_costs_credits,
item.price
),
modifier = Modifier
.fillMaxWidth()
)
@ -104,7 +110,10 @@ fun ItemDialog(
textAlign = TextAlign.Center,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
text = "You have ${item.quantity} of this item",
text = stringResource(
R.string.item_dialog_you_have_quantity,
item.quantity
),
modifier = Modifier
.fillMaxWidth()
)
@ -118,7 +127,7 @@ fun ItemDialog(
Button(
onClick = onClickUse
) {
Text("Use item")
Text(stringResource(R.string.item_dialog_use))
}
}
@ -126,7 +135,7 @@ fun ItemDialog(
Button(
onClick = onClickPurchase
) {
Text("Purchase")
Text(stringResource(R.string.item_dialog_purchase))
}
}
@ -134,7 +143,7 @@ fun ItemDialog(
Button(
onClick = onClickCancel
) {
Text("Cancel")
Text(stringResource(R.string.item_dialog_cancel))
}
}
}

View File

@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.dtos.ItemDtos
import com.github.nacabaro.vbhelper.R
@Composable
fun ItemElement(

View File

@ -17,6 +17,9 @@ import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun ItemsScreen(
@ -30,14 +33,14 @@ fun ItemsScreen(
Scaffold(
topBar = {
Column {
TopBanner("Items")
TopBanner(text = stringResource(R.string.items_title))
TabRow(
selectedTabIndex = selectedTabItem,
modifier = Modifier
) {
items.forEachIndexed { index, item ->
Tab(
text = { Text(item.label) },
text = { Text(text = stringResource(item.label)) },
selected = selectedTabItem == index,
onClick = { selectedTabItem = index }
)

View File

@ -21,6 +21,7 @@ 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.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.database.AppDatabase
@ -30,6 +31,7 @@ import com.github.nacabaro.vbhelper.source.CurrencyRepository
import com.github.nacabaro.vbhelper.source.ItemsRepository
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import com.github.nacabaro.vbhelper.R
@Composable
fun ItemsStore(
@ -52,7 +54,7 @@ fun ItemsStore(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text("No items")
Text(stringResource(R.string.items_no_items))
}
} else {
Column() {
@ -62,7 +64,10 @@ fun ItemsStore(
.fillMaxWidth()
) {
Text(
text = "${currentCurrency.value} credits",
text = stringResource(
R.string.items_store_credits,
currentCurrency.value
),
modifier = Modifier
.padding(8.dp)
)
@ -94,14 +99,15 @@ fun ItemsStore(
scope.launch {
Toast.makeText(
application.applicationContext,
purchaseItem(
application.container.db,
myItems[selectedElementIndex!!],
currencyRepository
application.getString(
purchaseItem(
application.container.db,
myItems[selectedElementIndex!!],
currencyRepository
)
),
Toast.LENGTH_SHORT
).show(
)
).show()
}
},
onClickCancel = { selectedElementIndex = null }
@ -113,9 +119,9 @@ suspend fun purchaseItem(
db: AppDatabase,
item: ItemDtos.ItemsWithQuantities,
currencyRepository: CurrencyRepository
): String {
if (currencyRepository.currencyValue.first() < item.price) {
return "Not enough credits"
): Int {
return if (currencyRepository.currencyValue.first() < item.price) {
R.string.items_not_enough_credits
} else {
db
.itemDao()
@ -129,6 +135,6 @@ suspend fun purchaseItem(
currencyRepository.currencyValue.first() - item.price
)
return "Purchase successful!"
R.string.items_purchase_success
}
}

View File

@ -17,11 +17,14 @@ 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.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.source.ItemsRepository
import com.github.nacabaro.vbhelper.R
@Composable
fun MyItems(
@ -39,7 +42,7 @@ fun MyItems(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text("No items")
Text(stringResource(R.string.items_no_items))
}
} else {
LazyVerticalGrid(

View File

@ -19,6 +19,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.github.nacabaro.vbhelper.dtos.ItemDtos
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun ObtainedItemDialog(
@ -82,7 +84,10 @@ fun ObtainedItemDialog(
textAlign = TextAlign.Center,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
text = "You have obtained ${obtainedItem.itemAmount} of this item",
text = stringResource(
R.string.obtained_item_you_have,
obtainedItem.itemAmount
),
modifier = Modifier
.fillMaxWidth()
.padding(top = 4.dp)
@ -91,7 +96,10 @@ fun ObtainedItemDialog(
textAlign = TextAlign.Center,
fontSize = MaterialTheme.typography.bodySmall.fontSize,
fontFamily = MaterialTheme.typography.bodySmall.fontFamily,
text = "You also got $obtainedCurrency credits",
text = stringResource(
R.string.obtained_item_you_also_got_credits,
obtainedCurrency
),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 4.dp)
@ -101,7 +109,7 @@ fun ObtainedItemDialog(
modifier = Modifier
.fillMaxWidth()
) {
Text(text = "Dismiss")
Text(text = stringResource(R.string.obtained_item_dismiss))
}
}
}

View File

@ -12,10 +12,12 @@ 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.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.R
@Composable
fun ChooseConnectOption(
@ -26,7 +28,7 @@ fun ChooseConnectOption(
Scaffold(
topBar = {
TopBanner(
text = "Scan a Vital Bracelet",
text = stringResource(R.string.scan_title),
onBackClick = {
navController.popBackStack()
}
@ -41,13 +43,13 @@ fun ChooseConnectOption(
.padding(contentPadding)
) {
ScanButton(
text = "Vital Bracelet to App",
text = stringResource(R.string.scan_vb_to_app),
disabled = onClickRead == null,
onClick = onClickRead?: { },
)
Spacer(modifier = Modifier.height(16.dp))
ScanButton(
text = "App to Vital Bracelet",
text = stringResource(R.string.scan_app_to_vb),
disabled = onClickWrite == null,
onClick = onClickWrite?: { },
)

View File

@ -25,6 +25,7 @@ import com.github.nacabaro.vbhelper.source.proto.Secrets
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withContext
import com.github.nacabaro.vbhelper.R
const val SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER = "SCAN_SCREEN_ACTIVITY_LIFECYCLE_LISTENER"
@ -93,9 +94,9 @@ fun ScanScreen(
else -> {
{
if(secrets == null) {
Toast.makeText(context, "Secrets is not yet initialized. Try again.", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.scan_secrets_not_initialized), Toast.LENGTH_SHORT).show()
} else if(secrets?.isMissingSecrets() == true) {
Toast.makeText(context, "Secrets not yet imported. Go to Settings and Import APK", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.scan_secrets_not_imported), Toast.LENGTH_SHORT).show()
} else {
readingScreen = true // kicks off nfc adapter in DisposableEffect
}
@ -107,9 +108,9 @@ fun ScanScreen(
else -> {
{
if(secrets == null) {
Toast.makeText(context, "Secrets is not yet initialized. Try again.", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.scan_secrets_not_initialized), Toast.LENGTH_SHORT).show()
} else if(secrets?.isMissingSecrets() == true) {
Toast.makeText(context, "Secrets not yet imported. Go to Settings and Import APK", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.scan_secrets_not_imported), Toast.LENGTH_SHORT).show()
} else {
writingScreen = true // kicks off nfc adapter in DisposableEffect
}

View File

@ -25,6 +25,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import com.github.nacabaro.vbhelper.R
class ScanScreenControllerImpl(
override val secretsFlow: Flow<Secrets>,
@ -38,7 +39,7 @@ class ScanScreenControllerImpl(
init {
val maybeNfcAdapter = NfcAdapter.getDefaultAdapter(componentActivity)
if (maybeNfcAdapter == null) {
Toast.makeText(componentActivity, "No NFC on device!", Toast.LENGTH_SHORT).show()
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_no_nfc_on_device), Toast.LENGTH_SHORT).show()
}
nfcAdapter = maybeNfcAdapter
checkSecrets()
@ -94,7 +95,7 @@ class ScanScreenControllerImpl(
val nfcData = NfcA.get(tag)
if (nfcData == null) {
componentActivity.runOnUiThread {
Toast.makeText(componentActivity, "Tag detected is not VB", Toast.LENGTH_SHORT).show()
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_tag_not_vb), Toast.LENGTH_SHORT).show()
}
}
nfcData.connect()
@ -112,7 +113,7 @@ class ScanScreenControllerImpl(
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()
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_missing_secrets), Toast.LENGTH_SHORT).show()
}
}
}
@ -135,10 +136,10 @@ class ScanScreenControllerImpl(
tagCommunicator.sendCharacter(castNfcCharacter)
}
onComplete.invoke()
"Sent character successfully!"
componentActivity.getString(R.string.scan_sent_character_success)
} catch (e: Throwable) {
Log.e("TAG", e.stackTraceToString())
"Whoops"
componentActivity.getString(R.string.scan_error_generic)
}
}
}
@ -151,13 +152,13 @@ class ScanScreenControllerImpl(
handleTag(secrets) { tagCommunicator ->
tagCommunicator.prepareDIMForCharacter(nfcCharacter.dimId)
onComplete.invoke()
"Sent DIM successfully!"
componentActivity.getString(R.string.scan_sent_dim_success)
}
}
// EXTRACTED DIRECTLY FROM EXAMPLE APP
private fun showWirelessSettings() {
Toast.makeText(componentActivity, "NFC must be enabled", Toast.LENGTH_SHORT).show()
Toast.makeText(componentActivity, componentActivity.getString(R.string.scan_nfc_must_be_enabled), Toast.LENGTH_SHORT).show()
componentActivity.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
}

View File

@ -10,8 +10,10 @@ 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.stringResource
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.R
@Composable
fun ActionScreen(
@ -33,12 +35,12 @@ fun ActionScreen(
.padding(innerPadding)
.fillMaxSize()
) {
Text("Place your Vital Bracelet near the reader...")
Text(stringResource(R.string.action_place_near_reader))
Button(
onClick = onClickCancel,
modifier = Modifier.padding(16.dp)
) {
Text("Cancel")
Text(stringResource(R.string.action_cancel))
}
}
}

View File

@ -11,9 +11,11 @@ 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.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.R
@Composable
fun ReadCharacterScreen(
@ -23,7 +25,7 @@ fun ReadCharacterScreen(
Scaffold(
topBar = {
TopBanner(
text = "Read character",
text = stringResource(R.string.read_character_title),
onBackClick = onClickCancel
)
}
@ -36,12 +38,12 @@ fun ReadCharacterScreen(
.fillMaxSize()
) {
Text(
text = "Prepare your device!",
text = stringResource(R.string.read_character_prepare_device),
textAlign = TextAlign.Center
)
Text(
text = "Go to connect and when ready press confirm!",
text = stringResource(R.string.read_character_go_to_connect),
textAlign = TextAlign.Center
)
@ -52,7 +54,7 @@ fun ReadCharacterScreen(
Button(
onClick = onClickConfirm,
) {
Text("Confirm")
Text(stringResource(R.string.read_character_confirm))
}
}
}

View File

@ -7,11 +7,14 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
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
import com.github.nacabaro.vbhelper.R
@Composable
fun ReadingScreen(
@ -92,7 +95,7 @@ fun ReadingScreen(
}
if (readingScreen) {
ActionScreen("Reading character") {
ActionScreen(topBannerText = stringResource(R.string.reading_character_title),) {
readingScreen = false
scanScreenController.cancelRead()
onCancel()

View File

@ -24,6 +24,7 @@ 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.res.stringResource
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
@ -31,6 +32,7 @@ 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
import com.github.nacabaro.vbhelper.R
@Composable
fun WriteCardScreen(
@ -55,7 +57,7 @@ fun WriteCardScreen(
Scaffold(
topBar = {
TopBanner(
text = "Writing card details",
text = stringResource(R.string.write_card_title),
onBackClick = onClickCancel
)
}
@ -101,7 +103,9 @@ fun WriteCardScreen(
) {
Image(
bitmap = charaImageBitmapData.imageBitmap,
contentDescription = "Icon",
contentDescription = stringResource(
R.string.write_card_icon_description
),
modifier = Modifier
.size(charaImageBitmapData.dpWidth)
.padding(8.dp),
@ -115,8 +119,14 @@ fun WriteCardScreen(
)
Column {
Text("Get your device Ready!")
Text("You will need ${cardDetails.name} card!")
Text(stringResource(R.string.write_card_device_ready))
Text(
stringResource(
R.string.write_card_required_card,
cardDetails.name
)
)
}
}
@ -125,7 +135,7 @@ fun WriteCardScreen(
Button(
onClick = onClickConfirm,
) {
Text("Confirm")
Text(stringResource(R.string.write_card_confirm))
}
}
}

View File

@ -25,6 +25,7 @@ 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.res.stringResource
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
@ -32,6 +33,8 @@ 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
import com.github.nacabaro.vbhelper.R
@Composable
fun WriteCharacterScreen(
@ -56,7 +59,7 @@ fun WriteCharacterScreen(
Scaffold(
topBar = {
TopBanner(
text = "Writing character",
text = stringResource(R.string.write_character_title),
onBackClick = onClickCancel
)
}
@ -102,7 +105,7 @@ fun WriteCharacterScreen(
) {
Image(
bitmap = charaImageBitmapData.imageBitmap,
contentDescription = "Icon",
contentDescription = stringResource(R.string.write_character_icon_description),
modifier = Modifier
.size(charaImageBitmapData.dpWidth)
.padding(8.dp),
@ -116,8 +119,8 @@ fun WriteCharacterScreen(
)
Column {
Text("Card installed successfully!!")
Text("Wait until your device is ready, then tap 'Confirm'")
Text(stringResource(R.string.write_character_success))
Text(stringResource(R.string.write_character_wait_ready))
}
}
@ -128,7 +131,7 @@ fun WriteCharacterScreen(
Button(
onClick = onClickConfirm,
) {
Text("Confirm")
Text(stringResource(R.string.write_character_confirm))
}
}
}

View File

@ -17,6 +17,8 @@ import com.github.nacabaro.vbhelper.screens.scanScreen.ScanScreenController
import com.github.nacabaro.vbhelper.source.StorageRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun WritingScreen(
@ -97,7 +99,7 @@ fun WritingScreen(
)
} else if (!isDoneSendingCard) {
writing = true
ActionScreen("Sending card") {
ActionScreen( topBannerText = stringResource(R.string.sending_card_title)) {
scanScreenController.cancelRead()
onCancel()
}
@ -115,7 +117,7 @@ fun WritingScreen(
)
} else if (!isDoneWritingCharacter) {
writing = true
ActionScreen("Writing character") {
ActionScreen(topBannerText = stringResource(R.string.writing_character_action_title)) {
isDoneSendingCard = false
scanScreenController.cancelRead()
onCancel()

View File

@ -6,8 +6,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.R
@Composable
fun CreditsScreen(
@ -16,7 +18,7 @@ fun CreditsScreen(
Scaffold (
topBar = {
TopBanner(
text = "Credits",
text = stringResource(R.string.credits_title),
onBackClick = {
navController.popBackStack()
}
@ -29,13 +31,13 @@ fun CreditsScreen(
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
) {
SettingsSection("Reverse engineering")
SettingsEntry(title = "cyanic", description = "Reversed the firmware and helped us during development.") { }
SettingsSection("Application development")
SettingsEntry(title = "cfogrady", description = "Developed vb-lib-nfc and part of this application.") { }
SettingsEntry(title = "nacabaro", description = "Developed this application.") { }
SettingsEntry(title = "lightheel", description = "Developing the battling part for this application, including server. Still in the works.") { }
SettingsEntry(title = "shvstrz", description = "Designing the app icon in SVG.") { }
SettingsSection(stringResource(R.string.credits_section_reverse_engineering))
SettingsEntry(title = "cyanic", description = stringResource(R.string.credits_cyanic_description)) { }
SettingsSection(stringResource(R.string.credits_section_app_development))
SettingsEntry(title = "cfogrady", description = stringResource(R.string.credits_cfogrady_description)) { }
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)) { }
}
}
}

View File

@ -16,12 +16,15 @@ 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.res.stringResource
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
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.R
@Composable
fun SettingsScreen(
@ -30,10 +33,10 @@ fun SettingsScreen(
) {
val context = LocalContext.current
Scaffold (
Scaffold(
topBar = {
TopBanner(
text = "Settings",
text = stringResource(R.string.settings_title),
onBackClick = {
navController.popBackStack()
}
@ -42,34 +45,57 @@ fun SettingsScreen(
modifier = Modifier
.fillMaxSize()
) { contentPadding ->
Column (
Column(
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
SettingsSection("NFC Communication")
SettingsEntry(title = "Import APK", description = "Import Secrets From Vital Arena 2.1.0 APK") {
SettingsSection(title = stringResource(R.string.settings_section_nfc))
SettingsEntry(
title = stringResource(R.string.settings_import_apk_title),
description = stringResource(R.string.settings_import_apk_desc)
) {
settingsScreenController.onClickImportApk()
}
SettingsSection("DiM/BEm management")
SettingsEntry(title = "Import card", description = "Import DiM/BEm card file") {
SettingsSection(title = stringResource(R.string.settings_section_dim_bem))
SettingsEntry(
title = stringResource(R.string.settings_import_card_title),
description = stringResource(R.string.settings_import_card_desc)
) {
settingsScreenController.onClickImportCard()
}
SettingsSection("About and credits")
SettingsEntry(title = "Credits", description = "Credits") {
SettingsSection(title = stringResource(R.string.settings_section_about))
SettingsEntry(
title = stringResource(R.string.settings_credits_title),
description = stringResource(R.string.settings_credits_desc)
) {
navController.navigate(NavigationItems.Credits.route)
}
SettingsEntry(title = "About", description = "About") {
SettingsEntry(
title = stringResource(R.string.settings_about_title),
description = stringResource(R.string.settings_about_desc)
) {
val browserIntent = Intent(
Intent.ACTION_VIEW, Uri.parse("https://github.com/nacabaro/vbhelper/"))
Intent.ACTION_VIEW,
Uri.parse("https://github.com/nacabaro/vbhelper/")
)
context.startActivity(browserIntent)
}
SettingsSection("Data management")
SettingsEntry(title = "Export data", description = "Export application database") {
SettingsSection(title = stringResource(R.string.settings_section_data))
SettingsEntry(
title = stringResource(R.string.settings_export_data_title),
description = stringResource(R.string.settings_export_data_desc)
) {
settingsScreenController.onClickOpenDirectory()
}
SettingsEntry(title = "Import data", description = "Import application database") {
SettingsEntry(
title = stringResource(R.string.settings_import_data_title),
description = stringResource(R.string.settings_import_data_desc)
) {
settingsScreenController.onClickImportDatabase()
}
}
@ -101,9 +127,9 @@ fun SettingsEntry(
fun SettingsSection(
title: String
) {
Box (
Box(
modifier = Modifier
.padding(start = 16.dp)
.padding(start = 16.dp, top = 16.dp, bottom = 4.dp)
) {
Text(
text = title,

View File

@ -33,6 +33,9 @@ import com.github.nacabaro.vbhelper.source.StorageRepository
import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.utils.getBitmap
import kotlinx.coroutines.launch
import androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
fun StorageDialog(
@ -94,7 +97,7 @@ fun StorageDialog(
val dpSize = (characterSprite.value!!.width * 4 / density).dp
Image(
bitmap = imageBitmap,
contentDescription = "Character image",
contentDescription = stringResource(R.string.storage_character_image_description),
filterQuality = FilterQuality.None,
modifier = Modifier
.size(dpSize)
@ -104,7 +107,7 @@ fun StorageDialog(
val nameDpSize = (characterName.value!!.width * 4 / density).dp
Image(
bitmap = nameImageBitmap,
contentDescription = "Character image",
contentDescription = stringResource(R.string.storage_character_image_description),
filterQuality = FilterQuality.None,
modifier = Modifier
.size(nameDpSize)
@ -121,7 +124,7 @@ fun StorageDialog(
modifier = Modifier
.weight(1f)
) {
Text(text = "Send to watch")
Text(text = stringResource(R.string.storage_send_to_watch))
}
Spacer(
modifier = Modifier
@ -130,7 +133,7 @@ fun StorageDialog(
Button(
onClick = onClickSetActive,
) {
Text(text = "Set active")
Text(text = stringResource(R.string.storage_set_active))
}
}
Button(
@ -140,21 +143,21 @@ fun StorageDialog(
modifier = Modifier
.fillMaxWidth()
) {
Text(text = "Send on adventure")
Text(text = stringResource(R.string.storage_send_on_adventure))
}
Button(
modifier = Modifier
.fillMaxWidth(),
onClick = onClickDelete
) {
Text(text = "Delete character")
Text(text = stringResource(R.string.storage_delete_character))
}
Button(
modifier = Modifier
.fillMaxWidth(),
onClick = onDismissRequest
) {
Text(text = "Close")
Text(text = stringResource(R.string.storage_close))
}
}
}

View File

@ -34,6 +34,8 @@ 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 androidx.compose.ui.res.stringResource
import com.github.nacabaro.vbhelper.R
@Composable
@ -51,7 +53,7 @@ fun StorageScreen(
Scaffold (
topBar = {
TopBanner(
text = "My characters",
text = stringResource(R.string.storage_my_characters_title),
onAdventureClick = {
navController.navigate(NavigationItems.Adventure.route)
}
@ -67,7 +69,7 @@ fun StorageScreen(
.fillMaxSize()
) {
Text(
text = "Nothing to see here",
text = stringResource(R.string.storage_nothing_to_see_here),
textAlign = TextAlign.Center,
modifier = Modifier
)
@ -92,7 +94,7 @@ fun StorageScreen(
} else {
Toast.makeText(
application,
"This character is in an adventure",
application.getString(R.string.storage_in_adventure_toast),
Toast.LENGTH_SHORT
).show()
navController.navigate(

View File

@ -0,0 +1,220 @@
<resources>
<string name="app_name">VBHelper</string>
<string name="beta_warning_message_main">
Este aplicativo ainda está em versão alfa e não está completo. Não o use para armazenar personagens importantes para você, pois futuras atualizações podem apagar todos os seus personagens. Desculpe pelo transtorno!
</string>
<string name="beta_warning_message_compatibility">
O aplicativo agora deve funcionar com o VB original e com o VH.
</string>
<string name="beta_warning_message_thanks">
Obrigado pela compreensão e pela paciência. Atenciosamente, a equipe de desenvolvimento.
</string>
<string name="beta_warning_button_dismiss">Fechar</string>
<string name="nav_scan">Escanear</string>
<string name="nav_battle">Batalhas</string>
<string name="nav_home">Início</string>
<string name="nav_dex">Dex</string>
<string name="nav_card_adventure">Aventura do card</string>
<string name="nav_storage">Armazenamento</string>
<string name="nav_settings">Configurações</string>
<string name="nav_viewer">Visualizador</string>
<string name="nav_card">Card</string>
<string name="nav_items">Itens</string>
<string name="nav_my_items">Meus itens</string>
<string name="nav_items_store">Loja de itens</string>
<string name="nav_apply_item">Aplicar item</string>
<string name="nav_adventure">Aventura</string>
<string name="nav_credits">Créditos</string>
<string name="adventure_title">Aventura</string>
<string name="adventure_empty_state">Nada para ver aqui</string>
<string name="home_title">VB Helper</string>
<string name="home_adventure_mission_finished">
Um dos seus personagens terminou a missão de aventura!
</string>
<string name="scan_secrets_not_initialized">
Os segredos ainda não foram inicializados. Tente novamente.
</string>
<string name="scan_secrets_not_imported">
Os segredos ainda não foram importados. Vá em Configurações e importe o APK.
</string>
<string name="scan_title">Escanear um Vital Bracelet</string>
<string name="scan_vb_to_app">Vital Bracelet para o app</string>
<string name="scan_app_to_vb">App para o Vital Bracelet</string>
<string name="scan_no_nfc_on_device">O dispositivo não possui NFC!</string>
<string name="scan_tag_not_vb">A tag detectada não é do Vital Bracelet.</string>
<string name="scan_missing_secrets">
Segredos ausentes. Vá em Configurações e importe o APK do Vital Arena.
</string>
<string name="scan_sent_character_success">Personagem enviado com sucesso!</string>
<string name="scan_error_generic">Ops!</string>
<string name="scan_sent_dim_success">DIM enviado com sucesso!</string>
<string name="scan_nfc_must_be_enabled">O NFC precisa estar ativado.</string>
<string name="settings_title">Configurações</string>
<string name="settings_section_nfc">Comunicação NFC</string>
<string name="settings_section_dim_bem">Gerenciamento de DiM/BEm</string>
<string name="settings_section_about">Sobre e créditos</string>
<string name="settings_section_data">Gerenciamento de dados</string>
<string name="settings_import_apk_title">Importar APK</string>
<string name="settings_import_apk_desc">
Importar segredos do APK do Vital Arena 2.1.0
</string>
<string name="settings_import_card_title">Importar card</string>
<string name="settings_import_card_desc">
Importar arquivo de card DiM/BEm
</string>
<string name="settings_credits_title">Créditos</string>
<string name="settings_credits_desc">Créditos</string>
<string name="settings_about_title">Sobre</string>
<string name="settings_about_desc">Sobre</string>
<string name="settings_export_data_title">Exportar dados</string>
<string name="settings_export_data_desc">
Exportar banco de dados do aplicativo
</string>
<string name="settings_import_data_title">Importar dados</string>
<string name="settings_import_data_desc">
Importar banco de dados do aplicativo
</string>
<string name="credits_title">Créditos</string>
<string name="credits_section_reverse_engineering">Engenharia reversa</string>
<string name="credits_section_app_development">Desenvolvimento do aplicativo</string>
<string name="credits_cyanic_description">
Reverteu o firmware e nos ajudou durante o desenvolvimento.
</string>
<string name="credits_cfogrady_description">
Desenvolveu vb-lib-nfc e parte deste aplicativo.
</string>
<string name="credits_nacabaro_description">
Desenvolveu este aplicativo.
</string>
<string name="credits_lightheel_description">
Está desenvolvendo a parte de batalhas deste aplicativo, incluindo o servidor. Ainda em desenvolvimento.
</string>
<string name="credits_shvstrz_description">
Responsável pelo design do ícone do aplicativo em SVG.
</string>
<string name="action_place_near_reader">Aproxime o seu Vital Bracelet do leitor...</string>
<string name="action_cancel">Cancelar</string>
<string name="read_character_title">Ler personagem</string>
<string name="read_character_prepare_device">Prepare seu dispositivo!</string>
<string name="read_character_go_to_connect">Vá em conectar e, quando estiver pronto, pressione confirmar!</string>
<string name="read_character_confirm">Confirmar</string>
<string name="reading_character_title">Lendo personagem</string>
<string name="write_card_title">Escrevendo detalhes do cartão</string>
<string name="write_card_icon_description">Ícone do cartão</string>
<string name="write_card_device_ready">Prepare o seu dispositivo!</string>
<string name="write_card_required_card">Você vai precisar do cartão %1$s!</string>
<string name="write_card_confirm">Confirmar</string>
<string name="write_character_title">Escrevendo personagem</string>
<string name="write_character_icon_description">Ícone do personagem</string>
<string name="write_character_success">
Cartão instalado com sucesso!!
</string>
<string name="write_character_wait_ready">
Aguarde até que seu dispositivo esteja pronto e então toque em Confirmar
</string>
<string name="write_character_confirm">Confirmar</string>
<string name="sending_card_title">Enviando cartão</string>
<string name="writing_character_action_title">Escrevendo personagem</string>
<string name="items_title">Itens</string>
<string name="items_no_items">Nenhum item</string>
<string name="items_store_credits">%1$d créditos</string>
<string name="items_not_enough_credits">Créditos insuficientes</string>
<string name="items_purchase_success">Compra realizada com sucesso!</string>
<string name="obtained_item_you_have">Você obteve %1$d deste item</string>
<string name="obtained_item_you_also_got_credits">Você também recebeu %1$d créditos</string>
<string name="obtained_item_dismiss">Fechar</string>
<string name="choose_character_title">Escolher personagem</string>
<string name="choose_character_item_applied">Item aplicado!</string>
<string name="item_dialog_costs_credits">Custa %1$d créditos</string>
<string name="item_dialog_you_have_quantity">Você tem %1$d deste item</string>
<string name="item_dialog_use">Usar item</string>
<string name="item_dialog_purchase">Comprar</string>
<string name="item_dialog_cancel">Cancelar</string>
<string name="battles_online_title">Batalhas online</string>
<string name="battles_coming_soon">Em breve</string>
<string name="cards_my_cards_title">Meus cards</string>
<string name="card_view_discovered_characters">Personagens descobertos</string>
<string name="dex_chara_icon_description">Ícone do personagem</string>
<string name="dex_chara_name_icon_description">Nome do personagem</string>
<string name="dex_chara_stats">HP: %1$d, BP: %2$d, AP: %3$d</string>
<string name="dex_chara_stage_attribute">Stg: %1$s, Atr: %2$s</string>
<string name="dex_chara_unknown_name">\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?</string>
<string name="dex_chara_stage_attribute_unknown">Stg: -, Atr: -</string>
<string name="dex_chara_stats_unknown">HP: -, BP: -, AP: -</string>
<string name="dex_chara_requirements">
Tr: %1$d; Bt: %2$d; Vr: %3$d; Wr: %4$d%%; Ct: %5$dh
</string>
<string name="dex_chara_adventure_level">AdvLvl %1$d</string>
<string name="dex_chara_fusions_button">Fusões</string>
<string name="dex_chara_close_button">Fechar</string>
<string name="card_adventure_missions_title">Missões de aventura</string>
<string name="card_entry_characters_obtained">%1$d de %2$d personagens obtidos</string>
<string name="card_entry_edit">Editar card</string>
<string name="card_entry_delete">Excluir card</string>
<string name="storage_my_characters_title">Meus personagens</string>
<string name="storage_nothing_to_see_here">Nada para ver aqui</string>
<string name="storage_in_adventure_toast">Este personagem está em uma aventura</string>
<string name="storage_character_image_description">Imagem do personagem</string>
<string name="storage_send_to_watch">Enviar para o relógio</string>
<string name="storage_set_active">Definir como ativo</string>
<string name="storage_send_on_adventure">Enviar para aventura</string>
<string name="storage_delete_character">Excluir personagem</string>
<string name="storage_close">Fechar</string>
<string name="home_vbdim_vitals">Vitais</string>
<string name="home_vbdim_trophies">Troféus</string>
<string name="home_vbdim_mood">Humor</string>
<string name="home_vbdim_next_timer">Próximo timer</string>
<string name="home_vbdim_total_battle_win">% vitórias totais</string>
<string name="home_vbdim_current_phase_win">% vitórias fase atual</string>
<string name="home_vbdim_special_missions">Missões especiais</string>
<string name="special_mission_none">Nenhuma missão selecionada</string>
<string name="special_mission_steps">Ande %1$d passos</string>
<string name="special_mission_battles">Lute %1$d vezes</string>
<string name="special_mission_wins">Vença %1$d batalhas</string>
<string name="special_mission_vitals">Ganhe %1$d vitals</string>
<string name="special_mission_steps_progress">Andou %1$d passos</string>
<string name="special_mission_battles_progress">Lutou %1$d vezes</string>
<string name="special_mission_wins_progress">Venceu %1$d batalhas</string>
<string name="special_mission_vitals_progress">Ganhou %1$d vitals</string>
<string name="special_mission_icon_content_description">Ícone de missão especial</string>
</resources>

View File

@ -1,3 +1,226 @@
<resources>
<string name="app_name">VBHelper</string>
<string name="beta_warning_message_main">
This application is currently in alpha and it is not complete. Do not use it to store important characters for you, as any future updates might delete all your characters. Sorry for the inconvenience!
</string>
<string name="beta_warning_message_compatibility">
The application should now work with the original VB and the VH.
</string>
<string name="beta_warning_message_thanks">
Thank you for your understanding and patience. Sincerely, the dev team.
</string>
<string name="beta_warning_button_dismiss">
Dismiss
</string>
<string name="nav_scan">Scan</string>
<string name="nav_battle">Battle</string>
<string name="nav_home">Home</string>
<string name="nav_dex">Dex</string>
<string name="nav_card_adventure">Card adventure</string>
<string name="nav_storage">Storage</string>
<string name="nav_settings">Settings</string>
<string name="nav_viewer">Viewer</string>
<string name="nav_card">Card</string>
<string name="nav_items">Items</string>
<string name="nav_my_items">My items</string>
<string name="nav_items_store">Items store</string>
<string name="nav_apply_item">Apply item</string>
<string name="nav_adventure">Adventure</string>
<string name="nav_credits">Credits</string>
<string name="adventure_title">Adventure</string>
<string name="adventure_empty_state">Nothing to see here</string>
<string name="home_title">VB Helper</string>
<string name="home_adventure_mission_finished">
One of your characters has finished their adventure mission!
</string>
<string name="scan_secrets_not_initialized">
Secrets is not yet initialized. Try again.
</string>
<string name="scan_secrets_not_imported">
Secrets not yet imported. Go to Settings and Import APK.
</string>
<string name="scan_title">Scan a Vital Bracelet</string>
<string name="scan_vb_to_app">Vital Bracelet to App</string>
<string name="scan_app_to_vb">App to Vital Bracelet</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_missing_secrets">
Missing Secrets. Go to settings and import Vital Arena APK.
</string>
<string name="scan_sent_character_success">Sent character successfully!</string>
<string name="scan_error_generic">Whoops</string>
<string name="scan_sent_dim_success">Sent DIM successfully!</string>
<string name="scan_nfc_must_be_enabled">NFC must be enabled</string>
<string name="settings_title">Settings</string>
<string name="settings_section_nfc">NFC Communication</string>
<string name="settings_section_dim_bem">DiM/BEm management</string>
<string name="settings_section_about">About and credits</string>
<string name="settings_section_data">Data management</string>
<string name="settings_import_apk_title">Import APK</string>
<string name="settings_import_apk_desc">
Import Secrets From Vital Arena 2.1.0 APK
</string>
<string name="settings_import_card_title">Import card</string>
<string name="settings_import_card_desc">
Import DiM/BEm card file
</string>
<string name="settings_credits_title">Credits</string>
<string name="settings_credits_desc">Credits</string>
<string name="settings_about_title">About</string>
<string name="settings_about_desc">About</string>
<string name="settings_export_data_title">Export data</string>
<string name="settings_export_data_desc">
Export application database
</string>
<string name="settings_import_data_title">Import data</string>
<string name="settings_import_data_desc">
Import application database
</string>
<string name="credits_title">Credits</string>
<string name="credits_section_reverse_engineering">Reverse engineering</string>
<string name="credits_section_app_development">Application development</string>
<string name="credits_cyanic_description">
Reversed the firmware and helped us during development.
</string>
<string name="credits_cfogrady_description">
Developed vb-lib-nfc and part of this application.
</string>
<string name="credits_nacabaro_description">
Developed this application.
</string>
<string name="credits_lightheel_description">
Developing the battling part for this application, including server. Still in the works.
</string>
<string name="credits_shvstrz_description">
Designing the app icon in SVG.
</string>
<string name="action_place_near_reader">Place your Vital Bracelet near the reader...</string>
<string name="action_cancel">Cancel</string>
<string name="read_character_title">Read character</string>
<string name="read_character_prepare_device">Prepare your device!</string>
<string name="read_character_go_to_connect">Go to connect and when ready press confirm!</string>
<string name="read_character_confirm">Confirm</string>
<string name="reading_character_title">Reading character</string>
<string name="write_card_title">Writing card details</string>
<string name="write_card_icon_description">Card icon</string>
<string name="write_card_device_ready">Get your device ready!</string>
<string name="write_card_required_card">You will need %1$s card!</string>
<string name="write_card_confirm">Confirm</string>
<string name="write_character_title">Writing character</string>
<string name="write_character_icon_description">Character icon</string>
<string name="write_character_success">
Card installed successfully!!
</string>
<string name="write_character_wait_ready">
Wait until your device is ready, then tap Confirm
</string>
<string name="write_character_confirm">Confirm</string>
<string name="sending_card_title">Sending card</string>
<string name="writing_character_action_title">Writing character</string>
<string name="items_title">Items</string>
<string name="items_no_items">No items</string>
<string name="items_store_credits">%1$d credits</string>
<string name="items_not_enough_credits">Not enough credits</string>
<string name="items_purchase_success">Purchase successful!</string>
<string name="obtained_item_you_have">You have obtained %1$d of this item</string>
<string name="obtained_item_you_also_got_credits">You also got %1$d credits</string>
<string name="obtained_item_dismiss">Dismiss</string>
<string name="choose_character_title">Choose character</string>
<string name="choose_character_item_applied">Item applied!</string>
<string name="item_dialog_costs_credits">Costs %1$d credits</string>
<string name="item_dialog_you_have_quantity">You have %1$d of this item</string>
<string name="item_dialog_use">Use item</string>
<string name="item_dialog_purchase">Purchase</string>
<string name="item_dialog_cancel">Cancel</string>
<string name="battles_online_title">Online battles</string>
<string name="battles_coming_soon">Coming soon</string>
<string name="cards_my_cards_title">My cards</string>
<string name="card_view_discovered_characters">Discovered characters</string>
<string name="dex_chara_icon_description">Character icon</string>
<string name="dex_chara_name_icon_description">Character name</string>
<string name="dex_chara_stats">HP: %1$d, BP: %2$d, AP: %3$d</string>
<string name="dex_chara_stage_attribute">Stg: %1$s, Atr: %2$s</string>
<string name="dex_chara_unknown_name">\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?\?</string>
<string name="dex_chara_stage_attribute_unknown">Stg: -, Atr: -</string>
<string name="dex_chara_stats_unknown">HP: -, BP: -, AP: -</string>
<string name="dex_chara_requirements">
Tr: %1$d; Bt: %2$d; Vr: %3$d; Wr: %4$d%%; Ct: %5$dh
</string>
<string name="dex_chara_adventure_level">AdvLvl %1$d</string>
<string name="dex_chara_fusions_button">Fusions</string>
<string name="dex_chara_close_button">Close</string>
<string name="card_adventure_missions_title">Adventure missions</string>
<string name="card_entry_characters_obtained">%1$d of %2$d characters obtained</string>
<string name="card_entry_edit">Edit card</string>
<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_in_adventure_toast">This character is in an adventure</string>
<string name="storage_character_image_description">Character image</string>
<string name="storage_send_to_watch">Send to watch</string>
<string name="storage_set_active">Set active</string>
<string name="storage_send_on_adventure">Send on adventure</string>
<string name="storage_delete_character">Delete character</string>
<string name="storage_close">Close</string>
<string name="home_vbdim_vitals">Vitals</string>
<string name="home_vbdim_trophies">Trophies</string>
<string name="home_vbdim_mood">Mood</string>
<string name="home_vbdim_next_timer">Next timer</string>
<string name="home_vbdim_total_battle_win">Total battle win %</string>
<string name="home_vbdim_current_phase_win">Current phase win %</string>
<string name="home_vbdim_special_missions">Special missions</string>
<string name="special_mission_none">No mission selected</string>
<string name="special_mission_steps">Walk %1$d steps</string>
<string name="special_mission_battles">Battle %1$d times</string>
<string name="special_mission_wins">Win %1$d battles</string>
<string name="special_mission_vitals">Earn %1$d vitals</string>
<string name="special_mission_steps_progress">Walked %1$d steps</string>
<string name="special_mission_battles_progress">Battled %1$d times</string>
<string name="special_mission_wins_progress">Won %1$d battles</string>
<string name="special_mission_vitals_progress">Earned %1$d vitals</string>
<string name="special_mission_icon_content_description">Special mission icon</string>
</resources>