commit 8642627a48b4b10a63d2966391fae57526e508f0 parent e8dd3a991b89626c36175d62a2dbca632819fded Author: Iván Ávalos <avalos@disroot.org> Date: Sat, 16 May 2026 15:18:53 +0200 [wallet] fix scroll/vertical constraints to prevent crashes Diffstat:
24 files changed, 283 insertions(+), 190 deletions(-)
diff --git a/wallet/src/main/java/net/taler/wallet/HandleUriScreen.kt b/wallet/src/main/java/net/taler/wallet/HandleUriScreen.kt @@ -18,9 +18,8 @@ package net.taler.wallet import android.net.Uri import android.util.Log +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -52,6 +51,7 @@ fun HandleUriScreen( uriString: String, onNavigate: NavigateCallback, onNavigateBack: () -> Unit, + onShowError: (error: TalerErrorInfo) -> Unit, ) { var processing by remember { mutableStateOf(false) } var errorInfo by remember { mutableStateOf<TalerErrorInfo?>(null) } @@ -157,21 +157,21 @@ fun HandleUriScreen( } } - val currentError = errorInfo - if (currentError != null) { - ErrorComposable( - error = currentError, - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()), - devMode = devMode, - onClose = onNavigateBack, - ) - } else if (networkStatus == true) { - LoadingScreen() - } else { - RetryScreen { - processTalerUri() + LaunchedEffect(errorInfo) { + val currentError = errorInfo + if (currentError != null) { + onShowError(currentError) + onNavigateBack() + } + } + + Box(Modifier.fillMaxSize()) { + if (networkStatus == true) { + LoadingScreen() + } else { + RetryScreen { + processTalerUri() + } } } } diff --git a/wallet/src/main/java/net/taler/wallet/WalletNavHost.kt b/wallet/src/main/java/net/taler/wallet/WalletNavHost.kt @@ -22,6 +22,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.Modifier @@ -117,7 +118,7 @@ fun WalletNavHost( NavHost( navController = navController, startDestination = startDestination, - modifier = modifier, + modifier = modifier.fillMaxSize(), enterTransition = { fadeIn(tween(250)) }, @@ -147,6 +148,7 @@ fun WalletNavHost( uriString = dest.uri, onNavigate = onNavigate, onNavigateBack = onNavigateBack, + onShowError = onShowError, ) } composable<WalletDestination.PromptWithdraw> { backStackEntry -> diff --git a/wallet/src/main/java/net/taler/wallet/accounts/AddAccountComposable.kt b/wallet/src/main/java/net/taler/wallet/accounts/AddAccountComposable.kt @@ -23,9 +23,7 @@ import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Edit @@ -84,9 +82,7 @@ fun AddAccountComposable( return ErrorComposable( error = TalerErrorInfo.makeCustomError( stringResource(R.string.send_deposit_no_methods_error)), - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()), + modifier = Modifier.fillMaxSize(), devMode = false, onClose = onClose, ) diff --git a/wallet/src/main/java/net/taler/wallet/accounts/AddBankAccountScreen.kt b/wallet/src/main/java/net/taler/wallet/accounts/AddBankAccountScreen.kt @@ -16,6 +16,7 @@ package net.taler.wallet.accounts +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -65,6 +66,7 @@ fun AddBankAccountScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), onNavigateBack = onNavigateBack, title = { if (bankAccountId != null) { diff --git a/wallet/src/main/java/net/taler/wallet/accounts/BankAccountsScreen.kt b/wallet/src/main/java/net/taler/wallet/accounts/BankAccountsScreen.kt @@ -23,8 +23,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AccountBalance import androidx.compose.material.icons.filled.Add @@ -89,6 +87,7 @@ fun BankAccountsScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.settings_bank_accounts)) }, onNavigateBack = onNavigateBack, floatingActionButton = { @@ -131,7 +130,6 @@ fun BankAccountsScreen( modifier = Modifier .fillMaxSize() .padding(paddingValues) - .verticalScroll(rememberScrollState()) ) } } diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt b/wallet/src/main/java/net/taler/wallet/balances/BalancesComposable.kt @@ -29,10 +29,10 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight +import androidx.compose.material.icons.filled.Autorenew +import androidx.compose.material.icons.filled.Percent import androidx.compose.material3.Badge import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -73,6 +73,8 @@ fun BalancesComposable( onBalanceClicked: (balance: BalanceItem) -> Unit, onPendingClicked: (balance: BalanceItem) -> Unit, onStatementClicked: (host: String) -> Unit, + onShowDiscounts: () -> Unit, + onShowPasses: () -> Unit, ) { if (state.showWelcome()) { EmptyBalancesComposable( @@ -89,9 +91,7 @@ fun BalancesComposable( is BalanceState.Loading -> LoadingScreen() is BalanceState.Error -> ErrorComposable(state.error, devMode = devMode, - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState())) + modifier = Modifier.fillMaxSize()) is BalanceState.Success -> LazyColumn( Modifier .consumeWindowInsets(innerPadding) @@ -116,6 +116,38 @@ fun BalancesComposable( onClick = { onStatementClicked(statement.donauBaseUrl) }, ) } + + stickyHeader { + SectionHeader { Text(stringResource(R.string.balances_section_tokens)) } + } + + item { + OutlinedCard(Modifier.cardPaddings()) { + ListItem( + modifier = Modifier.clickable { onShowDiscounts() }, + leadingContent = { Icon(Icons.Default.Percent, contentDescription = null) }, + headlineContent = { + Text( + stringResource(R.string.discounts_title), + style = MaterialTheme.typography.titleMedium, + ) + }, + ) + } + } + + item { + OutlinedCard(Modifier.cardPaddings()) { + ListItem( + modifier = Modifier.clickable { onShowPasses() }, + leadingContent = { Icon(Icons.Default.Autorenew, contentDescription = null) }, + headlineContent = { + Text(stringResource(R.string.passes_title), + style = MaterialTheme.typography.titleMedium) + } + ) + } + } } else -> {} @@ -325,6 +357,8 @@ fun BalancesComposablePreview() { onBalanceClicked = {}, onPendingClicked = {}, onStatementClicked = {}, + onShowDiscounts = {}, + onShowPasses = {}, ) } } @@ -344,6 +378,8 @@ fun BalancesComposableErrorPreview() { onBalanceClicked = {}, onPendingClicked = {}, onStatementClicked = {}, + onShowDiscounts = {}, + onShowPasses = {}, ) } } @@ -362,6 +398,8 @@ fun BalancesComposableEmptyPreview() { onBalanceClicked = {}, onPendingClicked = {}, onStatementClicked = {}, + onShowDiscounts = {}, + onShowPasses = {}, ) } } \ No newline at end of file diff --git a/wallet/src/main/java/net/taler/wallet/compose/GlobalScaffold.kt b/wallet/src/main/java/net/taler/wallet/compose/GlobalScaffold.kt @@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.exclude +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding @@ -62,6 +63,7 @@ fun GlobalScaffold( actions: @Composable RowScope.() -> Unit = {}, floatingActionButton: @Composable () -> Unit = {}, bottomBar: @Composable () -> Unit = {}, + tabs: @Composable () -> Unit = {}, snackbarHost: @Composable () -> Unit = {}, contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets.exclude( WindowInsets.systemBars.only(WindowInsetsSides.Bottom), @@ -78,6 +80,7 @@ fun GlobalScaffold( Scaffold( modifier = modifier + .fillMaxSize() .nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { Column { @@ -116,6 +119,8 @@ fun GlobalScaffold( ) } + tabs() + if (online != null && !online.value) Text( text = stringResource(R.string.offline_banner), textAlign = TextAlign.Center, diff --git a/wallet/src/main/java/net/taler/wallet/donau/DonauStatementScreen.kt b/wallet/src/main/java/net/taler/wallet/donau/DonauStatementScreen.kt @@ -17,8 +17,6 @@ package net.taler.wallet.donau import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -56,6 +54,7 @@ fun DonauStatementScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), onNavigateBack = onNavigateBack, title = { Text(stringResource(R.string.donau_statement_title)) }, ) { paddingValues -> @@ -67,8 +66,7 @@ fun DonauStatementScreen( error = s.error, modifier = Modifier .fillMaxSize() - .padding(paddingValues) - .verticalScroll(rememberScrollState()), + .padding(paddingValues), devMode = devMode, ) diff --git a/wallet/src/main/java/net/taler/wallet/donau/SetDonauScreen.kt b/wallet/src/main/java/net/taler/wallet/donau/SetDonauScreen.kt @@ -80,6 +80,7 @@ fun SetDonauScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), onNavigateBack = onNavigateBack, title = { Text(stringResource(R.string.donau_title)) }, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt @@ -82,6 +82,7 @@ fun ExchangeListScreen( GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), onNavigateBack = onNavigateBack, title = { Text(stringResource(R.string.exchange_list_title)) }, floatingActionButton = { diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeShoppingScreen.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeShoppingScreen.kt @@ -18,6 +18,7 @@ package net.taler.wallet.exchanges import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -72,6 +73,7 @@ fun ExchangeShoppingScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), onNavigateBack = onNavigateBack, ) { paddingValues -> Box(Modifier.padding(paddingValues)) { diff --git a/wallet/src/main/java/net/taler/wallet/main/MainActivity.kt b/wallet/src/main/java/net/taler/wallet/main/MainActivity.kt @@ -133,6 +133,7 @@ class MainActivity : FragmentActivity() { WalletNavHost( navController = navController, model = model, + modifier = Modifier.fillMaxSize(), launchUri = launchUri, onScanQr = { model.scanCode() }, onFulfillPayment = { url: String -> launchInAppBrowser(this@MainActivity, url) }, diff --git a/wallet/src/main/java/net/taler/wallet/main/MainScreen.kt b/wallet/src/main/java/net/taler/wallet/main/MainScreen.kt @@ -19,6 +19,7 @@ package net.taler.wallet.main import android.content.ClipboardManager import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons @@ -139,6 +140,7 @@ fun MainScreen( GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = tabTitle?.let { { Text(it) } }, navigationIcon = if (selectionMode) { { @@ -259,6 +261,7 @@ fun MainScreen( when (tab) { MainTab.ASSETS -> AnimatedContent( targetState = viewMode, + modifier = Modifier.fillMaxSize(), label = "MainViewMode", ) { targetViewMode -> when (targetViewMode) { diff --git a/wallet/src/main/java/net/taler/wallet/payment/PayTemplateScreen.kt b/wallet/src/main/java/net/taler/wallet/payment/PayTemplateScreen.kt @@ -17,6 +17,7 @@ package net.taler.wallet.payment import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -87,6 +88,7 @@ fun PayTemplateScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.payment_pay_template_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentComposable.kt b/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentComposable.kt @@ -30,11 +30,10 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.bringIntoViewRequester -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Autorenew import androidx.compose.material.icons.filled.Error @@ -133,51 +132,56 @@ fun PromptPaymentComposable( .fillMaxSize() .imePadding(), ) { - Column( + var orderExpanded by rememberSaveable { + mutableStateOf(contractTerms is ContractTerms.V0) + } + var choicesExpanded by rememberSaveable { mutableStateOf(true) } + var selectedIndex by rememberSaveable { mutableIntStateOf(status.defaultChoiceIndex ?: 0) } + var donauStatus: DonauStatus by remember { mutableStateOf(DonauStatus.Unavailable) } + + LazyColumn( Modifier .weight(1f) - .verticalScroll(rememberScrollState()) .fillMaxWidth(), ) { - MerchantSection(contractTerms, onClickImage) + item { MerchantSection(contractTerms, onClickImage) } // REVIEW ORDER SECTION - var orderExpanded by rememberSaveable { - mutableStateOf(contractTerms is ContractTerms.V0) - } - - ExpandableSection( - expanded = orderExpanded, - setExpanded = { orderExpanded = it }, - header = { Text(stringResource(R.string.payment_section_review)) }, - ) { - OrderSection(contractTerms, onClickImage) + item { + ExpandableSection( + expanded = orderExpanded, + setExpanded = { orderExpanded = it }, + header = { Text(stringResource(R.string.payment_section_review)) }, + ) { + OrderSection(contractTerms, onClickImage) + } } // PAYMENT OPTIONS SECTION if (contractTerms is ContractTerms.V1) { - var choicesExpanded by rememberSaveable { mutableStateOf(true) } - var selectedIndex by rememberSaveable { mutableIntStateOf(status.defaultChoiceIndex ?: 0) } - var donauStatus: DonauStatus by remember { mutableStateOf(DonauStatus.Unavailable) } - ExpandableSection( - expanded = choicesExpanded, - setExpanded = { choicesExpanded = it }, - header = { Text(stringResource(R.string.payment_section_choices)) }, - ) { - ChoicesSection( - status = status, - tokenFamilies = contractTerms.tokenFamilies, - selectedIndex = selectedIndex, - merchantBaseUrl = contractTerms.merchantBaseUrl, - onSelect = { index -> selectedIndex = index }, - onConfirm = onConfirm, - donauStatus = donauStatus, - onSetupDonau = onSetupDonau, - ) + item { + ExpandableSection( + expanded = choicesExpanded, + setExpanded = { choicesExpanded = it }, + header = { Text(stringResource(R.string.payment_section_choices)) }, + ) { + ChoicesSection( + status = status, + tokenFamilies = contractTerms.tokenFamilies, + selectedIndex = selectedIndex, + merchantBaseUrl = contractTerms.merchantBaseUrl, + onSelect = { index -> selectedIndex = index }, + onConfirm = onConfirm, + donauStatus = donauStatus, + onSetupDonau = onSetupDonau, + ) + } } - LaunchedEffect(selectedIndex) { - donauStatus = checkDonauStatus(selectedIndex) + item { + LaunchedEffect(selectedIndex) { + donauStatus = checkDonauStatus(selectedIndex) + } } } } diff --git a/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentScreen.kt b/wallet/src/main/java/net/taler/wallet/payment/PromptPaymentScreen.kt @@ -20,6 +20,7 @@ import android.graphics.Bitmap import android.util.Log import androidx.compose.foundation.Image import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Card @@ -86,6 +87,7 @@ fun PromptPaymentScreen( GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.payment_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/peer/IncomingPullPaymentScreen.kt b/wallet/src/main/java/net/taler/wallet/peer/IncomingPullPaymentScreen.kt @@ -16,6 +16,7 @@ package net.taler.wallet.peer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -60,6 +61,7 @@ fun IncomingPullPaymentScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.pay_peer_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/peer/IncomingPushPaymentScreen.kt b/wallet/src/main/java/net/taler/wallet/peer/IncomingPushPaymentScreen.kt @@ -16,6 +16,7 @@ package net.taler.wallet.peer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -69,6 +70,7 @@ fun IncomingPushPaymentScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.receive_peer_payment_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullScreen.kt b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPullScreen.kt @@ -16,6 +16,7 @@ package net.taler.wallet.peer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -83,6 +84,7 @@ fun OutgoingPullScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.receive_peer_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushScreen.kt b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushScreen.kt @@ -16,6 +16,7 @@ package net.taler.wallet.peer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -76,6 +77,7 @@ fun OutgoingPushScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.send_peer_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/settings/PerformanceStatsScreen.kt b/wallet/src/main/java/net/taler/wallet/settings/PerformanceStatsScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed @@ -70,6 +71,7 @@ fun PerformanceStatsScreen( TalerSurface { GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.performance_stats_title)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailScreen.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailScreen.kt @@ -19,9 +19,11 @@ package net.taler.wallet.transactions import android.content.Context import android.util.Log import androidx.compose.foundation.basicMarquee +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -118,142 +120,164 @@ fun TransactionDetailScreen( onNavigateBack = onNavigateBack, ) { paddingValues -> val t by transactionManager.selectedTransaction.collectAsStateLifecycleAware() - val modifier = Modifier.padding(paddingValues) - when (destination) { - is WalletDestination.TransactionPayment -> { - (t as? TransactionPayment)?.let { tx -> - TransactionPaymentComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - onFulfill = { url -> - launchInAppBrowser(context, url) - }, - onTransition = { action -> - handleTransactionAction(tx, action, model, onNavigateBack) - } - ) + val modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + Box(Modifier.fillMaxSize()) { + when (destination) { + is WalletDestination.TransactionPayment -> { + (t as? TransactionPayment)?.let { tx -> + TransactionPaymentComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), + onFulfill = { url -> + launchInAppBrowser(context, url) + }, + onTransition = { action -> + handleTransactionAction(tx, action, model, onNavigateBack) + } + ) + } } - } - is WalletDestination.TransactionWithdrawal -> { - (t as? TransactionWithdrawal)?.let { tx -> - val qrCode = remember(tx) { - (tx.withdrawalDetails as? WithdrawalDetails.ManualTransfer)?.let { details -> - if (details.exchangeCreditAccountDetails?.size == 1) { - val account0 = details.exchangeCreditAccountDetails[0] - val qrCodes = withdrawManager.getQrCodesForPayto(account0.paytoUri) - if (qrCodes.size == 1) qrCodes[0] - else null - } else null + + is WalletDestination.TransactionWithdrawal -> { + (t as? TransactionWithdrawal)?.let { tx -> + val qrCode = remember(tx) { + (tx.withdrawalDetails as? WithdrawalDetails.ManualTransfer)?.let { details -> + if (details.exchangeCreditAccountDetails?.size == 1) { + val account0 = details.exchangeCreditAccountDetails[0] + val qrCodes = withdrawManager.getQrCodesForPayto(account0.paytoUri) + if (qrCodes.size == 1) qrCodes[0] + else null + } else null + } } - } - TransactionWithdrawalComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - qrCode = qrCode, - onConfirmKyc = { url -> - launchInAppBrowser(context, url) - }, - onConfirmBank = { - if (tx.withdrawalDetails is WithdrawalDetails.TalerBankIntegrationApi) { - tx.withdrawalDetails.bankConfirmationUrl?.let { url -> - launchInAppBrowser(context, url) + TransactionWithdrawalComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), + qrCode = qrCode, + onConfirmKyc = { url -> + launchInAppBrowser(context, url) + }, + onConfirmBank = { + if (tx.withdrawalDetails is WithdrawalDetails.TalerBankIntegrationApi) { + tx.withdrawalDetails.bankConfirmationUrl?.let { url -> + launchInAppBrowser(context, url) + } } + }, + onConfirmManual = { + keepSelectedTx = true + onNavigate(WalletDestination.WireTransferDetails(false), false) + }, + onShowQrCodes = { + keepSelectedTx = true + onNavigate(WalletDestination.WireTransferDetails(true), false) + }, + onTransition = { action -> + handleTransactionAction(tx, action, model, onNavigateBack) } - }, - onConfirmManual = { - keepSelectedTx = true - onNavigate(WalletDestination.WireTransferDetails(false), false) - }, - onShowQrCodes = { - keepSelectedTx = true - onNavigate(WalletDestination.WireTransferDetails(true), false) - }, - onTransition = { action -> - handleTransactionAction(tx, action, model, onNavigateBack) - } - ) + ) + } } - } - is WalletDestination.TransactionDeposit -> { - (t as? TransactionDeposit)?.let { tx -> - TransactionDepositComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - onWireTransfer = { onNavigate(WalletDestination.WireTransferDetails(false), false) }, - onShowQrCodes = { onNavigate(WalletDestination.WireTransferDetails(true), false) }, - onTransition = { - handleTransactionAction(tx, it, model, onNavigateBack) - }, - ) + + is WalletDestination.TransactionDeposit -> { + (t as? TransactionDeposit)?.let { tx -> + TransactionDepositComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), + onWireTransfer = { + onNavigate( + WalletDestination.WireTransferDetails(false), + false + ) + }, + onShowQrCodes = { + onNavigate( + WalletDestination.WireTransferDetails(true), + false + ) + }, + onTransition = { + handleTransactionAction(tx, it, model, onNavigateBack) + }, + ) + } } - } - is WalletDestination.TransactionRefund -> { - (t as? TransactionRefund)?.let { tx -> - TransactionRefundComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - onTransition = { - handleTransactionAction(tx, it, model, onNavigateBack) - }, - ) + + is WalletDestination.TransactionRefund -> { + (t as? TransactionRefund)?.let { tx -> + TransactionRefundComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), + onTransition = { + handleTransactionAction(tx, it, model, onNavigateBack) + }, + ) + } } - } - is WalletDestination.TransactionRefresh -> { - (t as? TransactionRefresh)?.let { tx -> - TransactionRefreshComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - ) { - handleTransactionAction(tx, it, model, onNavigateBack) + + is WalletDestination.TransactionRefresh -> { + (t as? TransactionRefresh)?.let { tx -> + TransactionRefreshComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), + ) { + handleTransactionAction(tx, it, model, onNavigateBack) + } } } - } - is WalletDestination.TransactionPeer -> { - val tx = t - if (tx != null) { - TransactionPeerComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), - onConfirmKyc = { url -> launchInAppBrowser(context, url) } - ) { - handleTransactionAction(tx, it, model, onNavigateBack) + + is WalletDestination.TransactionPeer -> { + val tx = t + if (tx != null) { + TransactionPeerComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes), + onConfirmKyc = { url -> launchInAppBrowser(context, url) } + ) { + handleTransactionAction(tx, it, model, onNavigateBack) + } } } - } - is WalletDestination.TransactionLoss -> { - (t as? TransactionDenomLoss)?.let { tx -> - TransitionLossComposable( - modifier = modifier, - t = tx, - devMode = devMode, - spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes) - ) { - handleTransactionAction(tx, it, model, onNavigateBack) + + is WalletDestination.TransactionLoss -> { + (t as? TransactionDenomLoss)?.let { tx -> + TransitionLossComposable( + modifier = modifier, + t = tx, + devMode = devMode, + spec = exchangeManager.getSpecForCurrency(tx.amountRaw.currency, tx.scopes) + ) { + handleTransactionAction(tx, it, model, onNavigateBack) + } } } - } - is WalletDestination.TransactionDummy -> { - (t as? DummyTransaction)?.let { tx -> - TransactionDummyComposable( - modifier = modifier, - t = tx, - ) + + is WalletDestination.TransactionDummy -> { + (t as? DummyTransaction)?.let { tx -> + TransactionDummyComposable( + modifier = modifier, + t = tx, + ) + } } + + else -> {} } - else -> {} } } } diff --git a/wallet/src/main/java/net/taler/wallet/transfer/WireTransferDetailsScreen.kt b/wallet/src/main/java/net/taler/wallet/transfer/WireTransferDetailsScreen.kt @@ -16,6 +16,7 @@ package net.taler.wallet.transfer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -61,6 +62,7 @@ fun WireTransferDetailsScreen( GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text(stringResource(R.string.wire_transfer)) }, onNavigateBack = onNavigateBack, ) { paddingValues -> diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawScreen.kt b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawScreen.kt @@ -38,6 +38,7 @@ import net.taler.wallet.main.ViewMode import androidx.compose.material3.Text import androidx.compose.ui.res.stringResource import androidx.compose.ui.Modifier +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import net.taler.wallet.NavigateCallback @@ -124,6 +125,7 @@ fun PromptWithdrawScreen( GlobalScaffold( model = model, + modifier = Modifier.fillMaxSize(), title = { Text( status.selectedSpec?.symbol?.let { symbol ->