diff options
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/exchanges')
9 files changed, 383 insertions, 81 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/AddExchangeDialogFragment.kt b/wallet/src/main/java/net/taler/wallet/exchanges/AddExchangeDialogFragment.kt index 5ea763a..fd942b0 100644 --- a/wallet/src/main/java/net/taler/wallet/exchanges/AddExchangeDialogFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/exchanges/AddExchangeDialogFragment.kt @@ -22,6 +22,7 @@ import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels +import com.google.android.material.dialog.MaterialAlertDialogBuilder import net.taler.wallet.MainViewModel import net.taler.wallet.R @@ -32,7 +33,7 @@ class AddExchangeDialogFragment : DialogFragment() { private val exchangeManager by lazy { model.exchangeManager } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return AlertDialog.Builder(requireContext(), R.style.DialogTheme) + return MaterialAlertDialogBuilder(requireContext(), R.style.MaterialAlertDialog_Material3) .setIcon(R.drawable.ic_account_balance) .setTitle(R.string.exchange_list_add) .setView(R.layout.dialog_exchange_add) 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 e315632..674632e 100644 --- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeAdapter.kt +++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeAdapter.kt @@ -26,23 +26,15 @@ import android.widget.TextView import androidx.appcompat.widget.PopupMenu import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.Adapter -import kotlinx.serialization.Serializable import net.taler.wallet.R -import net.taler.wallet.cleanExchange import net.taler.wallet.exchanges.ExchangeAdapter.ExchangeItemViewHolder -@Serializable -data class ExchangeItem( - val exchangeBaseUrl: String, - val currency: String, - val paytoUris: List<String> -) { - val name: String get() = cleanExchange(exchangeBaseUrl) -} - interface ExchangeClickListener { fun onExchangeSelected(item: ExchangeItem) fun onManualWithdraw(item: ExchangeItem) + fun onPeerReceive(item: ExchangeItem) + fun onExchangeReload(item: ExchangeItem) + fun onExchangeDelete(item: ExchangeItem) } internal class ExchangeAdapter( @@ -78,14 +70,20 @@ internal class ExchangeAdapter( fun bind(item: ExchangeItem) { urlView.text = item.name - currencyView.text = context.getString(R.string.exchange_list_currency, item.currency) + // If currency is null, it's because we have no data from the exchange... + currencyView.text = if (item.currency == null) { + context.getString(R.string.exchange_not_contacted) + } else { + 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 + // ...thus, we should prevent the user from interacting with it. + overflowIcon.visibility = if (item.currency != null) VISIBLE else GONE } overflowIcon.setOnClickListener { openMenu(overflowIcon, item) } } @@ -98,6 +96,18 @@ internal class ExchangeAdapter( listener.onManualWithdraw(item) true } + R.id.action_receive_peer -> { + listener.onPeerReceive(item) + true + } + R.id.action_reload -> { + listener.onExchangeReload(item) + true + } + R.id.action_delete -> { + listener.onExchangeDelete(item) + true + } else -> false } } diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt index 1da9b49..7824d1e 100644 --- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt +++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFees.kt @@ -16,8 +16,9 @@ package net.taler.wallet.exchanges -import net.taler.lib.common.Amount -import net.taler.lib.common.Timestamp +import net.taler.common.Amount +import net.taler.common.Timestamp + data class CoinFee( val coin: Amount, diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt index c59fffe..d42ab2c 100644 --- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeFeesFragment.kt @@ -22,19 +22,19 @@ 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.Amount 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.FragmentExchangeFeesBinding import net.taler.wallet.exchanges.CoinFeeAdapter.CoinFeeViewHolder import net.taler.wallet.exchanges.WireFeeAdapter.WireFeeViewHolder +import net.taler.wallet.getAttrColor class ExchangeFeesFragment : Fragment() { @@ -71,7 +71,7 @@ class ExchangeFeesFragment : Fragment() { if (amount.isZero()) text = amount.toString() else { text = getString(R.string.amount_negative, amount) - setTextColor(getColor(context, R.color.red)) + setText(requireContext().getAttrColor(R.attr.colorError)) } } @@ -89,7 +89,7 @@ private class CoinFeeAdapter(private val items: List<CoinFee>) : Adapter<CoinFee holder.bind(items[position]) } - private class CoinFeeViewHolder(private val v: View) : ViewHolder(v) { + 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) @@ -127,7 +127,7 @@ private class WireFeeAdapter(private val items: List<WireFee>) : Adapter<WireFee holder.bind(items[position]) } - private class WireFeeViewHolder(private val v: View) : ViewHolder(v) { + 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) 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 9a96b59..8a40bff 100644 --- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListFragment.kt @@ -18,26 +18,35 @@ package net.taler.wallet.exchanges import android.os.Bundle import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.Toast import android.widget.Toast.LENGTH_LONG +import androidx.core.view.MenuProvider import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Lifecycle.State.RESUMED import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL +import com.google.android.material.dialog.MaterialAlertDialogBuilder import net.taler.common.EventObserver import net.taler.common.fadeIn import net.taler.common.fadeOut +import net.taler.common.showError import net.taler.wallet.MainViewModel import net.taler.wallet.R import net.taler.wallet.databinding.FragmentExchangeListBinding +import net.taler.wallet.showError open class ExchangeListFragment : Fragment(), ExchangeClickListener { protected val model: MainViewModel by activityViewModels() private val exchangeManager by lazy { model.exchangeManager } + private val transactionManager get() = model.transactionManager protected lateinit var ui: FragmentExchangeListBinding protected open val isSelectOnly = false @@ -53,6 +62,21 @@ open class ExchangeListFragment : Fragment(), ExchangeClickListener { } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + requireActivity().addMenuProvider(object : MenuProvider { + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + if (model.devMode.value == true) { + menuInflater.inflate(R.menu.exchange_list, menu) + } + } + + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + if (menuItem.itemId == R.id.action_add_dev_exchanges) { + exchangeManager.addDevExchanges() + } + return true + } + }, viewLifecycleOwner, RESUMED) + ui.list.apply { adapter = exchangeAdapter addItemDecoration(DividerItemDecoration(context, VERTICAL)) @@ -61,14 +85,37 @@ open class ExchangeListFragment : Fragment(), ExchangeClickListener { AddExchangeDialogFragment().show(parentFragmentManager, "ADD_EXCHANGE") } - exchangeManager.progress.observe(viewLifecycleOwner, { show -> + exchangeManager.progress.observe(viewLifecycleOwner) { show -> if (show) ui.progressBar.fadeIn() else ui.progressBar.fadeOut() - }) - exchangeManager.exchanges.observe(viewLifecycleOwner, { exchanges -> + } + exchangeManager.exchanges.observe(viewLifecycleOwner) { exchanges -> onExchangeUpdate(exchanges) - }) + } exchangeManager.addError.observe(viewLifecycleOwner, EventObserver { error -> - if (error) onAddExchangeFailed() + onAddExchangeFailed() + if (model.devMode.value == true) { + showError(error) + } + }) + exchangeManager.listError.observe(viewLifecycleOwner, EventObserver { error -> + onListExchangeFailed() + if (model.devMode.value == true) { + showError(error) + } + }) + exchangeManager.deleteError.observe(viewLifecycleOwner, EventObserver { error -> + if (model.devMode.value == true) { + showError(error) + } else { + showError(error.userFacingMsg) + } + }) + exchangeManager.reloadError.observe(viewLifecycleOwner, EventObserver { error -> + if (model.devMode.value == true) { + showError(error) + } else { + showError(error.userFacingMsg) + } }) } @@ -87,6 +134,10 @@ open class ExchangeListFragment : Fragment(), ExchangeClickListener { Toast.makeText(requireContext(), R.string.exchange_add_error, LENGTH_LONG).show() } + private fun onListExchangeFailed() { + Toast.makeText(requireContext(), R.string.exchange_list_error, LENGTH_LONG).show() + } + override fun onExchangeSelected(item: ExchangeItem) { throw AssertionError("must not get triggered here") } @@ -96,4 +147,28 @@ open class ExchangeListFragment : Fragment(), ExchangeClickListener { findNavController().navigate(R.id.action_nav_settings_exchanges_to_nav_exchange_manual_withdrawal) } + override fun onPeerReceive(item: ExchangeItem) { + transactionManager.selectedScope = item.scopeInfo + findNavController().navigate(R.id.action_global_receiveFunds) + } + + override fun onExchangeReload(item: ExchangeItem) { + exchangeManager.reload(item.exchangeBaseUrl) + } + + override fun onExchangeDelete(item: ExchangeItem) { + val optionsArray = arrayOf(getString(R.string.exchange_delete_force)) + val checkedArray = BooleanArray(1) { false } + + MaterialAlertDialogBuilder(requireContext(), R.style.MaterialAlertDialog_Material3) + .setTitle(R.string.exchange_delete) + .setMultiChoiceItems(optionsArray, checkedArray) { _, which, isChecked -> + checkedArray[which] = isChecked + } + .setNegativeButton(R.string.transactions_delete) { _, _ -> + exchangeManager.delete(item.exchangeBaseUrl, checkedArray[0]) + } + .setPositiveButton(R.string.cancel) { _, _ -> } + .show() + } } diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt index 8205eb7..fa357b5 100644 --- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt +++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeManager.kt @@ -17,24 +17,34 @@ package net.taler.wallet.exchanges import android.util.Log +import androidx.annotation.WorkerThread import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch import kotlinx.serialization.Serializable import net.taler.common.Event import net.taler.common.toEvent import net.taler.wallet.TAG +import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.backend.WalletBackendApi @Serializable data class ExchangeListResponse( - val exchanges: List<ExchangeItem> + val exchanges: List<ExchangeItem>, +) + +@Serializable +data class ExchangeDetailedResponse( + val exchange: ExchangeItem, ) class ExchangeManager( private val api: WalletBackendApi, - private val scope: CoroutineScope + private val scope: CoroutineScope, ) { private val mProgress = MutableLiveData<Boolean>() @@ -43,8 +53,17 @@ class ExchangeManager( private val mExchanges = MutableLiveData<List<ExchangeItem>>() val exchanges: LiveData<List<ExchangeItem>> get() = list() - private val mAddError = MutableLiveData<Event<Boolean>>() - val addError: LiveData<Event<Boolean>> = mAddError + private val mAddError = MutableLiveData<Event<TalerErrorInfo>>() + val addError: LiveData<Event<TalerErrorInfo>> = mAddError + + private val mListError = MutableLiveData<Event<TalerErrorInfo>>() + val listError: LiveData<Event<TalerErrorInfo>> = mListError + + private val mDeleteError = MutableLiveData<Event<TalerErrorInfo>>() + val deleteError: LiveData<Event<TalerErrorInfo>> = mDeleteError + + private val mReloadError = MutableLiveData<Event<TalerErrorInfo>>() + val reloadError: LiveData<Event<TalerErrorInfo>> = mReloadError var withdrawalExchange: ExchangeItem? = null @@ -53,7 +72,8 @@ class ExchangeManager( scope.launch { val response = api.request("listExchanges", ExchangeListResponse.serializer()) response.onError { - throw AssertionError("Wallet core failed to return exchanges!") + mProgress.value = false + mListError.value = it.toEvent() }.onSuccess { Log.d(TAG, "Exchange list: ${it.exchanges}") mProgress.value = false @@ -68,9 +88,9 @@ class ExchangeManager( api.request<Unit>("addExchange") { put("exchangeBaseUrl", exchangeUrl) }.onError { - mProgress.value = false Log.e(TAG, "Error adding exchange: $it") - mAddError.value = true.toEvent() + mProgress.value = false + mAddError.value = it.toEvent() }.onSuccess { mProgress.value = false Log.d(TAG, "Exchange $exchangeUrl added") @@ -78,4 +98,98 @@ class ExchangeManager( } } + fun reload(exchangeUrl: String, force: Boolean = true) = scope.launch { + mProgress.value = true + api.request<Unit>("updateExchangeEntry") { + put("exchangeBaseUrl", exchangeUrl) + put("force", force) + }.onError { + Log.e(TAG, "Error reloading exchange: $it") + mProgress.value = false + mReloadError.value = it.toEvent() + }.onSuccess { + mProgress.value = false + Log.d(TAG, "Exchange $exchangeUrl reloaded") + list() + } + } + + fun delete(exchangeUrl: String, purge: Boolean = false) = scope.launch { + mProgress.value = true + api.request<Unit>("deleteExchange") { + put("exchangeBaseUrl", exchangeUrl) + put("purge", purge) + }.onError { + Log.e(TAG, "Error deleting exchange: $it") + mProgress.value = false + mDeleteError.value = it.toEvent() + }.onSuccess { + mProgress.value = false + Log.d(TAG, "Exchange $exchangeUrl deleted") + list() + } + } + + fun findExchangeForCurrency(currency: String): Flow<ExchangeItem?> = flow { + emit(findExchange(currency)) + } + + @WorkerThread + suspend fun findExchange(currency: String): ExchangeItem? { + var exchange: ExchangeItem? = null + api.request( + operation = "listExchanges", + serializer = ExchangeListResponse.serializer() + ).onSuccess { exchangeListResponse -> + // just pick the first for now + exchange = exchangeListResponse.exchanges.find { it.currency == currency } + } + return exchange + } + + @WorkerThread + suspend fun findExchangeByUrl(exchangeUrl: String): ExchangeItem? { + var exchange: ExchangeItem? = null + api.request("getExchangeDetailedInfo", ExchangeDetailedResponse.serializer()) { + put("exchangeBaseUrl", exchangeUrl) + }.onError { + Log.e(TAG, "Error getExchangeDetailedInfo: $it") + }.onSuccess { + exchange = it.exchange + } + return exchange + } + + fun addDevExchanges() { + scope.launch { + listOf( + "https://exchange.demo.taler.net/", + "https://exchange.test.taler.net/", + "https://exchange.head.taler.net/", + "https://exchange.taler.ar/", + "https://exchange.taler.fdold.eu/", + "https://exchange.taler.grothoff.org/", + ).forEach { exchangeUrl -> + add(exchangeUrl) + delay(100) + } + exchanges.value?.let { exs -> + exs.find { + it.exchangeBaseUrl.startsWith("https://exchange.taler.fdold.eu") + }?.let { fDoldExchange -> + api.request<Unit>("addGlobalCurrencyExchange") { + put("currency", fDoldExchange.currency) + put("exchangeBaseUrl", fDoldExchange.exchangeBaseUrl) + put("exchangeMasterPub", + "7ER30ZWJEXAG026H5KG9M19NGTFC2DKKFPV79GVXA6DK5DCNSWXG") + }.onError { + Log.e(TAG, "Error addGlobalCurrencyExchange: $it") + }.onSuccess { + Log.i(TAG, "fdold is global now!") + } + } + } + } + } + } diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt b/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt new file mode 100644 index 0000000..0015e1c --- /dev/null +++ b/wallet/src/main/java/net/taler/wallet/exchanges/Exchanges.kt @@ -0,0 +1,38 @@ +/* + * 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 kotlinx.serialization.Serializable +import net.taler.wallet.balances.ScopeInfo +import net.taler.wallet.cleanExchange + +@Serializable +data class BuiltinExchange( + val exchangeBaseUrl: String, + val currencyHint: String? = null, +) + +@Serializable +data class ExchangeItem( + val exchangeBaseUrl: String, + // 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/exchanges/SelectExchangeDialogFragment.kt b/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeDialogFragment.kt new file mode 100644 index 0000000..136738b --- /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_select) + .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 61e0db5..0000000 --- a/wallet/src/main/java/net/taler/wallet/exchanges/SelectExchangeFragment.kt +++ /dev/null @@ -1,48 +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 - -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() - super.onExchangeUpdate(exchanges.filter { exchangeItem -> - exchangeItem.currency == exchangeSelection.amount.currency - }) - } - - override fun onExchangeSelected(item: ExchangeItem) { - withdrawManager.getWithdrawalDetails( - exchangeBaseUrl = item.exchangeBaseUrl, - amount = exchangeSelection.amount, - showTosImmediately = true, - uri = exchangeSelection.talerWithdrawUri, - ) - findNavController().navigateUp() - } - -} |