gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] branch master updated (841d87d -> 44496bc)


From: gnunet
Subject: [taler-taler-android] branch master updated (841d87d -> 44496bc)
Date: Mon, 28 Sep 2020 19:46:57 +0200

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

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

    from 841d87d  [cashier] Add about screen with version and license info
     new 0936fc8  [wallet] implement exchange selection for withdrawals
     new 44496bc  [wallet] Enable manual withdrawal (without payto:// 
parsing/display)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .idea/codeStyles/Project.xml                       |   1 +
 build.gradle                                       |   2 +-
 .../src/main/java/net/taler/common/Event.kt        |   4 +
 wallet/build.gradle                                |   2 +-
 .../net/taler/wallet/exchanges/ExchangeAdapter.kt  |  17 ++-
 ...ExchangeFragment.kt => ExchangeFeesFragment.kt} |  11 +-
 .../taler/wallet/exchanges/ExchangeListFragment.kt |  20 +--
 .../wallet/exchanges/SelectExchangeFragment.kt     | 135 +++------------------
 .../wallet/withdraw/ManualWithdrawFragment.kt      |   8 +-
 .../wallet/withdraw/PromptWithdrawFragment.kt      |  88 +++++++++-----
 .../net/taler/wallet/withdraw/WithdrawManager.kt   |  52 +++++---
 ...ect_exchange.xml => fragment_exchange_fees.xml} |   0
 .../main/res/layout/fragment_prompt_withdraw.xml   |   2 +-
 wallet/src/main/res/navigation/nav_graph.xml       |  10 +-
 wallet/src/main/res/values/strings.xml             |   1 +
 15 files changed, 167 insertions(+), 186 deletions(-)
 copy 
wallet/src/main/java/net/taler/wallet/exchanges/{SelectExchangeFragment.kt => 
ExchangeFeesFragment.kt} (95%)
 rename wallet/src/main/res/layout/{fragment_select_exchange.xml => 
fragment_exchange_fees.xml} (100%)

diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index b23c749..587f132 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -17,6 +17,7 @@
       </option>
       <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
       <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" 
value="2147483647" />
+      <option name="ALLOW_TRAILING_COMMA" value="true" />
       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
     </JetCodeStyleSettings>
     <codeStyleSettings language="XML">
diff --git a/build.gradle b/build.gradle
index 8973530..7f12ed4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
 buildscript {
-    ext.kotlin_version = '1.4.0'
+    ext.kotlin_version = '1.4.10'
     ext.ktor_version = "1.4.0"
     ext.nav_version = "2.3.0"
     ext.material_version = "1.2.1"
diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Event.kt 
b/taler-kotlin-android/src/main/java/net/taler/common/Event.kt
index 779247f..752e20e 100644
--- a/taler-kotlin-android/src/main/java/net/taler/common/Event.kt
+++ b/taler-kotlin-android/src/main/java/net/taler/common/Event.kt
@@ -34,6 +34,10 @@ open class Event<out T>(private val content: T) {
         return if (isConsumed.compareAndSet(false, true)) content else null
     }
 
+    fun getEvenIfConsumedAlready(): T {
+        return content
+    }
+
 }
 
 fun <T> T.toEvent() = Event(this)
