taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

DonauComposables.kt (6200B)


      1 /*
      2  * This file is part of GNU Taler
      3  * (C) 2025 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.donau
     18 
     19 import androidx.compose.foundation.clickable
     20 import androidx.compose.foundation.layout.Column
     21 import androidx.compose.foundation.layout.Row
     22 import androidx.compose.foundation.layout.fillMaxSize
     23 import androidx.compose.foundation.layout.fillMaxWidth
     24 import androidx.compose.foundation.layout.padding
     25 import androidx.compose.foundation.lazy.LazyColumn
     26 import androidx.compose.foundation.lazy.itemsIndexed
     27 import androidx.compose.material3.AlertDialog
     28 import androidx.compose.material3.Button
     29 import androidx.compose.material3.RadioButton
     30 import androidx.compose.material3.Switch
     31 import androidx.compose.material3.Text
     32 import androidx.compose.material3.TextButton
     33 import androidx.compose.runtime.Composable
     34 import androidx.compose.runtime.getValue
     35 import androidx.compose.runtime.mutableIntStateOf
     36 import androidx.compose.runtime.mutableStateOf
     37 import androidx.compose.runtime.remember
     38 import androidx.compose.runtime.setValue
     39 import androidx.compose.ui.Alignment
     40 import androidx.compose.ui.Modifier
     41 import androidx.compose.ui.res.stringResource
     42 import androidx.compose.ui.tooling.preview.Preview
     43 import androidx.compose.ui.unit.dp
     44 import net.taler.wallet.R
     45 import net.taler.wallet.cleanExchange
     46 import net.taler.wallet.compose.TalerSurface
     47 import net.taler.wallet.compose.WarningLabel
     48 import net.taler.wallet.payment.DonauStatus
     49 
     50 @Composable
     51 fun DonauToggle(
     52     donauStatus: DonauStatus,
     53     useDonau: Boolean = false,
     54     onToggleDonau: (Boolean) -> Unit,
     55 ) {
     56     if (donauStatus !is DonauStatus.Unavailable) {
     57         Column {
     58             Row(
     59                 Modifier
     60                     .fillMaxWidth()
     61                     .padding(9.dp),
     62             ) {
     63                 Text(
     64                     modifier = Modifier.weight(1f),
     65                     text = stringResource(R.string.donau_toggle_label),
     66                 )
     67 
     68                 Switch(
     69                     checked = useDonau,
     70                     onCheckedChange = onToggleDonau,
     71                 )
     72             }
     73 
     74             if (useDonau) when (donauStatus) {
     75                 is DonauStatus.Mismatch -> {
     76                     WarningLabel(stringResource(
     77                         R.string.donau_warning_mismatch,
     78                         cleanExchange(donauStatus.donauInfo.donauBaseUrl)))
     79                 }
     80 
     81                 is DonauStatus.Unset -> {
     82                     WarningLabel(stringResource(R.string.donau_warning_unset))
     83                 }
     84 
     85                 // no need to show anything
     86                 else -> {}
     87             }
     88         }
     89     }
     90 }
     91 
     92 @Composable
     93 fun DonauSelector(
     94     donauStatus: DonauStatus,
     95     showDialog: Boolean,
     96     onDismiss: () -> Unit,
     97     onSetup: (donauBaseUrl: String) -> Unit,
     98 ) {
     99     var selectedDonauIndex by remember { mutableIntStateOf(0) }
    100 
    101     val donauUrls = when(donauStatus) {
    102         is DonauStatus.Mismatch -> donauStatus.donauUrls
    103         is DonauStatus.Unset -> donauStatus.donauUrls
    104         else -> return
    105     }
    106 
    107     if (showDialog) AlertDialog(
    108         title = { Text(stringResource(R.string.donau_selector_title)) },
    109         text = {
    110             LazyColumn(modifier = Modifier.fillMaxWidth()) {
    111                 itemsIndexed(donauUrls) { i, url ->
    112                     DonauSelectorItem(
    113                         donauBaseUrl = url,
    114                         selected = i == selectedDonauIndex,
    115                         onSelected = { selectedDonauIndex = i },
    116                     )
    117                 }
    118             }
    119         },
    120         confirmButton = {
    121             Button(onClick = {
    122                 onSetup(donauUrls[selectedDonauIndex])
    123                 onDismiss()
    124             }) {
    125                 Text(stringResource(R.string.donau_selector_confirm))
    126             }
    127         },
    128         dismissButton = {
    129             TextButton (onClick = { onDismiss() }) {
    130                 Text(stringResource(R.string.cancel))
    131             }
    132         },
    133         onDismissRequest = {
    134             onDismiss()
    135         },
    136     )
    137 }
    138 
    139 @Composable
    140 fun DonauSelectorItem(
    141     donauBaseUrl: String,
    142     selected: Boolean,
    143     onSelected: () -> Unit,
    144 ) {
    145     Row(Modifier
    146         .padding(bottom = 5.dp)
    147         .fillMaxWidth()
    148         .clickable { onSelected() },
    149         verticalAlignment = Alignment.CenterVertically) {
    150         RadioButton(
    151             selected = selected,
    152             onClick = onSelected,
    153         )
    154 
    155         Text(
    156             modifier = Modifier.weight(1f),
    157             text = cleanExchange(donauBaseUrl)
    158         )
    159     }
    160 }
    161 
    162 @Preview
    163 @Composable
    164 fun DonauSelectorPreview() {
    165     TalerSurface {
    166         val donauInfo = DonauInfo(donauBaseUrl = "https://donau.test.taler.net/", taxPayerId = "1234")
    167         val donauUrls = listOf(
    168             "https://donau.head.taler.net/",
    169             "https://donau.test.taler.net/",
    170             "https://donau.demo.taler.net/",
    171         )
    172 
    173         var donauStatus: DonauStatus by remember { mutableStateOf(DonauStatus.Unset(donauUrls)) }
    174 
    175         Column(Modifier.fillMaxSize()) {
    176             Button(onClick = { donauStatus = DonauStatus.Unset(donauUrls) }) {
    177                 Text("DonauStatus.Unset")
    178             }
    179 
    180             Button(onClick = { donauStatus = DonauStatus.Mismatch(donauInfo, donauUrls) }) {
    181                 Text("DonauStatus.Mismatch")
    182             }
    183         }
    184 
    185         DonauSelector(donauStatus,
    186             showDialog = donauStatus !is DonauStatus.Unavailable,
    187             onDismiss = { donauStatus = DonauStatus.Unavailable },
    188             onSetup = { donauStatus = DonauStatus.Unavailable }
    189         )
    190     }
    191 }