feat: localisation with lyricist
This commit is contained in:
@@ -4,6 +4,24 @@ import cafe.adriel.lyricist.LyricistStrings
|
||||
|
||||
@LyricistStrings(languageTag = "en", default = true)
|
||||
val EnHomeStrings = AppStrings(
|
||||
// ── WalletScreen ──────────────────────────────────────────────────────────
|
||||
tabReceive = "Receive",
|
||||
tabSend = "Send",
|
||||
scanContentDescription = "Scan",
|
||||
dismissContentDescription = "Dismiss",
|
||||
clipboardInvoiceDetected = "Invoice detected in clipboard",
|
||||
clipboardLnurlDetected = "LNURL detected in clipboard",
|
||||
clipboardAddressDetected = "Lightning Address detected in clipboard",
|
||||
clipboardPaymentDetected = "Payment detected in clipboard",
|
||||
clipboardTapToOpen = "Tap to open",
|
||||
clipboardTapToPay = "Tap to pay",
|
||||
nfcInvoiceDetected = "Invoice detected via NFC",
|
||||
nfcLnurlDetected = "LNURL detected via NFC",
|
||||
nfcAddressDetected = "Lightning Address detected via NFC",
|
||||
nfcPaymentDetected = "Payment detected via NFC",
|
||||
nfcTapToOpen = "Tap to open",
|
||||
nfcTapToPay = "Tap to pay",
|
||||
|
||||
// ── HomeTab ───────────────────────────────────────────────────────────────
|
||||
loadingBalance = "Loading balance…",
|
||||
sats = "sats",
|
||||
|
||||
@@ -4,6 +4,24 @@ import cafe.adriel.lyricist.LyricistStrings
|
||||
|
||||
@LyricistStrings(languageTag = "es")
|
||||
val EsHomeStrings = AppStrings(
|
||||
// ── WalletScreen ──────────────────────────────────────────────────────────
|
||||
tabReceive = "Recibir",
|
||||
tabSend = "Enviar",
|
||||
scanContentDescription = "Escanear",
|
||||
dismissContentDescription = "Cerrar",
|
||||
clipboardInvoiceDetected = "Factura detectada en el portapapeles",
|
||||
clipboardLnurlDetected = "LNURL detectado en el portapapeles",
|
||||
clipboardAddressDetected = "Dirección Lightning detectada en el portapapeles",
|
||||
clipboardPaymentDetected = "Pago detectado en el portapapeles",
|
||||
clipboardTapToOpen = "Toca para abrir",
|
||||
clipboardTapToPay = "Toca para pagar",
|
||||
nfcInvoiceDetected = "Factura detectada por NFC",
|
||||
nfcLnurlDetected = "LNURL detectado por NFC",
|
||||
nfcAddressDetected = "Dirección Lightning detectada por NFC",
|
||||
nfcPaymentDetected = "Pago detectado por NFC",
|
||||
nfcTapToOpen = "Toca para abrir",
|
||||
nfcTapToPay = "Toca para pagar",
|
||||
|
||||
// ── HomeTab ───────────────────────────────────────────────────────────────
|
||||
loadingBalance = "Cargando saldo…",
|
||||
sats = "sats",
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
package com.bitcointxoko.gudariwallet.i18n
|
||||
|
||||
data class AppStrings(
|
||||
// ── Loading state ──────────────────────────────────────────────────────────
|
||||
// ── WalletScreen ──────────────────────────────────────────────────────────
|
||||
val tabReceive : String,
|
||||
val tabSend : String,
|
||||
val scanContentDescription : String,
|
||||
val dismissContentDescription : String,
|
||||
val clipboardInvoiceDetected : String,
|
||||
val clipboardLnurlDetected : String,
|
||||
val clipboardAddressDetected : String,
|
||||
val clipboardPaymentDetected : String,
|
||||
val clipboardTapToOpen : String,
|
||||
val clipboardTapToPay : String,
|
||||
val nfcInvoiceDetected : String,
|
||||
val nfcLnurlDetected : String,
|
||||
val nfcAddressDetected : String,
|
||||
val nfcPaymentDetected : String,
|
||||
val nfcTapToOpen : String,
|
||||
val nfcTapToPay : String,
|
||||
|
||||
// ── HomeTab ───────────────────────────────────────────────────────────────
|
||||
val loadingBalance: String,
|
||||
|
||||
// ── Balance display ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -56,6 +56,7 @@ import androidx.navigation.navArgument
|
||||
import cafe.adriel.lyricist.Lyricist
|
||||
import com.bitcointxoko.gudariwallet.MainActivity
|
||||
import com.bitcointxoko.gudariwallet.i18n.AppStrings
|
||||
import com.bitcointxoko.gudariwallet.LocalAppStrings
|
||||
import com.bitcointxoko.gudariwallet.ui.history.HistoryScreen
|
||||
import com.bitcointxoko.gudariwallet.ui.history.HistoryViewModel
|
||||
import com.bitcointxoko.gudariwallet.ui.history.HistoryViewModelFactory
|
||||
@@ -67,10 +68,12 @@ import com.bitcointxoko.gudariwallet.util.SendInputType
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
// ── Tab destinations ──────────────────────────────────────────────────────────
|
||||
// Note: label and icon are now resolved at the call site via LocalAppStrings,
|
||||
// so the sealed class carries only the stable route string and icon vector.
|
||||
|
||||
sealed class TabItem(val route: String, val label: String, val icon: ImageVector) {
|
||||
data object Receive : TabItem("receive", "Receive", Icons.Filled.QrCode)
|
||||
data object Send : TabItem("send", "Send", Icons.AutoMirrored.Filled.Send)
|
||||
sealed class TabItem(val route: String, val icon: ImageVector) {
|
||||
data object Receive : TabItem("receive", Icons.Filled.QrCode)
|
||||
data object Send : TabItem("send", Icons.AutoMirrored.Filled.Send)
|
||||
}
|
||||
|
||||
private const val ROUTE_HOME = "home"
|
||||
@@ -81,11 +84,12 @@ private const val ROUTE_PAYMENT_DETAIL = "payment_detail/{checkingId}"
|
||||
@Composable
|
||||
fun WalletScreen(
|
||||
vm : WalletViewModel,
|
||||
nfcVm : NfcViewModel, // ← new
|
||||
nfcVm : NfcViewModel,
|
||||
pendingPaymentHash: MutableState<String?>,
|
||||
pendingPaymentUri : MutableState<String?>,
|
||||
lyricist : Lyricist<AppStrings>
|
||||
) {
|
||||
val strings = LocalAppStrings.current
|
||||
val navController = rememberNavController()
|
||||
val context = LocalContext.current
|
||||
val historyFactory = remember {
|
||||
@@ -179,7 +183,6 @@ fun WalletScreen(
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
if (showBottomBar) {
|
||||
// ── Floating island nav bar: Receive | [Scan] | Send ──────────
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -204,8 +207,8 @@ fun WalletScreen(
|
||||
// Receive
|
||||
NavigationBarItem(
|
||||
selected = currentRoute == TabItem.Receive.route,
|
||||
icon = { Icon(TabItem.Receive.icon, contentDescription = TabItem.Receive.label) },
|
||||
label = { Text(TabItem.Receive.label) },
|
||||
icon = { Icon(TabItem.Receive.icon, contentDescription = strings.tabReceive) }, // ← localized
|
||||
label = { Text(strings.tabReceive) }, // ← localized
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
if (currentRoute != TabItem.Receive.route) {
|
||||
@@ -239,7 +242,7 @@ fun WalletScreen(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.QrCodeScanner,
|
||||
contentDescription = "Scan",
|
||||
contentDescription = strings.scanContentDescription, // ← localized
|
||||
modifier = Modifier.size(26.dp)
|
||||
)
|
||||
}
|
||||
@@ -248,8 +251,8 @@ fun WalletScreen(
|
||||
// Send
|
||||
NavigationBarItem(
|
||||
selected = currentRoute == TabItem.Send.route,
|
||||
icon = { Icon(TabItem.Send.icon, contentDescription = TabItem.Send.label) },
|
||||
label = { Text(TabItem.Send.label) },
|
||||
icon = { Icon(TabItem.Send.icon, contentDescription = strings.tabSend) }, // ← localized
|
||||
label = { Text(strings.tabSend) }, // ← localized
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
if (currentRoute != TabItem.Send.route) {
|
||||
@@ -298,7 +301,7 @@ fun WalletScreen(
|
||||
composable(TabItem.Receive.route) {
|
||||
ReceiveScreen(
|
||||
vm = vm,
|
||||
nfcVm = nfcVm, // ← new
|
||||
nfcVm = nfcVm,
|
||||
onNavigateToPaymentDetail = { checkingId ->
|
||||
navController.navigate("payment_detail/$checkingId")
|
||||
}
|
||||
@@ -324,13 +327,12 @@ fun WalletScreen(
|
||||
vm.scan(scanned)
|
||||
val wentBack = navController.popBackStack(TabItem.Send.route, inclusive = false)
|
||||
if (!wentBack) {
|
||||
// Scan was triggered from a non-Send tab — navigate to Send
|
||||
navController.navigate(TabItem.Send.route) {
|
||||
popUpTo(navController.graph.findStartDestination().id) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
restoreState = false // don't restore old Idle state; VM already has new state
|
||||
restoreState = false
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -394,21 +396,21 @@ fun WalletScreen(
|
||||
exit = slideOutVertically(targetOffsetY = { -it }),
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopCenter)
|
||||
.zIndex(2f) // above NFC banner
|
||||
.zIndex(2f)
|
||||
.fillMaxWidth()
|
||||
.statusBarsPadding()
|
||||
) {
|
||||
if (clipboardOffer is ClipboardOfferState.Detected) {
|
||||
val offer = clipboardOffer as ClipboardOfferState.Detected
|
||||
val label = when (offer.inputType) {
|
||||
is SendInputType.Bolt11 -> "Invoice"
|
||||
is SendInputType.Lnurl -> "LNURL"
|
||||
is SendInputType.LightningAddress -> "Lightning Address"
|
||||
else -> "Payment"
|
||||
is SendInputType.Bolt11 -> strings.clipboardInvoiceDetected // ← localized
|
||||
is SendInputType.Lnurl -> strings.clipboardLnurlDetected // ← localized
|
||||
is SendInputType.LightningAddress -> strings.clipboardAddressDetected // ← localized
|
||||
else -> strings.clipboardPaymentDetected // ← localized
|
||||
}
|
||||
val subLabel = when (offer.inputType) {
|
||||
is SendInputType.Lnurl -> "Tap to open"
|
||||
else -> "Tap to pay"
|
||||
is SendInputType.Lnurl -> strings.clipboardTapToOpen // ← localized
|
||||
else -> strings.clipboardTapToPay // ← localized
|
||||
}
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.primaryContainer,
|
||||
@@ -429,10 +431,7 @@ fun WalletScreen(
|
||||
Icon(Icons.Default.ContentPaste, contentDescription = null)
|
||||
Spacer(Modifier.width(12.dp))
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(
|
||||
"$label detected in clipboard",
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(label, style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
subLabel,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
@@ -440,7 +439,7 @@ fun WalletScreen(
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { vm.dismissClipboardOffer() }) {
|
||||
Icon(Icons.Default.Close, contentDescription = "Dismiss")
|
||||
Icon(Icons.Default.Close, contentDescription = strings.dismissContentDescription) // ← localized
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -448,29 +447,27 @@ fun WalletScreen(
|
||||
}
|
||||
|
||||
// ── NFC banner — floats over content, slides in from top ──────────
|
||||
// Shown when an NFC tag is tapped while the app is foregrounded.
|
||||
// Mirrors the clipboard banner pattern exactly.
|
||||
AnimatedVisibility(
|
||||
visible = nfcOffer is NfcOfferState.Detected,
|
||||
enter = slideInVertically(initialOffsetY = { -it }),
|
||||
exit = slideOutVertically(targetOffsetY = { -it }),
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopCenter)
|
||||
.zIndex(1f) // below clipboard banner if both show
|
||||
.zIndex(1f)
|
||||
.fillMaxWidth()
|
||||
.statusBarsPadding()
|
||||
) {
|
||||
if (nfcOffer is NfcOfferState.Detected) {
|
||||
val offer = nfcOffer as NfcOfferState.Detected
|
||||
val label = when (offer.inputType) {
|
||||
is SendInputType.Bolt11 -> "Invoice"
|
||||
is SendInputType.Lnurl -> "LNURL"
|
||||
is SendInputType.LightningAddress -> "Lightning Address"
|
||||
else -> "Payment"
|
||||
is SendInputType.Bolt11 -> strings.nfcInvoiceDetected // ← localized
|
||||
is SendInputType.Lnurl -> strings.nfcLnurlDetected // ← localized
|
||||
is SendInputType.LightningAddress -> strings.nfcAddressDetected // ← localized
|
||||
else -> strings.nfcPaymentDetected // ← localized
|
||||
}
|
||||
val subLabel = when (offer.inputType) {
|
||||
is SendInputType.Lnurl -> "Tap to open"
|
||||
else -> "Tap to pay"
|
||||
is SendInputType.Lnurl -> strings.nfcTapToOpen // ← localized
|
||||
else -> strings.nfcTapToPay // ← localized
|
||||
}
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.secondaryContainer,
|
||||
@@ -491,10 +488,7 @@ fun WalletScreen(
|
||||
Icon(Icons.Default.Nfc, contentDescription = null)
|
||||
Spacer(Modifier.width(12.dp))
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(
|
||||
"$label detected via NFC",
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(label, style = MaterialTheme.typography.bodyMedium)
|
||||
Text(
|
||||
subLabel,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
@@ -502,7 +496,7 @@ fun WalletScreen(
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { nfcVm.dismissNfcOffer() }) {
|
||||
Icon(Icons.Default.Close, contentDescription = "Dismiss")
|
||||
Icon(Icons.Default.Close, contentDescription = strings.dismissContentDescription) // ← localized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user