diff --git a/wallet/build.gradle b/wallet/build.gradle
index 02123ee..48e1749 100644
--- a/wallet/build.gradle
+++ b/wallet/build.gradle
@@ -139,7 +139,7 @@ dependencies {
     implementation 'me.zhanghai.android.materialprogressbar:library:1.6.1'
 
     // Markdown rendering
-    final def markwon_version = '4.5.1'
+    final def markwon_version = '4.6.0'
     implementation "io.noties.markwon:core:$markwon_version"
     implementation "io.noties.markwon:ext-tables:$markwon_version"
     implementation "io.noties.markwon:recycler:$markwon_version"
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeAdapter.kt
index 17ac50f..e315632 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeAdapter.kt
@@ -18,6 +18,8 @@ package net.taler.wallet.exchanges
 
 import android.view.LayoutInflater
 import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
 import android.view.ViewGroup
 import android.widget.ImageButton
 import android.widget.TextView
@@ -39,11 +41,14 @@ data class ExchangeItem(
 }
 
 interface ExchangeClickListener {
+    fun onExchangeSelected(item: ExchangeItem)
     fun onManualWithdraw(item: ExchangeItem)
 }
 
-internal class ExchangeAdapter(private val listener: ExchangeClickListener) :
-    Adapter<ExchangeItemViewHolder>() {
+internal class ExchangeAdapter(
+    private val selectOnly: Boolean,
+    private val listener: ExchangeClickListener,
+) : Adapter<ExchangeItemViewHolder>() {
 
     private val items = ArrayList<ExchangeItem>()
 
@@ -74,6 +79,14 @@ internal class ExchangeAdapter(private val listener: 
ExchangeClickListener) :
         fun bind(item: ExchangeItem) {
             urlView.text = item.name
             currencyView.text = 
context.getString(R.string.exchange_list_currency, item.currency)
+            if (selectOnly) {
+                itemView.setOnClickListener { 
listener.onExchangeSelected(item) }
+                overflowIcon.visibility = GONE
+            } else {
+                itemView.setOnClickListener(null)
+                itemView.isClickable = false
+                overflowIcon.visibility = VISIBLE
+            }
             overflowIcon.setOnClickListener { openMenu(overflowIcon, item) }
         }
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt
similarity index 95%
copy from 
wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
copy to wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt
index a95a51c..c59fffe 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt
@@ -32,22 +32,23 @@ import net.taler.common.toShortDate
 import net.taler.lib.common.Amount
 import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
-import net.taler.wallet.databinding.FragmentSelectExchangeBinding
+import net.taler.wallet.databinding.FragmentExchangeFeesBinding
 import net.taler.wallet.exchanges.CoinFeeAdapter.CoinFeeViewHolder
 import net.taler.wallet.exchanges.WireFeeAdapter.WireFeeViewHolder
 
-class SelectExchangeFragment : Fragment() {
+class ExchangeFeesFragment : Fragment() {
 
     private val model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
-    private lateinit var ui: FragmentSelectExchangeBinding
+    private lateinit var ui: FragmentExchangeFeesBinding
 
     override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
+        inflater: LayoutInflater,
+        container: ViewGroup?,
         savedInstanceState: Bundle?
     ): View? {
-        ui = FragmentSelectExchangeBinding.inflate(inflater, container, false)
+        ui = FragmentExchangeFeesBinding.inflate(inflater, container, false)
         return ui.root
     }
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt
index 86b2519..9a96b59 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt
@@ -34,17 +34,19 @@ import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
 import net.taler.wallet.databinding.FragmentExchangeListBinding
 
-class ExchangeListFragment : Fragment(), ExchangeClickListener {
+open class ExchangeListFragment : Fragment(), ExchangeClickListener {
 
-    private val model: MainViewModel by activityViewModels()
+    protected val model: MainViewModel by activityViewModels()
     private val exchangeManager by lazy { model.exchangeManager }
 
-    private lateinit var ui: FragmentExchangeListBinding
-    private val exchangeAdapter by lazy { ExchangeAdapter(this) }
+    protected lateinit var ui: FragmentExchangeListBinding
+    protected open val isSelectOnly = false
+    private val exchangeAdapter by lazy { ExchangeAdapter(isSelectOnly, this) }
 
     override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?,
     ): View? {
         ui = FragmentExchangeListBinding.inflate(inflater, container, false)
         return ui.root
@@ -70,7 +72,7 @@ class ExchangeListFragment : Fragment(), 
ExchangeClickListener {
         })
     }
 
-    private fun onExchangeUpdate(exchanges: List<ExchangeItem>) {
+    protected open fun onExchangeUpdate(exchanges: List<ExchangeItem>) {
         exchangeAdapter.update(exchanges)
         if (exchanges.isEmpty()) {
             ui.emptyState.fadeIn()
@@ -85,6 +87,10 @@ class ExchangeListFragment : Fragment(), 
ExchangeClickListener {
         Toast.makeText(requireContext(), R.string.exchange_add_error, 
LENGTH_LONG).show()
     }
 
+    override fun onExchangeSelected(item: ExchangeItem) {
+        throw AssertionError("must not get triggered here")
+    }
+
     override fun onManualWithdraw(item: ExchangeItem) {
         exchangeManager.withdrawalExchange = item
         
findNavController().navigate(R.id.action_nav_settings_exchanges_to_nav_exchange_manual_withdrawal)
diff --git 
a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt 
b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
index a95a51c..61e0db5 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
@@ -16,130 +16,33 @@
 
 package net.taler.wallet.exchanges
 
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.View.GONE
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.core.content.ContextCompat.getColor
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.activityViewModels
-import androidx.recyclerview.widget.RecyclerView.Adapter
-import androidx.recyclerview.widget.RecyclerView.ViewHolder
-import net.taler.common.toRelativeTime
-import net.taler.common.toShortDate
-import net.taler.lib.common.Amount
-import net.taler.wallet.MainViewModel
-import net.taler.wallet.R
-import net.taler.wallet.databinding.FragmentSelectExchangeBinding
-import net.taler.wallet.exchanges.CoinFeeAdapter.CoinFeeViewHolder
-import net.taler.wallet.exchanges.WireFeeAdapter.WireFeeViewHolder
+import androidx.navigation.fragment.findNavController
+import net.taler.common.fadeOut
 
-class SelectExchangeFragment : Fragment() {
+class SelectExchangeFragment : ExchangeListFragment() {
 
-    private val model: MainViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
-    private lateinit var ui: FragmentSelectExchangeBinding
-
-    override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-        ui = FragmentSelectExchangeBinding.inflate(inflater, container, false)
-        return ui.root
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        val fees = withdrawManager.exchangeFees ?: throw 
IllegalStateException()
-        if (fees.withdrawFee.isZero()) {
-            ui.withdrawFeeLabel.visibility = GONE
-            ui.withdrawFeeView.visibility = GONE
-        } else ui.withdrawFeeView.setAmount(fees.withdrawFee)
-        if (fees.overhead.isZero()) {
-            ui.overheadLabel.visibility = GONE
-            ui.overheadView.visibility = GONE
-        } else ui.overheadView.setAmount(fees.overhead)
-        ui.expirationView.text = 
fees.earliestDepositExpiration.ms.toRelativeTime(requireContext())
-        ui.coinFeesList.adapter = CoinFeeAdapter(fees.coinFees)
-        ui.wireFeesList.adapter = WireFeeAdapter(fees.wireFees)
-    }
-
-    private fun TextView.setAmount(amount: Amount) {
-        if (amount.isZero()) text = amount.toString()
-        else {
-            text = getString(R.string.amount_negative, amount)
-            setTextColor(getColor(context, R.color.red))
-        }
+    override val isSelectOnly = true
+    private val exchangeSelection by lazy {
+        
requireNotNull(withdrawManager.exchangeSelection.value?.getEvenIfConsumedAlready())
     }
 
-}
-
-private class CoinFeeAdapter(private val items: List<CoinFee>) : 
Adapter<CoinFeeViewHolder>() {
-    override fun getItemCount() = items.size
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
CoinFeeViewHolder {
-        val v =
-            
LayoutInflater.from(parent.context).inflate(R.layout.list_item_coin_fee, 
parent, false)
-        return CoinFeeViewHolder(v)
+    override fun onExchangeUpdate(exchanges: List<ExchangeItem>) {
+        ui.progressBar.fadeOut()
+        super.onExchangeUpdate(exchanges.filter { exchangeItem ->
+            exchangeItem.currency == exchangeSelection.amount.currency
+        })
     }
 
-    override fun onBindViewHolder(holder: CoinFeeViewHolder, position: Int) {
-        holder.bind(items[position])
+    override fun onExchangeSelected(item: ExchangeItem) {
+        withdrawManager.getWithdrawalDetails(
+            exchangeBaseUrl = item.exchangeBaseUrl,
+            amount = exchangeSelection.amount,
+            showTosImmediately = true,
+            uri = exchangeSelection.talerWithdrawUri,
+        )
+        findNavController().navigateUp()
     }
 
-    private class CoinFeeViewHolder(private val v: View) : ViewHolder(v) {
-        private val res = v.context.resources
-        private val coinView: TextView = v.findViewById(R.id.coinView)
-        private val withdrawFeeView: TextView = 
v.findViewById(R.id.withdrawFeeView)
-        private val depositFeeView: TextView = 
v.findViewById(R.id.depositFeeView)
-        private val refreshFeeView: TextView = 
v.findViewById(R.id.refreshFeeView)
-        private val refundFeeView: TextView = 
v.findViewById(R.id.refundFeeView)
-        fun bind(item: CoinFee) {
-            coinView.text = res.getQuantityString(
-                R.plurals.exchange_fee_coin,
-                item.quantity,
-                item.coin,
-                item.quantity
-            )
-            withdrawFeeView.text =
-                v.context.getString(R.string.exchange_fee_withdraw_fee, 
item.feeWithdraw)
-            depositFeeView.text =
-                v.context.getString(R.string.exchange_fee_deposit_fee, 
item.feeDeposit)
-            refreshFeeView.text =
-                v.context.getString(R.string.exchange_fee_refresh_fee, 
item.feeRefresh)
-            refundFeeView.text =
-                v.context.getString(R.string.exchange_fee_refund_fee, 
item.feeRefresh)
-        }
-    }
-}
-
-private class WireFeeAdapter(private val items: List<WireFee>) : 
Adapter<WireFeeViewHolder>() {
-    override fun getItemCount() = items.size
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
WireFeeViewHolder {
-        val v =
-            
LayoutInflater.from(parent.context).inflate(R.layout.list_item_wire_fee, 
parent, false)
-        return WireFeeViewHolder(v)
-    }
-
-    override fun onBindViewHolder(holder: WireFeeViewHolder, position: Int) {
-        holder.bind(items[position])
-    }
-
-    private class WireFeeViewHolder(private val v: View) : ViewHolder(v) {
-        private val validityView: TextView = v.findViewById(R.id.validityView)
-        private val wireFeeView: TextView = v.findViewById(R.id.wireFeeView)
-        private val closingFeeView: TextView = 
v.findViewById(R.id.closingFeeView)
-        fun bind(item: WireFee) {
-            validityView.text = v.context.getString(
-                R.string.exchange_fee_wire_fee_timespan,
-                item.start.ms.toShortDate(v.context),
-                item.end.ms.toShortDate(v.context)
-            )
-            wireFeeView.text =
-                v.context.getString(R.string.exchange_fee_wire_fee_wire_fee, 
item.wireFee)
-            closingFeeView.text =
-                
v.context.getString(R.string.exchange_fee_wire_fee_closing_fee, item.closingFee)
-        }
-    }
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/ManualWithdrawFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/ManualWithdrawFragment.kt
index f368c68..47c2c6b 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/ManualWithdrawFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/ManualWithdrawFragment.kt
@@ -21,10 +21,9 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import android.widget.Toast
-import android.widget.Toast.LENGTH_SHORT
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
+import androidx.navigation.fragment.findNavController
 import net.taler.common.hideKeyboard
 import net.taler.lib.common.Amount
 import net.taler.wallet.MainViewModel
@@ -44,7 +43,7 @@ class ManualWithdrawFragment : Fragment() {
 
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
+        savedInstanceState: Bundle?,
     ): View? {
         ui = FragmentManualWithdrawBinding.inflate(inflater, container, false)
         return ui.root
@@ -70,8 +69,9 @@ class ManualWithdrawFragment : Fragment() {
         val value = ui.amountView.text.toString().toLong()
         val amount = Amount(exchangeItem.currency, value, 0)
         ui.amountView.hideKeyboard()
-        Toast.makeText(requireContext(), "Not implemented: $amount", 
LENGTH_SHORT).show()
+
         withdrawManager.getWithdrawalDetails(exchangeItem.exchangeBaseUrl, 
amount)
+        
findNavController().navigate(R.id.action_nav_exchange_manual_withdrawal_to_promptWithdraw)
     }
 
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt 
b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
index 0c7687c..38e09fa 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -20,13 +20,12 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import android.widget.Toast
-import android.widget.Toast.LENGTH_SHORT
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
 import com.google.android.material.snackbar.Snackbar
 import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
+import net.taler.common.EventObserver
 import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.lib.common.Amount
@@ -35,6 +34,7 @@ import net.taler.wallet.R
 import net.taler.wallet.cleanExchange
 import net.taler.wallet.databinding.FragmentPromptWithdrawBinding
 import net.taler.wallet.withdraw.WithdrawStatus.Loading
+import net.taler.wallet.withdraw.WithdrawStatus.ReceivedDetails
 import net.taler.wallet.withdraw.WithdrawStatus.TosReviewRequired
 import net.taler.wallet.withdraw.WithdrawStatus.Withdrawing
 
@@ -46,8 +46,9 @@ class PromptWithdrawFragment : Fragment() {
     private lateinit var ui: FragmentPromptWithdrawBinding
 
     override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?,
     ): View? {
         ui = FragmentPromptWithdrawBinding.inflate(inflater, container, false)
         return ui.root
@@ -59,21 +60,26 @@ class PromptWithdrawFragment : Fragment() {
         withdrawManager.withdrawStatus.observe(viewLifecycleOwner, {
             showWithdrawStatus(it)
         })
+        withdrawManager.exchangeSelection.observe(viewLifecycleOwner, 
EventObserver {
+            
findNavController().navigate(R.id.action_promptWithdraw_to_selectExchangeFragment)
+        })
     }
 
     private fun showWithdrawStatus(status: WithdrawStatus?): Any = when 
(status) {
-        is WithdrawStatus.ReceivedDetails -> {
-            showContent(status.amountRaw, status.amountEffective, 
status.exchangeBaseUrl)
-            ui.confirmWithdrawButton.apply {
-                text = getString(R.string.withdraw_button_confirm)
-                setOnClickListener {
-                    it.fadeOut()
-                    ui.confirmProgressBar.fadeIn()
-                    withdrawManager.acceptWithdrawal()
-                }
-                isEnabled = true
+        null -> model.showProgressBar.value = false
+        is Loading -> model.showProgressBar.value = true
+        is WithdrawStatus.NeedsExchange -> {
+            model.showProgressBar.value = false
+            val exchangeSelection = status.exchangeSelection.getIfNotConsumed()
+            if (exchangeSelection == null) { // already consumed
+                findNavController().popBackStack()
+            } else {
+                withdrawManager.selectExchange(exchangeSelection)
             }
         }
+        is TosReviewRequired -> onTosReviewRequired(status)
+        is ReceivedDetails -> onReceivedDetails(status)
+        is Withdrawing -> model.showProgressBar.value = true
         is WithdrawStatus.Success -> {
             model.showProgressBar.value = false
             withdrawManager.withdrawStatus.value = null
@@ -81,14 +87,18 @@ class PromptWithdrawFragment : Fragment() {
             model.showTransactions(status.currency)
             Snackbar.make(requireView(), R.string.withdraw_initiated, 
LENGTH_LONG).show()
         }
-        is Loading -> {
-            model.showProgressBar.value = true
-        }
-        is Withdrawing -> {
-            model.showProgressBar.value = true
+        is WithdrawStatus.Error -> {
+            model.showProgressBar.value = false
+            
findNavController().navigate(R.id.action_promptWithdraw_to_errorFragment)
         }
-        is TosReviewRequired -> {
-            showContent(status.amountRaw, status.amountEffective, 
status.exchangeBaseUrl)
+    }
+
+    private fun onTosReviewRequired(s: TosReviewRequired) {
+        model.showProgressBar.value = false
+        if (s.showImmediately.getIfNotConsumed() == true) {
+            
findNavController().navigate(R.id.action_promptWithdraw_to_reviewExchangeTOS)
+        } else {
+            showContent(s.amountRaw, s.amountEffective, s.exchangeBaseUrl, 
s.talerWithdrawUri)
             ui.confirmWithdrawButton.apply {
                 text = getString(R.string.withdraw_button_tos)
                 setOnClickListener {
@@ -97,14 +107,27 @@ class PromptWithdrawFragment : Fragment() {
                 isEnabled = true
             }
         }
-        is WithdrawStatus.Error -> {
-            model.showProgressBar.value = false
-            
findNavController().navigate(R.id.action_promptWithdraw_to_errorFragment)
+    }
+
+    private fun onReceivedDetails(s: ReceivedDetails) {
+        showContent(s.amountRaw, s.amountEffective, s.exchangeBaseUrl, 
s.talerWithdrawUri)
+        ui.confirmWithdrawButton.apply {
+            text = getString(R.string.withdraw_button_confirm)
+            setOnClickListener {
+                it.fadeOut()
+                ui.confirmProgressBar.fadeIn()
+                withdrawManager.acceptWithdrawal()
+            }
+            isEnabled = true
         }
-        null -> model.showProgressBar.value = false
     }
 
-    private fun showContent(amountRaw: Amount, amountEffective: Amount, 
exchange: String) {
+    private fun showContent(
+        amountRaw: Amount,
+        amountEffective: Amount,
+        exchange: String,
+        uri: String?,
+    ) {
         model.showProgressBar.value = false
         ui.progressBar.fadeOut()
 
@@ -117,15 +140,20 @@ class PromptWithdrawFragment : Fragment() {
         ui.chosenAmountView.fadeIn()
 
         ui.feeLabel.fadeIn()
-        ui.feeView.text = getString(R.string.amount_negative, (amountRaw - 
amountEffective).toString())
+        ui.feeView.text =
+            getString(R.string.amount_negative, (amountRaw - 
amountEffective).toString())
         ui.feeView.fadeIn()
 
         ui.exchangeIntroView.fadeIn()
         ui.withdrawExchangeUrl.text = cleanExchange(exchange)
         ui.withdrawExchangeUrl.fadeIn()
-        ui.selectExchangeButton.fadeIn()
-        ui.selectExchangeButton.setOnClickListener {
-            Toast.makeText(context, "Not yet implemented", LENGTH_SHORT).show()
+
+        if (uri != null) {  // no Uri for manual withdrawals
+            ui.selectExchangeButton.fadeIn()
+            ui.selectExchangeButton.setOnClickListener {
+                val exchangeSelection = ExchangeSelection(amountRaw, uri)
+                withdrawManager.selectExchange(exchangeSelection)
+            }
         }
 
         ui.withdrawCard.fadeIn()
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 25c5b72..5e11c04 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
@@ -18,10 +18,13 @@ package net.taler.wallet.withdraw
 
 import android.util.Log
 import androidx.annotation.UiThread
+import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import kotlinx.serialization.Serializable
+import net.taler.common.Event
+import net.taler.common.toEvent
 import net.taler.lib.common.Amount
 import net.taler.wallet.TAG
 import net.taler.wallet.backend.TalerErrorInfo
@@ -32,20 +35,23 @@ import 
net.taler.wallet.withdraw.WithdrawStatus.ReceivedDetails
 
 sealed class WithdrawStatus {
     data class Loading(val talerWithdrawUri: String? = null) : WithdrawStatus()
+    data class NeedsExchange(val exchangeSelection: Event<ExchangeSelection>) 
: WithdrawStatus()
+
     data class TosReviewRequired(
         val talerWithdrawUri: String? = null,
         val exchangeBaseUrl: String,
         val amountRaw: Amount,
         val amountEffective: Amount,
         val tosText: String,
-        val tosEtag: String
+        val tosEtag: String,
+        val showImmediately: Event<Boolean>,
     ) : WithdrawStatus()
 
     data class ReceivedDetails(
         val talerWithdrawUri: String? = null,
         val exchangeBaseUrl: String,
         val amountRaw: Amount,
-        val amountEffective: Amount
+        val amountEffective: Amount,
     ) : WithdrawStatus()
 
     object Withdrawing : WithdrawStatus()
@@ -57,24 +63,31 @@ sealed class WithdrawStatus {
 data class WithdrawalDetailsForUri(
     val amount: Amount,
     val defaultExchangeBaseUrl: String?,
-    val possibleExchanges: List<ExchangeItem>
+    val possibleExchanges: List<ExchangeItem>,
 )
 
 @Serializable
 data class WithdrawalDetails(
     val tosAccepted: Boolean,
     val amountRaw: Amount,
-    val amountEffective: Amount
+    val amountEffective: Amount,
+)
+
+data class ExchangeSelection(
+    val amount: Amount,
+    val talerWithdrawUri: String,
 )
 
 class WithdrawManager(
     private val api: WalletBackendApi,
-    private val scope: CoroutineScope
+    private val scope: CoroutineScope,
 ) {
 
     val withdrawStatus = MutableLiveData<WithdrawStatus>()
     val testWithdrawalInProgress = MutableLiveData(false)
 
+    private val _exchangeSelection = 
MutableLiveData<Event<ExchangeSelection>>()
+    val exchangeSelection: LiveData<Event<ExchangeSelection>> = 
_exchangeSelection
     var exchangeFees: ExchangeFees? = null
         private set
 
@@ -87,6 +100,11 @@ class WithdrawManager(
         }
     }
 
+    @UiThread
+    fun selectExchange(selection: ExchangeSelection) {
+        _exchangeSelection.value = selection.toEvent()
+    }
+
     fun getWithdrawalDetails(uri: String) = scope.launch {
         withdrawStatus.value = WithdrawStatus.Loading(uri)
         api.request("getWithdrawalDetailsForUri", 
WithdrawalDetailsForUri.serializer()) {
@@ -95,11 +113,10 @@ class WithdrawManager(
             handleError("getWithdrawalDetailsForUri", error)
         }.onSuccess { details ->
             if (details.defaultExchangeBaseUrl == null) {
-                // TODO go to exchange selection screen instead
-                val chosenExchange = 
details.possibleExchanges[0].exchangeBaseUrl
-                getWithdrawalDetails(chosenExchange, details.amount, uri)
+                val exchangeSelection = ExchangeSelection(details.amount, uri)
+                withdrawStatus.value = 
WithdrawStatus.NeedsExchange(exchangeSelection.toEvent())
             } else {
-                getWithdrawalDetails(details.defaultExchangeBaseUrl, 
details.amount, uri)
+                getWithdrawalDetails(details.defaultExchangeBaseUrl, 
details.amount, false, uri)
             }
         }
     }
@@ -107,7 +124,8 @@ class WithdrawManager(
     fun getWithdrawalDetails(
         exchangeBaseUrl: String,
         amount: Amount,
-        uri: String? = null
+        showTosImmediately: Boolean = false,
+        uri: String? = null,
     ) = scope.launch {
         withdrawStatus.value = WithdrawStatus.Loading(uri)
         api.request("getWithdrawalDetailsForAmount", 
WithdrawalDetails.serializer()) {
@@ -121,16 +139,17 @@ class WithdrawManager(
                     talerWithdrawUri = uri,
                     exchangeBaseUrl = exchangeBaseUrl,
                     amountRaw = details.amountRaw,
-                    amountEffective = details.amountEffective
+                    amountEffective = details.amountEffective,
                 )
-            } else getExchangeTos(exchangeBaseUrl, details, uri)
+            } else getExchangeTos(exchangeBaseUrl, details, 
showTosImmediately, uri)
         }
     }
 
     private fun getExchangeTos(
         exchangeBaseUrl: String,
         details: WithdrawalDetails,
-        uri: String?
+        showImmediately: Boolean,
+        uri: String?,
     ) = scope.launch {
         api.request("getExchangeTos", TosResponse.serializer()) {
             put("exchangeBaseUrl", exchangeBaseUrl)
@@ -143,7 +162,8 @@ class WithdrawManager(
                 amountRaw = details.amountRaw,
                 amountEffective = details.amountEffective,
                 tosText = it.tos,
-                tosEtag = it.currentEtag
+                tosEtag = it.currentEtag,
+                showImmediately = showImmediately.toEvent(),
             )
         }
     }
@@ -163,7 +183,7 @@ class WithdrawManager(
                 talerWithdrawUri = s.talerWithdrawUri,
                 exchangeBaseUrl = s.exchangeBaseUrl,
                 amountRaw = s.amountRaw,
-                amountEffective = s.amountEffective
+                amountEffective = s.amountEffective,
             )
         }
     }
@@ -181,7 +201,7 @@ class WithdrawManager(
         api.request<Unit>(operation) {
             put("exchangeBaseUrl", status.exchangeBaseUrl)
             if (status.talerWithdrawUri == null) {
-                put("amount", status.amountRaw)
+                put("amount", status.amountRaw.toJSONString())
             } else {
                 put("talerWithdrawUri", status.talerWithdrawUri)
             }
diff --git a/wallet/src/main/res/layout/fragment_select_exchange.xml 
b/wallet/src/main/res/layout/fragment_exchange_fees.xml
similarity index 100%
rename from wallet/src/main/res/layout/fragment_select_exchange.xml
rename to wallet/src/main/res/layout/fragment_exchange_fees.xml
diff --git a/wallet/src/main/res/layout/fragment_prompt_withdraw.xml 
b/wallet/src/main/res/layout/fragment_prompt_withdraw.xml
index 6bca4ef..421911a 100644
--- a/wallet/src/main/res/layout/fragment_prompt_withdraw.xml
+++ b/wallet/src/main/res/layout/fragment_prompt_withdraw.xml
@@ -169,7 +169,7 @@
         android:contentDescription="@string/nav_exchange_fees"
         android:src="@drawable/ic_edit"
         android:tint="?attr/colorOnPrimary"
-        android:visibility="invisible"
+        android:visibility="gone"
         app:layout_constraintBottom_toBottomOf="@+id/withdrawExchangeUrl"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toEndOf="@+id/withdrawExchangeUrl"
diff --git a/wallet/src/main/res/navigation/nav_graph.xml 
b/wallet/src/main/res/navigation/nav_graph.xml
index d8ce5b2..e8929c9 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -75,7 +75,11 @@
     <fragment
         android:id="@+id/nav_exchange_manual_withdrawal"
         android:name="net.taler.wallet.withdraw.ManualWithdrawFragment"
-        android:label="@string/withdraw_title"/>
+        android:label="@string/withdraw_title">
+        <action
+            
android:id="@+id/action_nav_exchange_manual_withdrawal_to_promptWithdraw"
+            app:destination="@id/promptWithdraw" />
+    </fragment>
 
     <fragment
         android:id="@+id/nav_settings_backup"
@@ -152,8 +156,8 @@
     <fragment
         android:id="@+id/selectExchangeFragment"
         android:name="net.taler.wallet.exchanges.SelectExchangeFragment"
-        android:label="@string/nav_exchange_fees"
-        tools:layout="@layout/fragment_select_exchange" />
+        android:label="@string/nav_exchange_select"
+        tools:layout="@layout/fragment_exchange_list" />
 
     <fragment
         android:id="@+id/nav_pending_operations"
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index 24db2b0..2e32c88 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -39,6 +39,7 @@ GNU Taler is immune against many types of fraud, such as 
phishing of credit card
 
     <string name="nav_prompt_withdraw">Withdraw Digital Cash</string>
     <string name="nav_exchange_tos">Exchange\'s Terms of Service</string>
+    <string name="nav_exchange_select">Select Exchange</string>
     <string name="nav_exchange_fees">Exchange Fees</string>
     <string name="nav_error">Error</string>
 

-- 
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]