summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2024-01-31 13:16:19 -0600
committerIván Ávalos <avalos@disroot.org>2024-01-31 13:16:44 -0600
commit08786869d47f0ff0353e0d94cd8874cc3b1af3e2 (patch)
tree12ae7d05baaff64d315e6cfc768dd8ad728f299c
parent017793d969750b9cb44600454b9a0471cccc0f4b (diff)
downloadtaler-android-dev/ivan-avalos/exchsel.tar.gz
taler-android-dev/ivan-avalos/exchsel.tar.bz2
taler-android-dev/ivan-avalos/exchsel.zip
[wallet] Replace exchange selection fragment with dialog decoupled from withdrawalsdev/ivan-avalos/exchsel
-rw-r--r--wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeDialogFragment.kt111
-rw-r--r--wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt55
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt64
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt26
-rw-r--r--wallet/src/main/res/navigation/nav_graph.xml9
5 files changed, 174 insertions, 91 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeDialogFragment.kt b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeDialogFragment.kt
new file mode 100644
index 0000000..2da7618
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeDialogFragment.kt
@@ -0,0 +1,111 @@
+/*
+ * This file is part of GNU Taler
+ * (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
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.wallet.exchanges
+
+import android.app.Dialog
+import android.os.Bundle
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.ListItem
+import androidx.compose.material3.ListItemDefaults
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.res.stringResource
+import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.asFlow
+import com.google.accompanist.themeadapter.material3.Mdc3Theme
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import net.taler.common.Event
+import net.taler.common.toEvent
+import net.taler.wallet.R
+import net.taler.wallet.cleanExchange
+import net.taler.wallet.compose.collectAsStateLifecycleAware
+
+class SelectExchangeDialogFragment: DialogFragment() {
+ private var exchangeList = MutableLiveData<List<ExchangeItem>>()
+
+ private var mExchangeSelection = MutableLiveData<Event<ExchangeItem>>()
+ val exchangeSelection: LiveData<Event<ExchangeItem>> = mExchangeSelection
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val view = ComposeView(requireContext()).apply {
+ setContent {
+ val exchanges = exchangeList.asFlow().collectAsStateLifecycleAware(initial = emptyList())
+ SelectExchangeComposable(exchanges.value) {
+ onExchangeSelected(it)
+ }
+ }
+ }
+
+ return MaterialAlertDialogBuilder(requireContext(), R.style.MaterialAlertDialog_Material3)
+ .setIcon(R.drawable.ic_account_balance)
+ .setTitle(R.string.exchange_list_add)
+ .setView(view)
+ .setNegativeButton(R.string.cancel) { _, _ ->
+ dismiss()
+ }
+ .create()
+ }
+
+ fun setExchanges(exchanges: List<ExchangeItem>) {
+ exchangeList.value = exchanges
+ }
+
+ private fun onExchangeSelected(exchange: ExchangeItem) {
+ mExchangeSelection.value = exchange.toEvent()
+ dismiss()
+ }
+}
+
+@Composable
+fun SelectExchangeComposable(
+ exchanges: List<ExchangeItem>,
+ onExchangeSelected: (exchange: ExchangeItem) -> Unit,
+) {
+ Mdc3Theme {
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ ) {
+ items(exchanges) {
+ ExchangeItemComposable(it) {
+ onExchangeSelected(it)
+ }
+ }
+ }
+ }
+}
+
+@Composable
+fun ExchangeItemComposable(exchange: ExchangeItem, onSelected: () -> Unit) {
+ ListItem(
+ modifier = Modifier.clickable { onSelected() },
+ headlineContent = { Text(cleanExchange(exchange.exchangeBaseUrl)) },
+ supportingContent = exchange.currency?.let {
+ { Text(stringResource(R.string.exchange_list_currency, it)) }
+ },
+ colors = ListItemDefaults.colors(
+ containerColor = Color.Transparent,
+ )
+ )
+} \ No newline at end of file
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
deleted file mode 100644
index 732e0c5..0000000
--- a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This file is part of GNU Taler
- * (C) 2020 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
- * Foundation; either version 3, or (at your option) any later version.
- *
- * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-package net.taler.wallet.exchanges
-
-import androidx.navigation.fragment.findNavController
-import net.taler.common.fadeOut
-import net.taler.wallet.withdraw.WithdrawStatus.ReceivedDetails
-
-class SelectExchangeFragment : ExchangeListFragment() {
-
- private val withdrawManager by lazy { model.withdrawManager }
-
- override val isSelectOnly = true
- private val exchangeSelection by lazy {
- requireNotNull(withdrawManager.exchangeSelection.value?.getEvenIfConsumedAlready())
- }
-
- override fun onExchangeUpdate(exchanges: List<ExchangeItem>) {
- ui.progressBar.fadeOut()
- val status = withdrawManager.withdrawStatus.value
- if (status is ReceivedDetails) {
- super.onExchangeUpdate(status.possibleExchanges)
- } else {
- findNavController().navigateUp()
- }
- }
-
- override fun onExchangeSelected(item: ExchangeItem) {
- val status = withdrawManager.withdrawStatus.value
- val exchanges = (status as? ReceivedDetails)?.possibleExchanges ?: emptyList()
- withdrawManager.getWithdrawalDetails(
- exchangeBaseUrl = item.exchangeBaseUrl,
- amount = exchangeSelection.amount,
- showTosImmediately = true,
- uri = exchangeSelection.talerWithdrawUri,
- possibleExchanges = exchanges,
- )
- findNavController().navigateUp()
- }
-
-}
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 caad7b6..16b956b 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -36,10 +36,13 @@ import net.taler.wallet.MainViewModel
import net.taler.wallet.R
import net.taler.wallet.cleanExchange
import net.taler.wallet.databinding.FragmentPromptWithdrawBinding
+import net.taler.wallet.exchanges.ExchangeItem
+import net.taler.wallet.exchanges.SelectExchangeDialogFragment
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
+import net.taler.wallet.withdraw.WithdrawStatus.NeedsExchange
class PromptWithdrawFragment : Fragment() {
@@ -47,6 +50,8 @@ class PromptWithdrawFragment : Fragment() {
private val withdrawManager by lazy { model.withdrawManager }
private val transactionManager by lazy { model.transactionManager }
+ private val selectExchangeDialog = SelectExchangeDialogFragment()
+
private lateinit var ui: FragmentPromptWithdrawBinding
override fun onCreateView(
@@ -64,22 +69,20 @@ class PromptWithdrawFragment : Fragment() {
withdrawManager.withdrawStatus.observe(viewLifecycleOwner) {
showWithdrawStatus(it)
}
- withdrawManager.exchangeSelection.observe(viewLifecycleOwner, EventObserver {
- findNavController().navigate(R.id.action_promptWithdraw_to_selectExchangeFragment)
+
+ selectExchangeDialog.exchangeSelection.observe(viewLifecycleOwner, EventObserver {
+ onExchangeSelected(it)
})
}
private fun showWithdrawStatus(status: WithdrawStatus?): Any = when (status) {
null -> model.showProgressBar.value = false
is Loading -> model.showProgressBar.value = true
- is WithdrawStatus.NeedsExchange -> {
+ is NeedsExchange -> {
model.showProgressBar.value = false
- val exchangeSelection = status.exchangeSelection.getIfNotConsumed()
- if (exchangeSelection == null) { // already consumed
- findNavController().popBackStack()
- } else {
- withdrawManager.selectExchange(exchangeSelection)
- }
+ if (selectExchangeDialog.dialog?.isShowing != true) {
+ selectExchange()
+ } else {}
}
is TosReviewRequired -> onTosReviewRequired(status)
is ReceivedDetails -> onReceivedDetails(status)
@@ -178,8 +181,7 @@ class PromptWithdrawFragment : Fragment() {
if (uri != null) { // no Uri for manual withdrawals
ui.selectExchangeButton.fadeIn()
ui.selectExchangeButton.setOnClickListener {
- val exchangeSelection = ExchangeSelection(amountRaw, uri)
- withdrawManager.selectExchange(exchangeSelection)
+ selectExchange()
}
}
@@ -195,4 +197,44 @@ class PromptWithdrawFragment : Fragment() {
ui.withdrawCard.fadeIn()
}
+ private fun selectExchange() {
+ val exchanges = when (val status = withdrawManager.withdrawStatus.value) {
+ is ReceivedDetails -> status.possibleExchanges
+ is NeedsExchange -> status.possibleExchanges
+ is TosReviewRequired -> status.possibleExchanges
+ else -> return
+ }
+ selectExchangeDialog.setExchanges(exchanges)
+ selectExchangeDialog.show(parentFragmentManager, "SELECT_EXCHANGE")
+ }
+
+ private fun onExchangeSelected(exchange: ExchangeItem) {
+ val status = withdrawManager.withdrawStatus.value
+ val amount = when (status) {
+ is ReceivedDetails -> status.amountRaw
+ is NeedsExchange -> status.amount
+ is TosReviewRequired -> status.amountRaw
+ else -> return
+ }
+ val uri = when (status) {
+ is ReceivedDetails -> status.talerWithdrawUri
+ is NeedsExchange -> status.talerWithdrawUri
+ is TosReviewRequired -> status.talerWithdrawUri
+ else -> return
+ }
+ val exchanges = when (status) {
+ is ReceivedDetails -> status.possibleExchanges
+ is NeedsExchange -> status.possibleExchanges
+ is TosReviewRequired -> status.possibleExchanges
+ else -> return
+ }
+
+ withdrawManager.getWithdrawalDetails(
+ exchangeBaseUrl = exchange.exchangeBaseUrl,
+ amount = amount,
+ showTosImmediately = false,
+ uri = uri,
+ possibleExchanges = exchanges,
+ )
+ }
}
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 34ae69f..6e8eafd 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
@@ -20,7 +20,6 @@ import android.net.Uri
import android.util.Log
import androidx.annotation.UiThread
import androidx.annotation.WorkerThread
-import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -40,7 +39,11 @@ 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 NeedsExchange(
+ val talerWithdrawUri: String,
+ val amount: Amount,
+ val possibleExchanges: List<ExchangeItem>,
+ ) : WithdrawStatus()
data class TosReviewRequired(
val talerWithdrawUri: String? = null,
@@ -146,11 +149,6 @@ data class AcceptManualWithdrawalResponse(
val transactionId: String,
)
-data class ExchangeSelection(
- val amount: Amount,
- val talerWithdrawUri: String,
-)
-
class WithdrawManager(
private val api: WalletBackendApi,
private val scope: CoroutineScope,
@@ -159,8 +157,6 @@ class WithdrawManager(
val withdrawStatus = MutableLiveData<WithdrawStatus>()
val testWithdrawalStatus = MutableLiveData<WithdrawTestStatus>()
- private val _exchangeSelection = MutableLiveData<Event<ExchangeSelection>>()
- val exchangeSelection: LiveData<Event<ExchangeSelection>> = _exchangeSelection
var exchangeFees: ExchangeFees? = null
private set
@@ -173,11 +169,6 @@ 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()) {
@@ -186,8 +177,11 @@ class WithdrawManager(
handleError("getWithdrawalDetailsForUri", error)
}.onSuccess { details ->
if (details.defaultExchangeBaseUrl == null) {
- val exchangeSelection = ExchangeSelection(details.amount, uri)
- withdrawStatus.value = WithdrawStatus.NeedsExchange(exchangeSelection.toEvent())
+ withdrawStatus.value = WithdrawStatus.NeedsExchange(
+ talerWithdrawUri = uri,
+ amount = details.amount,
+ possibleExchanges = details.possibleExchanges,
+ )
} else getWithdrawalDetails(
exchangeBaseUrl = details.defaultExchangeBaseUrl,
amount = details.amount,
diff --git a/wallet/src/main/res/navigation/nav_graph.xml b/wallet/src/main/res/navigation/nav_graph.xml
index 8c1010c..24def7f 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -301,9 +301,6 @@
android:label="@string/nav_prompt_withdraw"
tools:layout="@layout/fragment_prompt_withdraw">
<action
- android:id="@+id/action_promptWithdraw_to_selectExchangeFragment"
- app:destination="@id/selectExchangeFragment" />
- <action
android:id="@+id/action_promptWithdraw_to_reviewExchangeTOS"
app:destination="@id/reviewExchangeTOS" />
<action
@@ -335,12 +332,6 @@
app:popUpTo="@id/nav_main" />
</fragment>
<fragment
- android:id="@+id/selectExchangeFragment"
- android:name="net.taler.wallet.exchanges.SelectExchangeFragment"
- android:label="@string/nav_exchange_select"
- tools:layout="@layout/fragment_exchange_list" />
-
- <fragment
android:id="@+id/nav_pending_operations"
android:name="net.taler.wallet.pending.PendingOperationsFragment"
android:label="@string/pending_operations_title"