[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.
- [taler-taler-android] branch master updated (841d87d -> 44496bc),
gnunet <=