gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-android] 01/15: [wallet] DD51: initial rendering based on c


From: gnunet
Subject: [taler-taler-android] 01/15: [wallet] DD51: initial rendering based on currency spec
Date: Wed, 27 Mar 2024 18:27:04 +0100

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository taler-android.

commit 1e9ee99cb07c595132fa96935e3f2b7c88dd586a
Author: Iván Ávalos <avalos@disroot.org>
AuthorDate: Mon Feb 12 16:43:50 2024 -0600

    [wallet] DD51: initial rendering based on currency spec
    
    bug 0008329
    
    (cherry picked from commit 4789103406f44ba797c7bfee3112cc6aaa228683)
---
 .../src/main/java/net/taler/common/Amount.kt       | 46 +++++++++++++++++++++-
 .../net/taler/common}/CurrencySpecification.kt     | 11 ++++--
 .../net/taler/wallet/balances/BalanceAdapter.kt    |  7 +---
 .../net/taler/wallet/balances/BalanceManager.kt    | 38 +++++++++++++++++-
 .../java/net/taler/wallet/balances/Balances.kt     |  1 +
 .../java/net/taler/wallet/exchanges/Exchanges.kt   |  2 +
 .../wallet/transactions/TransactionAdapter.kt      |  2 +-
 .../wallet/transactions/TransactionPeerFragment.kt |  2 +-
 .../net/taler/wallet/transactions/Transactions.kt  |  2 +-
 .../wallet/transactions/TransactionsFragment.kt    |  6 +--
 .../withdraw/TransactionWithdrawalComposable.kt    |  4 +-
 .../net/taler/wallet/withdraw/WithdrawManager.kt   |  2 +
 .../taler/wallet/withdraw/manual/ScreenTransfer.kt |  2 +-
 wallet/src/main/res/layout/list_item_balance.xml   | 15 +------
 14 files changed, 105 insertions(+), 35 deletions(-)

diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt 
b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
index 5fb36fa..d6188cf 100644
--- a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
+++ b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
@@ -16,11 +16,14 @@
 
 package net.taler.common
 
+import android.os.Build
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.Serializer
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
+import java.text.DecimalFormat
+import java.text.NumberFormat
 import kotlin.math.floor
 import kotlin.math.pow
 import kotlin.math.roundToInt
