WIP: Fixing the uglies.
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.App.Starting"
|
||||
android:screenOrientation="portrait"
|
||||
android:resizeableActivity="false"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@@ -42,11 +42,11 @@ import swiss.qpq.gajumobile.ui.screens.CreateWalletScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.DashboardScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.DeleteConfirmationScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.EnvironmentInfoScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.ExplorerScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.FetchingScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.LockScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.ManageAccountScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.ManageWalletsScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.ManualGridsEntryScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.MnemonicRecoveryScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.MnemonicVerifyScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.QRReceiveScreen
|
||||
@@ -56,6 +56,7 @@ import swiss.qpq.gajumobile.ui.screens.SendReviewScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.SettingsScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.SetupChoiceScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.SignRequestScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.TransactionSuccessScreen
|
||||
import swiss.qpq.gajumobile.ui.screens.ViewMnemonicScreen
|
||||
import swiss.qpq.gajumobile.ui.theme.MyApplicationTheme
|
||||
import swiss.qpq.gajumaru.core.formatting.GajuFormat
|
||||
@@ -120,16 +121,19 @@ enum class Screen {
|
||||
MANAGE_ACCOUNT,
|
||||
MANAGE_WALLETS,
|
||||
DELETE_CONFIRM,
|
||||
EXPLORER,
|
||||
VIEW_MNEMONIC,
|
||||
VERIFY_MNEMONIC,
|
||||
ENVIRONMENT_INFO,
|
||||
SEND_FORM,
|
||||
SEND_REVIEW,
|
||||
SIGN_REQUEST,
|
||||
FETCHING_SIGN_REQUEST
|
||||
FETCHING_SIGN_REQUEST,
|
||||
MANUAL_GRIDS_ENTRY,
|
||||
TRANSACTION_SUCCESS
|
||||
}
|
||||
|
||||
enum class ScannerMode { SEND, GRIDS }
|
||||
|
||||
@Composable
|
||||
fun GajuRouter(
|
||||
context: android.content.Context,
|
||||
@@ -182,6 +186,8 @@ fun GajuRouter(
|
||||
var activeWalletIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||
var activeAccountIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||
|
||||
var currentScannerMode by rememberSaveable { mutableStateOf(ScannerMode.SEND) }
|
||||
|
||||
var nodeStatusResult by remember { mutableStateOf<Map<String, Any?>?>(null) }
|
||||
var nodeStatusError by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
@@ -194,10 +200,67 @@ fun GajuRouter(
|
||||
var pendingGasPrice by rememberSaveable { mutableStateOf("") }
|
||||
var pendingTTL by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
var lastTxHash by rememberSaveable { mutableStateOf("") }
|
||||
var lastTxAmount by rememberSaveable { mutableStateOf("") }
|
||||
var lastTxRecipient by rememberSaveable { mutableStateOf("") }
|
||||
var lastTxPayload by rememberSaveable { mutableStateOf("") }
|
||||
var lastTxNetworkId by rememberSaveable { mutableStateOf("") }
|
||||
var lastTxSenderLabel by rememberSaveable { mutableStateOf("") }
|
||||
var lastTxWalletName by rememberSaveable { mutableStateOf("") }
|
||||
|
||||
var pendingSignRequest by remember { mutableStateOf<GridsSignRequest?>(null) }
|
||||
var pendingSignUrl by rememberSaveable { mutableStateOf("") }
|
||||
var activeFetchJob by remember { mutableStateOf<Job?>(null) }
|
||||
|
||||
fun processGridsUrl(url: String) {
|
||||
try {
|
||||
val result = Grids.parse(url)
|
||||
if (result.verb == Grids.Verb.SIGN) {
|
||||
pendingSignUrl = result.url
|
||||
navigateTo(Screen.FETCHING_SIGN_REQUEST)
|
||||
|
||||
activeFetchJob = scope.launch {
|
||||
try {
|
||||
android.util.Log.i("GajuRouter", "Fetching GRIDS request from: ${result.url}")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Http.get(result.url) as? Map<String, Any?>
|
||||
}
|
||||
if (response != null) {
|
||||
pendingSignRequest = response.toGridsSignRequest()
|
||||
// Remove fetching screen and add request screen
|
||||
screenStack.removeAt(screenStack.size - 1)
|
||||
navigateTo(Screen.SIGN_REQUEST)
|
||||
} else {
|
||||
onError(context.getString(R.string.err_fetch_sig_failed))
|
||||
navigateBack()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (activeFetchJob?.isCancelled == false) {
|
||||
onError(context.getString(R.string.err_fetch_failed, e.message ?: ""))
|
||||
navigateBack()
|
||||
}
|
||||
} finally {
|
||||
activeFetchJob = null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pendingScanResult = result
|
||||
pendingRecipient = result.recipient ?: ""
|
||||
pendingAmountStr = if (result.amount != null) {
|
||||
val type = GajuFormat.Type.valueOf(appState.balanceFormat)
|
||||
val unit = GajuFormat.Unit.valueOf(appState.balanceUnit)
|
||||
GajuFormat.amount(GajuFormat.standardSpec(type, unit), result.amount)
|
||||
} else ""
|
||||
pendingPayload = if (result.payload != null) String(result.payload, Charsets.UTF_8) else ""
|
||||
|
||||
navigateTo(Screen.SEND_FORM)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
onError(context.getString(R.string.err_invalid_grids_url, e.message ?: ""))
|
||||
}
|
||||
}
|
||||
|
||||
when (currentScreen) {
|
||||
Screen.CREATE_WALLET -> {
|
||||
CreateWalletScreen(
|
||||
@@ -353,8 +416,28 @@ fun GajuRouter(
|
||||
onAccountIndexChange = { activeAccountIndex = it },
|
||||
balanceFormat = GajuFormat.Type.valueOf(appState.balanceFormat),
|
||||
balanceUnit = GajuFormat.Unit.valueOf(appState.balanceUnit),
|
||||
onSend = { navigateTo(Screen.QR_SCANNER) },
|
||||
onGrids = { navigateTo(Screen.QR_SCANNER) },
|
||||
onSend = {
|
||||
currentScannerMode = ScannerMode.SEND
|
||||
pendingRecipient = ""
|
||||
pendingAmountStr = ""
|
||||
pendingPayload = ""
|
||||
pendingGas = "20000"
|
||||
pendingGasPrice = "1000000000"
|
||||
pendingTTL = "500"
|
||||
pendingScanResult = null
|
||||
navigateTo(Screen.QR_SCANNER)
|
||||
},
|
||||
onGrids = {
|
||||
currentScannerMode = ScannerMode.GRIDS
|
||||
pendingRecipient = ""
|
||||
pendingAmountStr = ""
|
||||
pendingPayload = ""
|
||||
pendingGas = "20000"
|
||||
pendingGasPrice = "1000000000"
|
||||
pendingTTL = "500"
|
||||
pendingScanResult = null
|
||||
navigateTo(Screen.QR_SCANNER)
|
||||
},
|
||||
onReceive = { navigateTo(Screen.QR_RECEIVE) },
|
||||
onAddAccount = { walletId ->
|
||||
selectedWalletId = walletId
|
||||
@@ -378,7 +461,6 @@ fun GajuRouter(
|
||||
onNavigate = { dest ->
|
||||
val screen = when (dest) {
|
||||
"settings" -> Screen.SETTINGS
|
||||
"transactions" -> Screen.EXPLORER
|
||||
"environment_info" -> Screen.ENVIRONMENT_INFO
|
||||
"manage_wallets" -> Screen.MANAGE_WALLETS
|
||||
"CREATE_WALLET" -> Screen.CREATE_WALLET
|
||||
@@ -573,7 +655,6 @@ fun GajuRouter(
|
||||
} else {
|
||||
val screen = when (dest) {
|
||||
"dashboard" -> Screen.DASHBOARD
|
||||
"transactions" -> Screen.EXPLORER
|
||||
"environment_info" -> Screen.ENVIRONMENT_INFO
|
||||
"manage_wallets" -> Screen.MANAGE_WALLETS
|
||||
else -> null
|
||||
@@ -598,55 +679,30 @@ fun GajuRouter(
|
||||
}
|
||||
)
|
||||
}
|
||||
Screen.QR_SCANNER -> QRScannerScreen(
|
||||
onScanResult = { url ->
|
||||
try {
|
||||
val result = Grids.parse(url)
|
||||
if (result.verb == Grids.Verb.SIGN) {
|
||||
pendingSignUrl = result.url
|
||||
navigateTo(Screen.FETCHING_SIGN_REQUEST)
|
||||
|
||||
activeFetchJob = scope.launch {
|
||||
try {
|
||||
android.util.Log.i("GajuRouter", "Fetching GRIDS request from: ${result.url}")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val response = withContext(Dispatchers.IO) {
|
||||
Http.get(result.url) as? Map<String, Any?>
|
||||
}
|
||||
if (response != null) {
|
||||
pendingSignRequest = response.toGridsSignRequest()
|
||||
// Remove fetching screen and add request screen
|
||||
screenStack.removeAt(screenStack.size - 1)
|
||||
navigateTo(Screen.SIGN_REQUEST)
|
||||
} else {
|
||||
onError(context.getString(R.string.err_fetch_sig_failed))
|
||||
navigateBack()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (activeFetchJob?.isCancelled == false) {
|
||||
onError(context.getString(R.string.err_fetch_failed, e.message ?: ""))
|
||||
navigateBack()
|
||||
}
|
||||
} finally {
|
||||
activeFetchJob = null
|
||||
}
|
||||
}
|
||||
Screen.QR_SCANNER -> {
|
||||
QRScannerScreen(
|
||||
onScanResult = { processGridsUrl(it) },
|
||||
onManualEntry = {
|
||||
if (currentScannerMode == ScannerMode.GRIDS) {
|
||||
navigateTo(Screen.MANUAL_GRIDS_ENTRY)
|
||||
} else {
|
||||
pendingScanResult = result
|
||||
navigateTo(Screen.SEND_FORM)
|
||||
pendingScanResult = null
|
||||
navigateTo(Screen.SEND_FORM)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
onError(context.getString(R.string.err_invalid_grids_url, e.message ?: ""))
|
||||
}
|
||||
},
|
||||
onGenerate = { navigateTo(Screen.QR_RECEIVE) },
|
||||
onUpload = {},
|
||||
onManualEntry = {
|
||||
pendingScanResult = null
|
||||
navigateTo(Screen.SEND_FORM)
|
||||
},
|
||||
onBack = { navigateBack() },
|
||||
)
|
||||
},
|
||||
onBack = { navigateBack() },
|
||||
)
|
||||
}
|
||||
Screen.MANUAL_GRIDS_ENTRY -> {
|
||||
ManualGridsEntryScreen(
|
||||
onConfirm = { url ->
|
||||
// Remove manual entry screen and process result
|
||||
screenStack.removeAt(screenStack.size - 1)
|
||||
processGridsUrl(url)
|
||||
},
|
||||
onBack = { navigateBack() }
|
||||
)
|
||||
}
|
||||
Screen.SEND_FORM -> {
|
||||
val wallets = walletRepo.listWallets().mapNotNull { walletRepo.loadWallet(it) }
|
||||
val activeWallet = wallets.getOrNull(activeWalletIndex)
|
||||
@@ -658,22 +714,16 @@ fun GajuRouter(
|
||||
return
|
||||
}
|
||||
|
||||
val result = pendingScanResult
|
||||
val initialRecipient = result?.recipient ?: ""
|
||||
val initialAmount = if (result?.amount != null) {
|
||||
val type = GajuFormat.Type.valueOf(appState.balanceFormat)
|
||||
val unit = GajuFormat.Unit.valueOf(appState.balanceUnit)
|
||||
GajuFormat.amount(GajuFormat.standardSpec(type, unit), result.amount)
|
||||
} else ""
|
||||
val initialPayload = if (result?.payload != null) String(result.payload, Charsets.UTF_8) else ""
|
||||
|
||||
SendFormScreen(
|
||||
fromAccount = activeAccount,
|
||||
balanceFormat = GajuFormat.Type.valueOf(appState.balanceFormat),
|
||||
balanceUnit = GajuFormat.Unit.valueOf(appState.balanceUnit),
|
||||
initialRecipient = initialRecipient,
|
||||
initialAmount = initialAmount,
|
||||
initialPayload = initialPayload,
|
||||
initialRecipient = pendingRecipient,
|
||||
initialAmount = pendingAmountStr,
|
||||
initialPayload = pendingPayload,
|
||||
initialGas = pendingGas,
|
||||
initialGasPrice = pendingGasPrice,
|
||||
initialTTL = pendingTTL,
|
||||
onReview = { recipient, amountStr, payload, gas, gasPrice, ttl ->
|
||||
pendingRecipient = recipient
|
||||
pendingAmountStr = amountStr
|
||||
@@ -699,9 +749,12 @@ fun GajuRouter(
|
||||
|
||||
SendReviewScreen(
|
||||
senderLabel = activeAccount.label,
|
||||
walletName = activeWallet.name,
|
||||
networkId = activeWallet.networkId,
|
||||
recipientLabel = "Recipient",
|
||||
recipientId = pendingRecipient,
|
||||
amountStr = pendingAmountStr,
|
||||
payload = pendingPayload,
|
||||
onSend = {
|
||||
scope.launch {
|
||||
try {
|
||||
@@ -739,12 +792,31 @@ fun GajuRouter(
|
||||
client.postTx(signedTx)
|
||||
}
|
||||
|
||||
val hash = result["hash"] as? String ?: "Unknown"
|
||||
onError(context.getString(R.string.msg_tx_posted, hash))
|
||||
val hash = (result["tx_hash"] ?: result["hash"]) as? String ?: "Unknown"
|
||||
|
||||
// Success! Go back to dashboard
|
||||
screenStack.clear()
|
||||
screenStack.add(Screen.DASHBOARD)
|
||||
lastTxHash = hash
|
||||
lastTxAmount = GajuFormat.amount(
|
||||
GajuFormat.standardSpec(
|
||||
GajuFormat.Type.valueOf(appState.balanceFormat),
|
||||
GajuFormat.Unit.valueOf(appState.balanceUnit)
|
||||
),
|
||||
amountPucks
|
||||
)
|
||||
lastTxRecipient = pendingRecipient
|
||||
lastTxPayload = pendingPayload
|
||||
lastTxNetworkId = activeWallet.networkId
|
||||
lastTxSenderLabel = activeAccount.label
|
||||
lastTxWalletName = activeWallet.name
|
||||
|
||||
// 6. Schedule a balance refresh in 3 seconds
|
||||
scope.launch {
|
||||
kotlinx.coroutines.delay(3000)
|
||||
walletRepo.refreshAccount(activeWallet.id, activeAccount.id)
|
||||
appStateManager.notifyWalletsChanged()
|
||||
}
|
||||
|
||||
// Success! Go to success screen
|
||||
navigateTo(Screen.TRANSACTION_SUCCESS)
|
||||
} catch (e: Throwable) {
|
||||
val msg = e.message ?: e.toString()
|
||||
onError(context.getString(R.string.err_send_failed, msg))
|
||||
@@ -853,19 +925,18 @@ fun GajuRouter(
|
||||
onDone = { navigateBack() },
|
||||
)
|
||||
}
|
||||
Screen.EXPLORER -> {
|
||||
ExplorerScreen(
|
||||
onNavigate = { dest ->
|
||||
val screen = when (dest) {
|
||||
"dashboard" -> Screen.DASHBOARD
|
||||
"settings" -> Screen.SETTINGS
|
||||
"manage_wallets" -> Screen.MANAGE_WALLETS
|
||||
else -> null
|
||||
}
|
||||
if (screen != null) {
|
||||
screenStack.clear()
|
||||
screenStack.add(screen)
|
||||
}
|
||||
Screen.TRANSACTION_SUCCESS -> {
|
||||
TransactionSuccessScreen(
|
||||
amount = lastTxAmount,
|
||||
recipient = lastTxRecipient,
|
||||
payload = lastTxPayload,
|
||||
txHash = lastTxHash,
|
||||
senderLabel = lastTxSenderLabel,
|
||||
walletName = lastTxWalletName,
|
||||
networkId = lastTxNetworkId,
|
||||
onExit = {
|
||||
screenStack.clear()
|
||||
screenStack.add(Screen.DASHBOARD)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -138,14 +138,6 @@ fun GajuTopBar(
|
||||
},
|
||||
leadingIcon = { Icon(painterResource(R.drawable.ic_account_box), null, modifier = Modifier.size(18.dp)) }
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.menu_transactions)) },
|
||||
onClick = {
|
||||
menuExpanded = false
|
||||
onNavigate("transactions")
|
||||
},
|
||||
leadingIcon = { Icon(painterResource(R.drawable.gajumobile_icon), null, modifier = Modifier.size(18.dp), tint = Color.Unspecified) }
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.menu_settings)) },
|
||||
onClick = {
|
||||
@@ -296,6 +288,7 @@ fun SuccessLayout(
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
onProceed: () -> Unit,
|
||||
proceedText: String = stringResource(R.string.proceed_to_dashboard),
|
||||
requireRiskAcknowledgment: Boolean = true,
|
||||
) {
|
||||
var checked by remember { mutableStateOf(value = false) }
|
||||
|
||||
@@ -308,34 +301,37 @@ fun SuccessLayout(
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
.padding(24.dp),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.padding(bottom = 24.dp)
|
||||
.clickable { checked = !checked },
|
||||
) {
|
||||
Checkbox(
|
||||
checked = checked,
|
||||
onCheckedChange = { checked = it },
|
||||
colors = CheckboxDefaults.colors(
|
||||
checkedColor = MaterialTheme.colorScheme.primary,
|
||||
uncheckedColor = MaterialTheme.colorScheme.onBackground,
|
||||
),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.understand_risks_success_label),
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
)
|
||||
if (requireRiskAcknowledgment) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.padding(bottom = 24.dp)
|
||||
.clickable { checked = !checked },
|
||||
) {
|
||||
Checkbox(
|
||||
checked = checked,
|
||||
onCheckedChange = { checked = it },
|
||||
colors = CheckboxDefaults.colors(
|
||||
checkedColor = MaterialTheme.colorScheme.primary,
|
||||
uncheckedColor = MaterialTheme.colorScheme.onBackground,
|
||||
),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.understand_risks_success_label),
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
GajuButton(
|
||||
text = proceedText,
|
||||
onClick = onProceed,
|
||||
containerColor = if (checked) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant,
|
||||
contentColor = if (checked) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
containerColor = if (!requireRiskAcknowledgment || checked) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant,
|
||||
contentColor = if (!requireRiskAcknowledgment || checked) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = !requireRiskAcknowledgment || checked
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8,10 +8,13 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -57,7 +60,12 @@ fun AccountNamingScreen(
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize().padding(24.dp).safeDrawingPadding(),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.padding(24.dp)
|
||||
.safeDrawingPadding()
|
||||
.verticalScroll(rememberScrollState()),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
GajuHeader()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package swiss.qpq.gajumobile.ui.screens
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -28,6 +30,7 @@ import androidx.compose.material3.TabRowDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -65,6 +68,7 @@ fun DashboardScreen(
|
||||
onRefresh: (String, String) -> Unit,
|
||||
onNavigate: (String) -> Unit,
|
||||
) {
|
||||
val context = androidx.compose.ui.platform.LocalContext.current
|
||||
if (wallets.isEmpty()) {
|
||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
@@ -107,6 +111,14 @@ fun DashboardScreen(
|
||||
val currentWallet = wallets[walletPagerState.currentPage]
|
||||
val currentAccount = currentWallet.accounts.getOrNull(selectedAccountIndex)
|
||||
|
||||
// Automatically refresh balance after 1 second of staying on an account
|
||||
LaunchedEffect(currentAccount?.id) {
|
||||
currentAccount?.let { account ->
|
||||
kotlinx.coroutines.delay(1000)
|
||||
onRefresh(currentWallet.id, account.id)
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = { GajuTopBar(onNavigate = onNavigate) },
|
||||
) { innerPadding ->
|
||||
@@ -249,6 +261,23 @@ fun DashboardScreen(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// View on Explorer Link
|
||||
androidx.compose.material3.TextButton(
|
||||
onClick = {
|
||||
val url = "https://${currentWallet.networkId}.gajumaru.io/account/${account.gajuId}"
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
context.startActivity(intent)
|
||||
},
|
||||
modifier = Modifier.padding(bottom = 12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.view_account_in_explorer),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Balance Box
|
||||
@@ -315,6 +344,20 @@ fun DashboardScreen(
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
|
||||
currentAccount?.cachedBalance?.let { balance ->
|
||||
val timeStr = remember(balance.timestamp) {
|
||||
val instant = java.time.Instant.ofEpochMilli(balance.timestamp)
|
||||
val dateTime = java.time.LocalDateTime.ofInstant(instant, java.time.ZoneId.systemDefault())
|
||||
dateTime.format(java.time.format.DateTimeFormatter.ofPattern("HH:mm:ss"))
|
||||
}
|
||||
Text(
|
||||
text = stringResource(R.string.last_balance_check_label, timeStr),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f),
|
||||
modifier = Modifier.padding(top = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package swiss.qpq.gajumobile.ui.screens
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
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 swiss.qpq.gajumobile.R
|
||||
import swiss.qpq.gajumobile.ui.components.GajuTopBar
|
||||
|
||||
@Composable
|
||||
fun ExplorerScreen(
|
||||
onNavigate: (String) -> Unit
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = { GajuTopBar(onNavigate = onNavigate) },
|
||||
) { innerPadding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.padding(innerPadding),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.explorer_title),
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier.padding(vertical = 16.dp),
|
||||
)
|
||||
|
||||
Text(stringResource(R.string.loading_groot), color = MaterialTheme.colorScheme.primary, fontStyle = androidx.compose.ui.text.font.FontStyle.Italic)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().weight(1f).padding(horizontal = 24.dp, vertical = 8.dp),
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
shape = RoundedCornerShape(4.dp),
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Text(stringResource(R.string.explorer_content_placeholder), color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -194,6 +195,7 @@ fun ManageWalletsScreen(
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.padding(innerPadding)
|
||||
.imePadding()
|
||||
.padding(horizontal = 24.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package swiss.qpq.gajumobile.ui.screens
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
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 swiss.qpq.gajumobile.R
|
||||
import swiss.qpq.gajumobile.ui.components.GajuButton
|
||||
import swiss.qpq.gajumobile.ui.components.GajuHeader
|
||||
import swiss.qpq.gajumobile.ui.components.GajuTextField
|
||||
|
||||
@Composable
|
||||
fun ManualGridsEntryScreen(
|
||||
onConfirm: (String) -> Unit,
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
var url by remember { mutableStateOf("") }
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.imePadding()
|
||||
.padding(24.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
GajuHeader()
|
||||
|
||||
Text(
|
||||
text = "MANUAL GRIDS ENTRY",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(vertical = 24.dp)
|
||||
)
|
||||
|
||||
GajuTextField(
|
||||
value = url,
|
||||
onValueChange = { url = it },
|
||||
label = "GRIDS URL",
|
||||
placeholder = "grids://...",
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
GajuButton(
|
||||
text = "CONFIRM",
|
||||
onClick = { if (url.isNotBlank()) onConfirm(url) },
|
||||
enabled = url.isNotBlank()
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
GajuButton(
|
||||
text = stringResource(id = R.string.back_button_caps),
|
||||
onClick = onBack,
|
||||
containerColor = MaterialTheme.colorScheme.secondary,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondary
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -33,14 +33,11 @@ import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import swiss.qpq.gajumobile.R
|
||||
import swiss.qpq.gajumobile.ui.components.GajuHeader
|
||||
import swiss.qpq.gajumobile.ui.components.ScannerAction
|
||||
import swiss.qpq.gajumobile.ui.components.GajuButton
|
||||
|
||||
@Composable
|
||||
fun QRScannerScreen(
|
||||
onScanResult: (String) -> Unit,
|
||||
onGenerate: () -> Unit,
|
||||
onUpload: () -> Unit,
|
||||
onManualEntry: () -> Unit,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
@@ -114,24 +111,26 @@ fun QRScannerScreen(
|
||||
|
||||
Spacer(modifier = Modifier.weight(0.5f))
|
||||
|
||||
GajuButton(
|
||||
text = stringResource(id = R.string.manual_entry_button),
|
||||
onClick = onManualEntry,
|
||||
modifier = Modifier.padding(horizontal = 48.dp),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Row(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 48.dp),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
.padding(horizontal = 48.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
ScannerAction(label = stringResource(id = R.string.back_action), icon = R.drawable.ic_home, onClick = onBack)
|
||||
ScannerAction(label = stringResource(id = R.string.generate_qr_action), icon = R.drawable.ic_qr_code, onClick = onGenerate)
|
||||
ScannerAction(label = stringResource(id = R.string.upload_qr_action), icon = R.drawable.ic_qr_code, onClick = onUpload)
|
||||
GajuButton(
|
||||
text = stringResource(id = R.string.manual_entry_button),
|
||||
onClick = onManualEntry,
|
||||
)
|
||||
|
||||
GajuButton(
|
||||
text = stringResource(id = R.string.back_button_caps),
|
||||
onClick = onBack,
|
||||
containerColor = MaterialTheme.colorScheme.secondary,
|
||||
contentColor = MaterialTheme.colorScheme.onSecondary,
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -47,15 +48,18 @@ fun SendFormScreen(
|
||||
initialRecipient: String = "",
|
||||
initialAmount: String = "",
|
||||
initialPayload: String = "",
|
||||
initialGas: String = "20000",
|
||||
initialGasPrice: String = "1000000000",
|
||||
initialTTL: String = "500",
|
||||
onReview: (recipient: String, amount: String, payload: String, gas: String, gasPrice: String, ttl: String) -> Unit,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
var toAddress by remember { mutableStateOf(value = initialRecipient) }
|
||||
var amount by remember { mutableStateOf(value = initialAmount) }
|
||||
var payload by remember { mutableStateOf(value = initialPayload) }
|
||||
var gas by remember { mutableStateOf(value = "20000") } // Default gas
|
||||
var gasPrice by remember { mutableStateOf(value = "1000000000") } // Default gas price
|
||||
var ttl by remember { mutableStateOf(value = "500") } // Default TTL
|
||||
var gas by remember { mutableStateOf(value = initialGas) }
|
||||
var gasPrice by remember { mutableStateOf(value = initialGasPrice) }
|
||||
var ttl by remember { mutableStateOf(value = initialTTL) }
|
||||
var showAdvanced by remember { mutableStateOf(value = false) }
|
||||
|
||||
Scaffold(
|
||||
@@ -89,6 +93,7 @@ fun SendFormScreen(
|
||||
.fillMaxSize()
|
||||
.background(MaterialTheme.colorScheme.background)
|
||||
.padding(innerPadding)
|
||||
.imePadding()
|
||||
.padding(horizontal = 24.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
|
||||
@@ -40,9 +40,12 @@ import swiss.qpq.gajumobile.ui.components.GajuHeader
|
||||
@Composable
|
||||
fun SendReviewScreen(
|
||||
senderLabel: String,
|
||||
walletName: String,
|
||||
networkId: String,
|
||||
recipientLabel: String,
|
||||
recipientId: String,
|
||||
amountStr: String,
|
||||
payload: String = "",
|
||||
onSend: () -> Unit,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
@@ -108,7 +111,16 @@ fun SendReviewScreen(
|
||||
)
|
||||
|
||||
Text(stringResource(id = R.string.sending_from_label), color = MaterialTheme.colorScheme.onSurfaceVariant, fontSize = 12.sp)
|
||||
Text(senderLabel, color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold)
|
||||
Text(
|
||||
text = "$senderLabel ($walletName)",
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.on_network_label, networkId),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
@@ -135,6 +147,12 @@ fun SendReviewScreen(
|
||||
Text(stringResource(id = R.string.payment_summary_to), fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
Text(recipientId.take(12) + "...", fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
|
||||
if (payload.isNotBlank()) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(stringResource(id = R.string.payload_label), fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
Text(payload, fontSize = 12.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onBackground)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(stringResource(id = R.string.cannot_be_undone_warning), fontWeight = FontWeight.ExtraBold, color = MaterialTheme.colorScheme.error)
|
||||
Text(stringResource(id = R.string.proceed_confirmation_question), fontStyle = androidx.compose.ui.text.font.FontStyle.Italic, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package swiss.qpq.gajumobile.ui.screens
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
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.text.style.TextAlign
|
||||
@@ -16,26 +21,58 @@ import swiss.qpq.gajumobile.ui.components.SuccessLayout
|
||||
|
||||
@Composable
|
||||
fun TransactionSuccessScreen(
|
||||
amount: String,
|
||||
recipient: String,
|
||||
payload: String,
|
||||
txHash: String,
|
||||
senderLabel: String,
|
||||
walletName: String,
|
||||
networkId: String,
|
||||
onExit: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
SuccessLayout(
|
||||
title = stringResource(R.string.send_title),
|
||||
proceedText = stringResource(R.string.exit_button_caps),
|
||||
onProceed = onExit,
|
||||
requireRiskAcknowledgment = false,
|
||||
content = {
|
||||
Text(stringResource(R.string.transaction_success_title), color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold)
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Text(stringResource(R.string.transaction_success_payment_prefix), fontSize = 14.sp, color = MaterialTheme.colorScheme.onBackground)
|
||||
Text("木 22,980.78991", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary)
|
||||
Text(amount, fontSize = 24.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary)
|
||||
Text(stringResource(R.string.transaction_success_to), fontSize = 14.sp, color = MaterialTheme.colorScheme.onBackground)
|
||||
Text("ak_9jzm...", fontSize = 12.sp, color = MaterialTheme.colorScheme.onBackground)
|
||||
Text(recipient, fontSize = 12.sp, color = MaterialTheme.colorScheme.onBackground, maxLines = 1)
|
||||
|
||||
if (payload.isNotBlank()) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(stringResource(id = R.string.payload_label), fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
Text(payload, fontSize = 12.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onBackground)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Text(stringResource(R.string.transaction_success_subtracted_msg), textAlign = TextAlign.Center, fontSize = 12.sp, color = MaterialTheme.colorScheme.onBackground)
|
||||
Text(
|
||||
text = stringResource(R.string.transaction_success_subtracted_msg, senderLabel, walletName, networkId),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 12.sp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
Text(stringResource(R.string.transaction_success_track_hint), fontSize = 12.sp, color = MaterialTheme.colorScheme.onBackground)
|
||||
Text(stringResource(R.string.view_transaction_on_chain), color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold, fontSize = 12.sp)
|
||||
Text(
|
||||
text = stringResource(R.string.view_transaction_on_chain),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 12.sp,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
val url = "https://$networkId.gajumaru.io/tx/$txHash"
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
context.startActivity(intent)
|
||||
}
|
||||
.padding(8.dp)
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
<!-- General / Shared -->
|
||||
<string name="menu_manage_wallets">Wallets verwalten</string>
|
||||
<string name="menu_transactions">Transaktionen</string>
|
||||
<string name="menu_settings">Einstellungen</string>
|
||||
<string name="menu_environment_info">Umgebungsinformationen</string>
|
||||
<string name="tap_to_reveal">ZUM ANZEIGEN TIPPEN</string>
|
||||
@@ -173,7 +172,7 @@
|
||||
<string name="transaction_success_title">Transaktion erfolgreich!</string>
|
||||
<string name="transaction_success_payment_prefix">Sie haben erfolgreich eine Zahlung gesendet von</string>
|
||||
<string name="transaction_success_to">an</string>
|
||||
<string name="transaction_success_subtracted_msg">Der Betrag wurde vom TÄGLICHEN Konto in Ihrer PRIMÄREN WALLET abgezogen.</string>
|
||||
<string name="transaction_success_subtracted_msg">Der Betrag wurde vom %1$s-Konto in Ihrer %2$s-Wallet auf %3$s abgebucht.</string>
|
||||
<string name="transaction_success_track_hint">Sie können diese Transaktion hier on-chain verfolgen.</string>
|
||||
<string name="view_transaction_on_chain">TRANSAKTION ON-CHAIN ANZEIGEN</string>
|
||||
<string name="understand_risks_success_label">Ich verstehe und übernehme alle Risiken.</string>
|
||||
@@ -246,4 +245,6 @@
|
||||
<string name="confirm_delete_button">LÖSCHEN\nBESTÄTIGEN</string>
|
||||
<string name="wallet">WALLET</string>
|
||||
<string name="account">KONTO</string>
|
||||
<string name="view_account_in_explorer">KONTO IM EXPLORER ANZEIGEN</string>
|
||||
<string name="last_balance_check_label">Letzte Prüfung: %1$s</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
<!-- General / Shared -->
|
||||
<string name="menu_manage_wallets">Gérer les portefeuilles</string>
|
||||
<string name="menu_transactions">Transactions</string>
|
||||
<string name="menu_settings">Paramètres</string>
|
||||
<string name="menu_environment_info">Informations sur l\'environnement</string>
|
||||
<string name="tap_to_reveal">APPUYER POUR RÉVÉLER</string>
|
||||
@@ -173,7 +172,7 @@
|
||||
<string name="transaction_success_title">Transaction réussie !</string>
|
||||
<string name="transaction_success_payment_prefix">Vous avez envoyé avec succès un paiement de</string>
|
||||
<string name="transaction_success_to">à</string>
|
||||
<string name="transaction_success_subtracted_msg">Le montant a été déduit du compte QUOTIDIEN de votre PORTEFEUILLE PRINCIPAL.</string>
|
||||
<string name="transaction_success_subtracted_msg">Le montant a été déduit du compte %1$s de votre portefeuille %2$s sur %3$s.</string>
|
||||
<string name="transaction_success_track_hint">Vous pouvez suivre cette transaction sur la chaîne ici.</string>
|
||||
<string name="view_transaction_on_chain">VOIR LA TRANSACTION SUR LA CHAÎNE</string>
|
||||
<string name="understand_risks_success_label">Je comprends et assume pleinement les risques.</string>
|
||||
@@ -246,4 +245,6 @@
|
||||
<string name="confirm_delete_button">CONFIRMER LA\nSUPPRESSION</string>
|
||||
<string name="wallet">PORTEFEUILLE</string>
|
||||
<string name="account">COMPTE</string>
|
||||
<string name="view_account_in_explorer">VOIR LE COMPTE DANS L\'EXPLORATEUR</string>
|
||||
<string name="last_balance_check_label">Dernière vérification: %1$s</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
<!-- General / Shared -->
|
||||
<string name="menu_manage_wallets">Gestisci portafogli</string>
|
||||
<string name="menu_transactions">Transazioni</string>
|
||||
<string name="menu_settings">Impostazioni</string>
|
||||
<string name="menu_environment_info">Informazioni sull\'ambiente</string>
|
||||
<string name="tap_to_reveal">TOCCA PER RIVELARE</string>
|
||||
@@ -173,7 +172,7 @@
|
||||
<string name="transaction_success_title">Transazione riuscita!</string>
|
||||
<string name="transaction_success_payment_prefix">Hai inviato con successo un pagamento di</string>
|
||||
<string name="transaction_success_to">a</string>
|
||||
<string name="transaction_success_subtracted_msg">L\'importo è stato detratto dal conto GIORNALIERO nel tuo PORTAFOGLIO PRINCIPALE.</string>
|
||||
<string name="transaction_success_subtracted_msg">L\'importo è stato detratto dal conto %1$s nel tuo portafoglio %2$s su %3$s.</string>
|
||||
<string name="transaction_success_track_hint">Puoi tracciare questa transazione on-chain qui.</string>
|
||||
<string name="view_transaction_on_chain">VISUALIZZA TRANSAZIONE ON-CHAIN</string>
|
||||
<string name="understand_risks_success_label">Comprendo e mi assumo pienamente i rischi.</string>
|
||||
@@ -246,4 +245,6 @@
|
||||
<string name="confirm_delete_button">CONFERMA\nELIMINA</string>
|
||||
<string name="wallet">PORTAFOGLIO</string>
|
||||
<string name="account">ACCOUNT</string>
|
||||
<string name="view_account_in_explorer">VISUALIZZA ACCOUNT NELL\'EXPLORER</string>
|
||||
<string name="last_balance_check_label">Ultima verifica: %1$s</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
<!-- General / Shared -->
|
||||
<string name="menu_manage_wallets">ウォレットを管理</string>
|
||||
<string name="menu_transactions">トランザクション</string>
|
||||
<string name="menu_settings">設定</string>
|
||||
<string name="menu_environment_info">環境情報</string>
|
||||
<string name="tap_to_reveal">タップして表示</string>
|
||||
@@ -107,11 +106,6 @@
|
||||
<string name="network_mainnet">メインネット</string>
|
||||
<string name="network_testnet">テストネット</string>
|
||||
|
||||
<!-- ExplorerScreen -->
|
||||
<string name="explorer_title">トランザクション</string>
|
||||
<string name="loading_groot">Grootを読み込み中</string>
|
||||
<string name="explorer_content_placeholder">Gajuエクスプローラーのコンテンツ</string>
|
||||
|
||||
<!-- SetupChoiceScreen -->
|
||||
<string name="create_account_button">アカウントを作成</string>
|
||||
<string name="recover_account_button">アカウントを復元</string>
|
||||
@@ -173,7 +167,7 @@
|
||||
<string name="transaction_success_title">トランザクション成功!</string>
|
||||
<string name="transaction_success_payment_prefix">以下の送金に成功しました</string>
|
||||
<string name="transaction_success_to">送信先</string>
|
||||
<string name="transaction_success_subtracted_msg">金額はプライマリウォレットの日常アカウントから差し引かれました。</string>
|
||||
<string name="transaction_success_subtracted_msg">金額は%3$s上の%2$sウォレットの%1$sアカウントから差し引かれました。</string>
|
||||
<string name="transaction_success_track_hint">ここでチェーン上のトランザクションを追跡できます。</string>
|
||||
<string name="view_transaction_on_chain">チェーン上でトランザクションを表示</string>
|
||||
<string name="understand_risks_success_label">私はリスクを理解し、完全に引き受けます。</string>
|
||||
@@ -246,4 +240,6 @@
|
||||
<string name="confirm_delete_button">削除を確定</string>
|
||||
<string name="wallet">ウォレット</string>
|
||||
<string name="account">アカウント</string>
|
||||
<string name="view_account_in_explorer">エクスプローラーでアカウントを表示</string>
|
||||
<string name="last_balance_check_label">最終確認: %1$s</string>
|
||||
</resources>
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
<!-- General / Shared -->
|
||||
<string name="menu_manage_wallets">Manage Wallets</string>
|
||||
<string name="menu_transactions">Transactions</string>
|
||||
<string name="menu_settings">Settings</string>
|
||||
<string name="menu_environment_info">Environment Info</string>
|
||||
<string name="tap_to_reveal">TAP TO REVEAL</string>
|
||||
@@ -89,6 +88,7 @@
|
||||
<string name="balance_label">BALANCE</string>
|
||||
<string name="on_network_label">ON %1$s</string>
|
||||
<string name="refresh_balance_content_desc">Refresh Balance</string>
|
||||
<string name="last_balance_check_label">Last check at %1$s</string>
|
||||
<string name="account_settings_content_desc">Account Settings</string>
|
||||
<string name="send_action">Send</string>
|
||||
<string name="grids_action">GRIDS</string>
|
||||
@@ -107,11 +107,6 @@
|
||||
<string name="network_mainnet">Mainnet</string>
|
||||
<string name="network_testnet">Testnet</string>
|
||||
|
||||
<!-- ExplorerScreen -->
|
||||
<string name="explorer_title">Transactions</string>
|
||||
<string name="loading_groot">Loading Groot</string>
|
||||
<string name="explorer_content_placeholder">Gaju Explorer Content</string>
|
||||
|
||||
<!-- SetupChoiceScreen -->
|
||||
<string name="create_account_button">Create Account</string>
|
||||
<string name="recover_account_button">Recover Account</string>
|
||||
@@ -173,9 +168,10 @@
|
||||
<string name="transaction_success_title">Transaction Successful!</string>
|
||||
<string name="transaction_success_payment_prefix">You have successfully sent a payment of</string>
|
||||
<string name="transaction_success_to">to</string>
|
||||
<string name="transaction_success_subtracted_msg">The amount has been subtracted from the DAILY account in your PRIMARY WALLET.</string>
|
||||
<string name="transaction_success_subtracted_msg">The amount has been subtracted from the %1$s account in your %2$s wallet on %3$s.</string>
|
||||
<string name="transaction_success_track_hint">You can track this transaction on-chain here.</string>
|
||||
<string name="view_transaction_on_chain">VIEW TRANSACTION ON-CHAIN</string>
|
||||
<string name="view_account_in_explorer">VIEW ACCOUNT IN EXPLORER</string>
|
||||
<string name="understand_risks_success_label">I understand and fully assume the risks.</string>
|
||||
|
||||
<!-- QRScannerScreen -->
|
||||
|
||||
Reference in New Issue
Block a user