TransactionPeerPushDebit.kt (6731B)
1 /* 2 * This file is part of GNU Taler 3 * (C) 2022 Taler Systems S.A. 4 * 5 * GNU Taler is free software; you can redistribute it and/or modify it under the 6 * terms of the GNU General Public License as published by the Free Software 7 * Foundation; either version 3, or (at your option) any later version. 8 * 9 * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY 10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 17 package net.taler.wallet.peer 18 19 import androidx.compose.foundation.layout.ColumnScope 20 import androidx.compose.foundation.layout.Spacer 21 import androidx.compose.foundation.layout.aspectRatio 22 import androidx.compose.foundation.layout.fillMaxWidth 23 import androidx.compose.foundation.layout.height 24 import androidx.compose.foundation.layout.padding 25 import androidx.compose.material3.CircularProgressIndicator 26 import androidx.compose.material3.MaterialTheme 27 import androidx.compose.material3.Text 28 import androidx.compose.runtime.Composable 29 import androidx.compose.ui.Alignment.Companion.CenterHorizontally 30 import androidx.compose.ui.Modifier 31 import androidx.compose.ui.res.stringResource 32 import androidx.compose.ui.text.style.TextAlign 33 import androidx.compose.ui.tooling.preview.Preview 34 import androidx.compose.ui.unit.dp 35 import net.taler.common.Amount 36 import net.taler.common.CurrencySpecification 37 import net.taler.common.Timestamp 38 import net.taler.wallet.R 39 import net.taler.wallet.balances.ScopeInfo 40 import net.taler.wallet.compose.QrCodeParams 41 import net.taler.wallet.compose.QrCodeUriComposable 42 import net.taler.wallet.compose.TalerSurface 43 import net.taler.wallet.transactions.AmountType 44 import net.taler.wallet.transactions.PeerInfoShort 45 import net.taler.wallet.transactions.TransactionAction.Abort 46 import net.taler.wallet.transactions.TransactionAction.Retry 47 import net.taler.wallet.transactions.TransactionAction.Suspend 48 import net.taler.wallet.transactions.TransactionAmountComposable 49 import net.taler.wallet.transactions.TransactionInfoComposable 50 import net.taler.wallet.transactions.TransactionMajorState.Done 51 import net.taler.wallet.transactions.TransactionMajorState.Pending 52 import net.taler.wallet.transactions.TransactionMinorState.CreatePurse 53 import net.taler.wallet.transactions.TransactionMinorState.KycRequired 54 import net.taler.wallet.transactions.TransactionMinorState.Ready 55 import net.taler.wallet.transactions.TransactionPeerComposable 56 import net.taler.wallet.transactions.TransactionPeerPushDebit 57 import net.taler.wallet.transactions.TransactionState 58 59 @Composable 60 fun ColumnScope.TransactionPeerPushDebitComposable(t: TransactionPeerPushDebit, spec: CurrencySpecification?) { 61 if (t.error == null) PeerQrCode( 62 state = t.txState, 63 amount = t.amountRaw.withSpec(spec), 64 talerUri = t.talerUri, 65 instructionResId = R.string.send_peer_payment_instruction, 66 ) 67 68 TransactionAmountComposable( 69 label = stringResource(id = R.string.transaction_order_total), 70 amount = t.amountRaw.withSpec(spec), 71 amountType = AmountType.Neutral, 72 ) 73 74 if (t.amountEffective > t.amountRaw) { 75 val fee = t.amountEffective - t.amountRaw 76 TransactionAmountComposable( 77 label = stringResource(id = R.string.amount_fee), 78 amount = fee.withSpec(spec), 79 amountType = AmountType.Negative, 80 ) 81 } 82 83 TransactionAmountComposable( 84 label = if (t.txState.major == Done) { 85 stringResource(id = R.string.amount_sent) 86 } else { 87 stringResource(R.string.amount_send) 88 }, 89 amount = t.amountEffective.withSpec(spec), 90 amountType = AmountType.Negative, 91 ) 92 93 TransactionInfoComposable( 94 label = stringResource(id = R.string.send_peer_purpose), 95 info = t.info.summary ?: "", 96 ) 97 } 98 99 @Composable 100 fun ColumnScope.PeerQrCode( 101 state: TransactionState, 102 amount: Amount, 103 talerUri: String?, 104 instructionResId: Int, 105 ) { 106 if (state == TransactionState(Pending) && state.minor != KycRequired) { 107 Text( 108 modifier = Modifier.padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 8.dp), 109 style = MaterialTheme.typography.bodyLarge, 110 text = stringResource(id = instructionResId, amount.toString()), 111 textAlign = TextAlign.Center, 112 ) 113 114 if (state.minor == Ready && talerUri != null) { 115 Spacer(Modifier.height(8.dp)) 116 QrCodeUriComposable( 117 modifier = Modifier.padding(horizontal = 16.dp), 118 qrData = talerUri, 119 clipboardLabel = "Push payment", 120 params = QrCodeParams.Taler, 121 buttonText = stringResource(id = R.string.copy), 122 ) { 123 Text( 124 modifier = Modifier 125 .padding(top = 12.dp) 126 .padding(horizontal = 16.dp), 127 style = MaterialTheme.typography.bodyLarge, 128 text = stringResource(id = R.string.receive_peer_invoice_uri), 129 ) 130 } 131 } else CircularProgressIndicator( 132 modifier = Modifier 133 .padding(45.dp) 134 .fillMaxWidth() 135 .aspectRatio(1f) 136 .align(CenterHorizontally), 137 ) 138 } 139 } 140 141 @Preview 142 @Composable 143 fun TransactionPeerPushDebitPreview(loading: Boolean = false) { 144 val t = TransactionPeerPushDebit( 145 transactionId = "transactionId", 146 timestamp = Timestamp.fromMillis(System.currentTimeMillis() - 360 * 60 * 1000), 147 txState = TransactionState(Pending, if (loading) CreatePurse else Ready), 148 txActions = listOf(Retry, Suspend, Abort), 149 exchangeBaseUrl = "https://exchange.example.org/", 150 amountRaw = Amount.fromString("TESTKUDOS", "42.1337"), 151 amountEffective = Amount.fromString("TESTKUDOS", "42.23"), 152 info = PeerInfoShort( 153 expiration = Timestamp.fromMillis(System.currentTimeMillis() + 60 * 60 * 1000), 154 summary = "test invoice", 155 ), 156 talerUri = "https://exchange.example.org/peer/pull/credit", 157 scopes = listOf(ScopeInfo.Exchange( 158 currency = "TESTKUDOS", 159 url = "exchange.test.taler.net", 160 )) 161 ) 162 163 TalerSurface { 164 TransactionPeerComposable(t, true, null, Modifier, {}) {} 165 } 166 } 167 168 @Preview 169 @Composable 170 fun TransactionPeerPushDebitLoadingPreview() { 171 TransactionPeerPushDebitPreview(loading = true) 172 }