@@ -54,6 +57,11 @@ public data class Amount(
      * of 50_000_000 would correspond to 50 cents.
      */
     val fraction: Int,
+
+    /**
+     * Currency specification for amount
+     */
+    val spec: CurrencySpecification? = null,
 ) : Comparable<Amount> {
 
     public companion object {
@@ -170,6 +178,8 @@ public data class Amount(
         return Amount(checkCurrency(currency), this.value, this.fraction)
     }
 
+    fun withSpec(spec: CurrencySpecification?) = copy(spec = spec)
+
     public operator fun minus(other: Amount): Amount {
         check(currency == other.currency) { "Can only subtract from same 
currency" }
         var resultValue = value
@@ -196,8 +206,40 @@ public data class Amount(
         return "$currency:$amountStr"
     }
 
-    override fun toString(): String {
-        return "$amountStr $currency"
+    override fun toString() = toString(
+        showSymbol = true,
+        negative = false,
+    )
+
+    fun toString(
+        showSymbol: Boolean = true,
+        negative: Boolean = false,
+    ): String {
+        val symbols = DecimalFormat().decimalFormatSymbols
+
+        val format = if (showSymbol) {
+            NumberFormat.getCurrencyInstance()
+        } else {
+            // Make sure monetary separators are the ones used!
+            symbols.decimalSeparator = symbols.monetaryDecimalSeparator
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 
{
+                symbols.groupingSeparator = symbols.monetaryGroupingSeparator
+            }
+
+            NumberFormat.getInstance()
+        }
+
+        if (spec != null) {
+            symbols.currencySymbol = spec.symbol(this)
+            format.maximumFractionDigits = spec.numFractionalNormalDigits
+            format.minimumFractionDigits = spec.numFractionalTrailingZeroDigits
+        } else {
+            symbols.currencySymbol = currency
+        }
+
+        (format as DecimalFormat).decimalFormatSymbols = symbols
+
+        return format.format((if (negative) "-$amountStr" else 
amountStr).toBigDecimal())
     }
 
     override fun compareTo(other: Amount): Int {
diff --git 
a/wallet/src/main/java/net/taler/wallet/balances/CurrencySpecification.kt 
b/taler-kotlin-android/src/main/java/net/taler/common/CurrencySpecification.kt
similarity index 84%
rename from 
wallet/src/main/java/net/taler/wallet/balances/CurrencySpecification.kt
rename to 
taler-kotlin-android/src/main/java/net/taler/common/CurrencySpecification.kt
index 5001db4..4aa8968 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/CurrencySpecification.kt
+++ 
b/taler-kotlin-android/src/main/java/net/taler/common/CurrencySpecification.kt
@@ -1,6 +1,6 @@
 /*
  * This file is part of GNU Taler
- * (C) 2023 Taler Systems S.A.
+ * (C) 2024 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
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet.balances
+package net.taler.common
 
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
@@ -29,5 +29,8 @@ data class CurrencySpecification(
     @SerialName("num_fractional_trailing_zero_digits")
     val numFractionalTrailingZeroDigits: Int,
     @SerialName("alt_unit_names")
-    val altUnitNames: Map<String, String>,
-)
\ No newline at end of file
+    val altUnitNames: Map<Int, String>,
+) {
+    // TODO: add support for alt units
+    fun symbol(amount: Amount): String = altUnitNames[0] ?: amount.currency
+}
\ No newline at end of file
diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
index efb3d48..0b87dee 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
@@ -58,7 +58,6 @@ class BalanceAdapter(private val listener: 
BalanceClickListener) : Adapter<Balan
     }
 
     inner class BalanceViewHolder(private val v: View) : 
RecyclerView.ViewHolder(v) {
-        private val currencyView: TextView = 
v.findViewById(R.id.balanceCurrencyView)
         private val amountView: TextView = 
v.findViewById(R.id.balanceAmountView)
         private val scopeView: TextView = v.findViewById(R.id.scopeView)
         private val balanceInboundAmount: TextView = 
v.findViewById(R.id.balanceInboundAmount)
@@ -67,8 +66,7 @@ class BalanceAdapter(private val listener: 
BalanceClickListener) : Adapter<Balan
 
         fun bind(item: BalanceItem) {
             v.setOnClickListener { 
listener.onBalanceClick(item.available.currency) }
-            currencyView.text = item.currency
-            amountView.text = item.available.amountStr
+            amountView.text = item.available.toString()
 
             val amountIncoming = item.pendingIncoming
             if (amountIncoming.isZero()) {
@@ -77,8 +75,7 @@ class BalanceAdapter(private val listener: 
BalanceClickListener) : Adapter<Balan
             } else {
                 balanceInboundAmount.visibility = VISIBLE
                 balanceInboundLabel.visibility = VISIBLE
-                balanceInboundAmount.text =
-                    v.context.getString(R.string.amount_positive, 
amountIncoming)
+                balanceInboundAmount.text = 
v.context.getString(R.string.amount_positive, amountIncoming)
             }
 
             val scopeInfo = item.scopeInfo
diff --git a/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt
index 2930c77..9b5beaf 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalanceManager.kt
@@ -24,15 +24,24 @@ import androidx.lifecycle.distinctUntilChanged
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import kotlinx.serialization.Serializable
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.backend.WalletBackendApi
+import org.json.JSONObject
 
 @Serializable
 data class BalanceResponse(
     val balances: List<BalanceItem>
 )
 
+@Serializable
+data class GetCurrencySpecificationResponse(
+    val currencySpecification: CurrencySpecification,
+)
+
 sealed class BalanceState {
     data object None: BalanceState()
     data object Loading: BalanceState()
@@ -67,11 +76,38 @@ class BalanceManager(
             }
             response.onSuccess {
                 mState.postValue(BalanceState.Success(it.balances))
-                mBalances.postValue(it.balances)
+                scope.launch {
+                    // Get currency spec for all balances)
+                    mState.postValue(
+                        BalanceState.Success(it.balances.map { balance ->
+                            val spec = 
getCurrencySpecification(balance.scopeInfo)
+                            balance.copy(
+                                available = balance.available.withSpec(spec),
+                                pendingIncoming = 
balance.pendingIncoming.withSpec(spec),
+                                pendingOutgoing = 
balance.pendingOutgoing.withSpec(spec),
+                            )
+                        }),
+                    )
+                }
             }
         }
     }
 
+    private suspend fun getCurrencySpecification(scopeInfo: ScopeInfo): 
CurrencySpecification? {
+        var spec: CurrencySpecification? = null
+        api.request("getCurrencySpecification", 
GetCurrencySpecificationResponse.serializer()) {
+            val json = Json.encodeToString(scopeInfo)
+            Log.d(TAG, "BalanceManager: $json")
+            put("scope", JSONObject(json))
+        }.onSuccess {
+            spec = it.currencySpecification
+        }.onError {
+            Log.e(TAG, "Error getting currency spec for scope $scopeInfo: $it")
+        }
+
+        return spec
+    }
+
     fun resetBalances() {
         mState.value = BalanceState.None
     }
diff --git a/wallet/src/main/java/net/taler/wallet/balances/Balances.kt 
b/wallet/src/main/java/net/taler/wallet/balances/Balances.kt
index dff2ffb..3e0acc9 100644
--- a/wallet/src/main/java/net/taler/wallet/balances/Balances.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/Balances.kt
@@ -19,6 +19,7 @@ package net.taler.wallet.balances
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
 import net.taler.common.Amount
+import net.taler.common.CurrencySpecification
 
 @Serializable
 data class BalanceItem(
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt
index af373c2..ce0bd82 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt
@@ -17,6 +17,7 @@
 package net.taler.wallet.exchanges
 
 import kotlinx.serialization.Serializable
+import net.taler.wallet.balances.ScopeInfo
 import net.taler.wallet.cleanExchange
 
 @Serializable
@@ -25,6 +26,7 @@ data class ExchangeItem(
     // can be null before exchange info in wallet-core was fully loaded
     val currency: String? = null,
     val paytoUris: List<String>,
+    val scopeInfo: ScopeInfo? = null,
 ) {
     val name: String get() = cleanExchange(exchangeBaseUrl)
 }
\ No newline at end of file
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
index c9ae889..6fade86 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -183,7 +183,7 @@ internal class TransactionAdapter(
         }
 
         private fun bindAmount(transaction: Transaction) {
-            val amountStr = transaction.amountEffective.amountStr
+            val amountStr = transaction.amountEffective.toString(showSymbol = 
false)
             when (transaction.amountType) {
                 AmountType.Positive -> {
                     amount.text = context.getString(R.string.amount_positive, 
amountStr)
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
index c934d89..7feedd1 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionPeerFragment.kt
@@ -106,7 +106,7 @@ fun TransactionAmountComposable(label: String, amount: 
Amount, amountType: Amoun
     )
     Text(
         modifier = Modifier.padding(top = 8.dp, start = 16.dp, end = 16.dp, 
bottom = 16.dp),
-        text = if (amountType == AmountType.Negative) "-$amount" else 
amount.toString(),
+        text = amount.toString(negative = amountType == AmountType.Negative),
         fontSize = 24.sp,
         color = when (amountType) {
             AmountType.Positive -> colorResource(R.color.green)
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
index 9017854..be36a13 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
@@ -41,7 +41,7 @@ import net.taler.wallet.R
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorCode
 import net.taler.wallet.backend.TalerErrorInfo
-import net.taler.wallet.balances.CurrencySpecification
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.cleanExchange
 import net.taler.wallet.refund.RefundPaymentInfo
 import net.taler.wallet.transactions.TransactionMajorState.None
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
index 3f610d3..d89fbb5 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
@@ -37,7 +37,6 @@ import androidx.recyclerview.selection.StorageStrategy
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import net.taler.common.Amount
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.common.showError
@@ -113,8 +112,9 @@ class TransactionsFragment : Fragment(), 
OnTransactionClickListener, ActionMode.
             val balances = state.balances
             // hide extra fab when in single currency mode (uses 
MainFragment's FAB)
             if (balances.size == 1) ui.mainFab.visibility = INVISIBLE
-            balances.find { it.currency == currency }?.available?.let { 
amount: Amount ->
-                ui.amount.text = amount.amountStr
+            // TODO: find via scopeInfo instead of currency
+            balances.find { it.currency == currency }?.let { balance ->
+                ui.amount.text = balance.available.toString(showSymbol = false)
             }
         }
         transactionManager.progress.observe(viewLifecycleOwner) { show ->
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
 
b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
index fda1815..7e8f94f 100644
--- 
a/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/withdraw/TransactionWithdrawalComposable.kt
@@ -38,7 +38,7 @@ import net.taler.wallet.R
 import net.taler.wallet.backend.TalerErrorCode
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.cleanExchange
-import net.taler.wallet.balances.CurrencySpecification
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.transactions.ActionButton
 import net.taler.wallet.transactions.ActionListener
 import net.taler.wallet.transactions.AmountType
@@ -133,7 +133,7 @@ fun TransactionWithdrawalComposablePreview() {
                         numFractionalInputDigits = 2,
                         numFractionalNormalDigits = 2,
                         numFractionalTrailingZeroDigits = 2,
-                        altUnitNames = mapOf("0" to "NETZBON"),
+                        altUnitNames = mapOf(0 to "NETZBON"),
                     ),
                 ),
             ),
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
index 4c9479b..e308b2a 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
@@ -31,6 +31,7 @@ import net.taler.common.toEvent
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorInfo
 import net.taler.wallet.backend.WalletBackendApi
+import net.taler.wallet.balances.ScopeInfo
 import net.taler.wallet.exchanges.ExchangeFees
 import net.taler.wallet.exchanges.ExchangeItem
 import net.taler.wallet.transactions.WithdrawalExchangeAccountDetails
@@ -145,6 +146,7 @@ data class ManualWithdrawalDetails(
     val amountEffective: Amount,
     val withdrawalAccountsList: List<WithdrawalExchangeAccountDetails>,
     val ageRestrictionOptions: List<Int>? = null,
+    val scopeInfo: ScopeInfo,
 )
 
 @Serializable
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt
index d75c685..86972cf 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/manual/ScreenTransfer.kt
@@ -47,8 +47,8 @@ import androidx.compose.ui.unit.dp
 import net.taler.common.Amount
 import net.taler.wallet.CURRENCY_BTC
 import net.taler.wallet.R
+import net.taler.common.CurrencySpecification
 import net.taler.wallet.compose.ShareButton
-import net.taler.wallet.balances.CurrencySpecification
 import net.taler.wallet.compose.copyToClipBoard
 import net.taler.wallet.transactions.AmountType
 import net.taler.wallet.transactions.TransactionAmountComposable
diff --git a/wallet/src/main/res/layout/list_item_balance.xml 
b/wallet/src/main/res/layout/list_item_balance.xml
index 82e663f..483b1ce 100644
--- a/wallet/src/main/res/layout/list_item_balance.xml
+++ b/wallet/src/main/res/layout/list_item_balance.xml
@@ -28,26 +28,13 @@
         android:layout_height="wrap_content"
         android:layout_marginEnd="8dp"
         android:textSize="40sp"
-        app:layout_constraintEnd_toStartOf="@+id/balanceCurrencyView"
+        app:layout_constraintEnd_toStartOf="@+id/pendingView"
         app:layout_constraintHorizontal_bias="0.0"
         app:layout_constraintHorizontal_chainStyle="packed"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         tools:text="100.50" />
 
-    <TextView
-        android:id="@+id/balanceCurrencyView"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="8dp"
-        android:textSize="20sp"
-        app:layout_constrainedWidth="true"
-        app:layout_constraintBottom_toBottomOf="@+id/balanceAmountView"
-        app:layout_constraintEnd_toStartOf="@+id/pendingView"
-        app:layout_constraintStart_toEndOf="@+id/balanceAmountView"
-        app:layout_constraintTop_toTopOf="@+id/balanceAmountView"
-        tools:text="TESTKUDOS" />
-
     <TextView
         android:id="@+id/scopeView"
         android:layout_width="0dp"

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]