commit 2b307902d1b77f16a90e095931206d59f33578d4
parent bd4e0958bfa9c4ac42d92f2feb710efc98ad53ec
Author: Iván Ávalos <avalos@disroot.org>
Date: Fri, 25 Oct 2024 21:31:18 +0200
[wallet] Disable actions when wallet is empty
Diffstat:
3 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/wallet/src/main/java/net/taler/wallet/MainFragment.kt b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
@@ -103,6 +103,12 @@ class MainFragment: Fragment() {
val settingsFragmentState = rememberFragmentState()
+ val context = LocalContext.current
+ val balanceState by model.balanceManager.state.observeAsState(BalanceState.None)
+ val selectedScope by model.transactionManager.selectedScope.collectAsStateLifecycleAware()
+ val txResult by remember(selectedScope) { model.transactionManager.transactionsFlow(selectedScope) }.collectAsStateLifecycleAware()
+ val selectedSpec = remember(selectedScope) { selectedScope?.let { model.balanceManager.getSpecForScopeInfo(it) } }
+
Scaffold(
bottomBar = {
NavigationBar {
@@ -149,12 +155,6 @@ class MainFragment: Fragment() {
}
}
) { innerPadding ->
- val context = LocalContext.current
- val balanceState by model.balanceManager.state.observeAsState(BalanceState.None)
- val selectedScope by model.transactionManager.selectedScope.collectAsStateLifecycleAware()
- val txResult by remember(selectedScope) { model.transactionManager.transactionsFlow(selectedScope) }.collectAsStateLifecycleAware()
- val selectedSpec = remember(selectedScope) { selectedScope?.let { model.balanceManager.getSpecForScopeInfo(it) } }
-
LaunchedEffect(tab, selectedScope) {
setTitle(tab, selectedScope)
}
@@ -197,10 +197,15 @@ class MainFragment: Fragment() {
}
}
+ val disableActions = remember(balanceState) {
+ (balanceState as? BalanceState.Success)?.balances?.isEmpty() ?: true
+ }
+
TalerActionsModal(
showSheet = showSheet,
sheetState = sheetState,
onDismiss = { showSheet = false },
+ disableActions = disableActions,
onSend = this@MainFragment::onSend,
onReceive = this@MainFragment::onReceive,
onScanQr = this@MainFragment::onScanQr,
@@ -281,6 +286,7 @@ fun SettingsView(
fun TalerActionsModal(
showSheet: Boolean,
sheetState: SheetState,
+ disableActions: Boolean,
onDismiss: () -> Unit,
onSend: () -> Unit,
onReceive: () -> Unit,
@@ -308,12 +314,14 @@ fun TalerActionsModal(
icon = R.drawable.transaction_p2p_outgoing,
title = R.string.transactions_send_funds,
onClick = onSend,
+ enabled = !disableActions,
)
GridMenuItem(
icon = R.drawable.transaction_p2p_incoming,
title = R.string.transactions_receive_funds,
onClick = onReceive,
+ enabled = !disableActions,
)
GridMenuItem(
@@ -326,12 +334,14 @@ fun TalerActionsModal(
icon = R.drawable.transaction_deposit,
title = R.string.send_deposit_button_label,
onClick = onDeposit,
+ enabled = !disableActions
)
GridMenuItem(
icon = R.drawable.transaction_withdrawal,
title = R.string.withdraw_button_label,
onClick = onWithdraw,
+ enabled = !disableActions,
)
GridMenuItem(
diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt b/wallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt
@@ -19,12 +19,15 @@ package net.taler.wallet.balances
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.Button
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard
@@ -34,6 +37,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@@ -48,6 +52,7 @@ import net.taler.wallet.balances.ScopeInfo.Global
import net.taler.wallet.cleanExchange
import net.taler.wallet.compose.LoadingScreen
import net.taler.wallet.compose.TalerSurface
+import net.taler.wallet.launchInAppBrowser
import net.taler.wallet.transactions.Transaction
import net.taler.wallet.transactions.TransactionsComposable
import net.taler.wallet.transactions.TransactionsResult
@@ -68,8 +73,8 @@ fun BalancesComposable(
is BalanceState.None -> {}
is BalanceState.Loading -> LoadingScreen()
is BalanceState.Error -> WithdrawalError(state.error)
- is BalanceState.Success -> if (selectedScope == null) {
- if (state.balances.isNotEmpty()) {
+ is BalanceState.Success -> if (state.balances.isNotEmpty()) {
+ if (selectedScope == null) {
LazyColumn(Modifier.fillMaxSize()) {
items(state.balances, key = { it.scopeInfo.hashCode() }) { balance ->
BalanceRow(balance) {
@@ -78,23 +83,23 @@ fun BalancesComposable(
}
}
} else {
- EmptyBalancesComposable()
+ val balance = remember(state.balances, selectedScope) {
+ state.balances.find { it.scopeInfo == selectedScope }
+ }
+
+ balance?.let {
+ TransactionsComposable(
+ balance = it,
+ currencySpec = selectedCurrencySpec,
+ txResult = txResult,
+ onTransactionClick = onTransactionClicked,
+ onTransactionsDelete = onTransactionsDelete,
+ onShowBalancesClicked = onShowBalancesClicked,
+ )
+ } ?: error("no balance matching scopeInfo")
}
} else {
- val balance = remember(state.balances, selectedScope) {
- state.balances.find { it.scopeInfo == selectedScope }
- }
-
- balance?.let {
- TransactionsComposable(
- balance = it,
- currencySpec = selectedCurrencySpec,
- txResult = txResult,
- onTransactionClick = onTransactionClicked,
- onTransactionsDelete = onTransactionsDelete,
- onShowBalancesClicked = onShowBalancesClicked,
- )
- } ?: error("no balance matching scopeInfo")
+ EmptyBalancesComposable()
}
}
}
@@ -173,16 +178,27 @@ fun BalanceRow(
@Composable
fun EmptyBalancesComposable() {
- Box(
+ Column(
modifier = Modifier.fillMaxSize(),
- contentAlignment = Alignment.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center,
) {
+ val context = LocalContext.current
+
// TODO: render hyperlink!
Text(
stringResource(R.string.balances_empty_state),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyMedium,
)
+
+ Spacer(Modifier.height(32.dp))
+
+ Button(onClick = {
+ launchInAppBrowser(context, context.getString(R.string.balances_empty_demo_url))
+ }) {
+ Text(stringResource(R.string.balances_empty_get_money))
+ }
}
}
diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml
@@ -115,6 +115,8 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card
<string name="balance_scope_auditor">Auditor: %1$s</string>
<string name="balance_scope_exchange">From %1$s</string>
<string name="balances_empty_state">There is no digital cash in your wallet.\n\nYou can get test money from the demo bank:\n\nhttps://bank.demo.taler.net</string>
+ <string name="balances_empty_demo_url">https://bank.demo.taler.net</string>
+ <string name="balances_empty_get_money">Get test money</string>
<string name="balances_inbound_amount">+%1$s inbound</string>
<string name="balances_outbound_amount">-%1$s outbound</string>
<string name="balances_title">Balances</string>