From 6876951cb30f057a852937a533d5d51d26645680 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 7 Sep 2022 15:48:00 -0300 Subject: [wallet] implement prototype for handling incoming pay-push URI --- .../taler/wallet/peer/PeerPullPaymentComposable.kt | 223 +++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 wallet/src/main/java/net/taler/wallet/peer/PeerPullPaymentComposable.kt (limited to 'wallet/src/main/java/net/taler/wallet/peer/PeerPullPaymentComposable.kt') diff --git a/wallet/src/main/java/net/taler/wallet/peer/PeerPullPaymentComposable.kt b/wallet/src/main/java/net/taler/wallet/peer/PeerPullPaymentComposable.kt new file mode 100644 index 0000000..fff74ea --- /dev/null +++ b/wallet/src/main/java/net/taler/wallet/peer/PeerPullPaymentComposable.kt @@ -0,0 +1,223 @@ +/* + * This file is part of GNU Taler + * (C) 2022 Taler Systems S.A. + * + * GNU Taler is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3, or (at your option) any later version. + * + * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * GNU Taler; see the file COPYING. If not, see + */ + +package net.taler.wallet.peer + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +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.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Card +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.Alignment.Companion.CenterHorizontally +import androidx.compose.ui.Alignment.Companion.End +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import net.taler.common.Amount +import net.taler.wallet.R +import net.taler.wallet.backend.TalerErrorInfo + +@Composable +fun PeerPullPaymentComposable( + state: State, + onAccept: (PeerIncomingTerms) -> Unit, +) { + val scrollState = rememberScrollState() + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState), + ) { + Text( + modifier = Modifier + .padding(16.dp) + .align(CenterHorizontally), + text = stringResource(id = R.string.pay_peer_intro)) + when (val s = state.value) { + PeerIncomingChecking -> PeerPullCheckingComposable() + is PeerIncomingTerms -> PeerPullTermsComposable(s, onAccept) + is PeerIncomingAccepting -> PeerPullTermsComposable(s, onAccept) + PeerIncomingAccepted -> { + // we navigate away, don't show anything + } + is PeerIncomingError -> PeerPullErrorComposable(s) + } + } +} + +@Composable +fun ColumnScope.PeerPullCheckingComposable() { + CircularProgressIndicator( + modifier = Modifier + .align(CenterHorizontally) + .fillMaxSize(0.75f), + ) +} + +@Composable +fun ColumnScope.PeerPullTermsComposable( + terms: PeerIncomingTerms, + onAccept: (PeerIncomingTerms) -> Unit, +) { + Text( + modifier = Modifier + .padding(16.dp) + .align(CenterHorizontally), + text = terms.contractTerms.summary, + style = MaterialTheme.typography.h5, + ) + Spacer(modifier = Modifier.weight(1f)) + Card(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier.padding(8.dp) + ) { + Row( + modifier = Modifier.align(End), + ) { + Text( + text = stringResource(id = R.string.payment_label_amount_total), + style = MaterialTheme.typography.body1, + ) + Text( + modifier = Modifier.padding(start = 8.dp), + text = terms.contractTerms.amount.toString(), + style = MaterialTheme.typography.body1, + fontWeight = FontWeight.Bold, + ) + } + val fee = + Amount.zero(terms.amount.currency) // terms.amount - terms.contractTerms.amount + if (!fee.isZero()) { + Text( + modifier = Modifier.align(End), + text = stringResource(id = R.string.payment_fee, fee), + style = MaterialTheme.typography.body1, + ) + } + if (terms is PeerIncomingAccepting) { + CircularProgressIndicator( + modifier = Modifier + .padding(end = 64.dp) + .align(End), + ) + } else { + Button( + modifier = Modifier + .align(End) + .padding(top = 8.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = colorResource(R.color.green), + contentColor = Color.White, + ), + onClick = { onAccept(terms) }, + ) { + Text( + text = stringResource(id = R.string.payment_button_confirm), + ) + } + } + } + } +} + +@Composable +fun ColumnScope.PeerPullErrorComposable(s: PeerIncomingError) { + Text( + modifier = Modifier + .align(CenterHorizontally) + .padding(horizontal = 32.dp), + text = s.info.userFacingMsg, + style = MaterialTheme.typography.h5, + color = colorResource(id = R.color.red), + ) +} + +@Preview +@Composable +fun PeerPullCheckingPreview() { + Surface { + @SuppressLint("UnrememberedMutableState") + val s = mutableStateOf(PeerIncomingChecking) + PeerPullPaymentComposable(s) {} + } +} + +@Preview +@Composable +fun PeerPullTermsPreview() { + Surface { + val terms = PeerIncomingTerms( + amount = Amount.fromDouble("TESTKUDOS", 42.23), + contractTerms = PeerContractTerms( + summary = "This is a long test summary that can be more than one line long for sure", + amount = Amount.fromDouble("TESTKUDOS", 23.42), + ), + id = "ID123", + ) + + @SuppressLint("UnrememberedMutableState") + val s = mutableStateOf(terms) + PeerPullPaymentComposable(s) {} + } +} + +@Preview +@Composable +fun PeerPullAcceptingPreview() { + Surface { + val terms = PeerIncomingTerms( + amount = Amount.fromDouble("TESTKUDOS", 42.23), + contractTerms = PeerContractTerms( + summary = "This is a long test summary that can be more than one line long for sure", + amount = Amount.fromDouble("TESTKUDOS", 23.42), + ), + id = "ID123", + ) + + @SuppressLint("UnrememberedMutableState") + val s = mutableStateOf(PeerIncomingAccepting(terms)) + PeerPullPaymentComposable(s) {} + } +} + +@Preview +@Composable +fun PeerPullPayErrorPreview() { + Surface { + @SuppressLint("UnrememberedMutableState") + val s = mutableStateOf(PeerIncomingError(TalerErrorInfo(42, "hint", "msg"))) + PeerPullPaymentComposable(s) {} + } +} -- cgit v1.2.3