gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] 01/02: [wallet] add detail page for withdrawal eve


From: gnunet
Subject: [taler-taler-android] 01/02: [wallet] add detail page for withdrawal event in history
Date: Fri, 03 Apr 2020 20:27:43 +0200

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

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

commit bee652834f90fd8abd46b5adcf30adcc587984c2
Author: Torsten Grote <address@hidden>
AuthorDate: Fri Apr 3 14:04:22 2020 -0300

    [wallet] add detail page for withdrawal event in history
    
    Also make history accessible by tapping the balance
---
 .../src/main/java/net/taler/common/AndroidUtils.kt |   6 +
 .../main/java/net/taler/wallet/BalanceFragment.kt  |  18 ++-
 wallet/src/main/java/net/taler/wallet/Utils.kt     |  21 +++
 .../net/taler/wallet/history/HistoryAdapter.kt     |  94 +++++-------
 .../taler/wallet/history/HistoryEventFragment.kt   |  80 +++++++++++
 .../net/taler/wallet/history/HistoryFragment.kt    |  33 ++++-
 .../net/taler/wallet/history/HistoryManager.kt     |  14 +-
 .../net/taler/wallet/history/JsonDialogFragment.kt |   7 +
 .../wallet/withdraw/PromptWithdrawFragment.kt      |   5 +-
 .../src/main/res/layout/fragment_history_event.xml | 160 +++++++++++++++++++++
 wallet/src/main/res/layout/history_payment.xml     |  24 ++--
 wallet/src/main/res/layout/history_receive.xml     |  43 ++----
 wallet/src/main/res/layout/history_row.xml         |  11 +-
 wallet/src/main/res/layout/list_item_balance.xml   |   1 +
 wallet/src/main/res/menu/history_event.xml         |  23 +++
 wallet/src/main/res/navigation/nav_graph.xml       |  14 +-
 wallet/src/main/res/values/strings.xml             |  10 ++
 wallet/src/main/res/values/styles.xml              |   2 +-
 18 files changed, 446 insertions(+), 120 deletions(-)

diff --git a/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt 
b/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt
index 5bc5721..ad9dab9 100644
--- a/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt
+++ b/taler-kotlin-common/src/main/java/net/taler/common/AndroidUtils.kt
@@ -27,6 +27,7 @@ import android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE
 import android.text.format.DateUtils.FORMAT_NO_YEAR
 import android.text.format.DateUtils.FORMAT_SHOW_DATE
 import android.text.format.DateUtils.FORMAT_SHOW_TIME
+import android.text.format.DateUtils.FORMAT_SHOW_YEAR
 import android.text.format.DateUtils.MINUTE_IN_MILLIS
 import android.text.format.DateUtils.formatDateTime
 import android.text.format.DateUtils.getRelativeTimeSpanString
@@ -82,3 +83,8 @@ fun Long.toRelativeTime(context: Context): CharSequence {
         formatDateTime(context, this, flags)
     } else getRelativeTimeSpanString(this, now, MINUTE_IN_MILLIS, 
FORMAT_ABBREV_RELATIVE)
 }
+
+fun Long.toAbsoluteTime(context: Context): CharSequence {
+    val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_SHOW_YEAR
+    return formatDateTime(context, this, flags)
+}
diff --git a/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt 
b/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt
index d871cfb..3d5364b 100644
--- a/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/BalanceFragment.kt
@@ -31,6 +31,7 @@ import android.widget.TextView
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
@@ -41,13 +42,17 @@ import 
com.google.zxing.integration.android.IntentIntegrator.QR_CODE
 import kotlinx.android.synthetic.main.fragment_show_balance.*
 import net.taler.wallet.BalanceAdapter.BalanceViewHolder
 
-class BalanceFragment : Fragment() {
+interface BalanceClickListener {
+    fun onBalanceClick()
+}
+
+class BalanceFragment : Fragment(), BalanceClickListener {
 
     private val model: WalletViewModel by activityViewModels()
     private val withdrawManager by lazy { model.withdrawManager }
 
     private var reloadBalanceMenuItem: MenuItem? = null
-    private val balancesAdapter = BalanceAdapter()
+    private val balancesAdapter = BalanceAdapter(this)
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -141,9 +146,13 @@ class BalanceFragment : Fragment() {
         beginDelayedTransition(view as ViewGroup)
     }
 
+    override fun onBalanceClick() {
+        findNavController().navigate(R.id.walletHistory)
+    }
+
 }
 
-class BalanceAdapter : Adapter<BalanceViewHolder>() {
+class BalanceAdapter(private val listener: BalanceClickListener) : 
Adapter<BalanceViewHolder>() {
 
     private var items = emptyList<BalanceItem>()
 
@@ -169,13 +178,14 @@ class BalanceAdapter : Adapter<BalanceViewHolder>() {
         this.notifyDataSetChanged()
     }
 
-    class BalanceViewHolder(private val v: View) : ViewHolder(v) {
+    inner class BalanceViewHolder(private val v: View) : ViewHolder(v) {
         private val currencyView: TextView = 
v.findViewById(R.id.balance_currency)
         private val amountView: TextView = v.findViewById(R.id.balance_amount)
         private val balanceInboundAmount: TextView = 
v.findViewById(R.id.balanceInboundAmount)
         private val balanceInboundLabel: TextView = 
v.findViewById(R.id.balanceInboundLabel)
 
         fun bind(item: BalanceItem) {
+            v.setOnClickListener { listener.onBalanceClick() }
             currencyView.text = item.available.currency
             amountView.text = item.available.amountStr
 
diff --git a/wallet/src/main/java/net/taler/wallet/Utils.kt 
b/wallet/src/main/java/net/taler/wallet/Utils.kt
new file mode 100644
index 0000000..ae8712f
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/Utils.kt
@@ -0,0 +1,21 @@
+/*
+ * 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
+
+fun cleanExchange(exchange: String) = exchange.let {
+    if (it.startsWith("https://";)) it.substring(8) else it
+}.trimEnd('/')
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt
index 43b7bd7..881ada5 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/history/HistoryAdapter.kt
@@ -16,23 +16,19 @@
 
 package net.taler.wallet.history
 
-import android.annotation.SuppressLint
+import android.content.Context
 import android.graphics.Paint.STRIKE_THRU_TEXT_FLAG
 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.ImageView
 import android.widget.TextView
 import androidx.annotation.CallSuper
-import androidx.core.net.toUri
 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.wallet.BuildConfig
 import net.taler.wallet.R
+import net.taler.wallet.cleanExchange
 import net.taler.wallet.history.HistoryAdapter.HistoryEventViewHolder
 
 
@@ -68,23 +64,20 @@ internal class HistoryAdapter(
         this.notifyDataSetChanged()
     }
 
-    internal abstract inner class HistoryEventViewHolder(protected val v: 
View) : ViewHolder(v) {
+    internal abstract inner class HistoryEventViewHolder(private val v: View) 
: ViewHolder(v) {
 
+        protected val context: Context = v.context
         private val icon: ImageView = v.findViewById(R.id.icon)
         protected val title: TextView = v.findViewById(R.id.title)
         private val time: TextView = v.findViewById(R.id.time)
 
         @CallSuper
         open fun bind(event: HistoryEvent) {
-            if (BuildConfig.DEBUG) {  // doesn't produce recycling issues, no 
need to cover all cases
-                v.setOnClickListener { listener.onEventClicked(event) }
-            } else {
-                v.background = null
-            }
+            v.setOnClickListener { listener.onEventClicked(event) }
             icon.setImageResource(event.icon)
             if (event.title == 0) title.text = event::class.java.simpleName
             else title.setText(event.title)
-            time.text = event.timestamp.ms.toRelativeTime(v.context)
+            time.text = event.timestamp.ms.toRelativeTime(context)
         }
 
     }
@@ -96,8 +89,8 @@ internal class HistoryAdapter(
         override fun bind(event: HistoryEvent) {
             super.bind(event)
             info.text = when (event) {
-                is ExchangeAddedEvent -> event.exchangeBaseUrl
-                is ExchangeUpdatedEvent -> event.exchangeBaseUrl
+                is ExchangeAddedEvent -> cleanExchange(event.exchangeBaseUrl)
+                is ExchangeUpdatedEvent -> cleanExchange(event.exchangeBaseUrl)
                 is ReserveBalanceUpdatedEvent -> 
event.amountReserveBalance.toString()
                 is HistoryPaymentSentEvent -> event.orderShortInfo.summary
                 is HistoryOrderAcceptedEvent -> event.orderShortInfo.summary
@@ -113,8 +106,7 @@ internal class HistoryAdapter(
 
         private val summary: TextView = v.findViewById(R.id.summary)
         private val amountWithdrawn: TextView = 
v.findViewById(R.id.amountWithdrawn)
-        private val feeLabel: TextView = v.findViewById(R.id.feeLabel)
-        private val fee: TextView = v.findViewById(R.id.fee)
+        private val paintFlags = amountWithdrawn.paintFlags
 
         override fun bind(event: HistoryEvent) {
             super.bind(event)
@@ -127,52 +119,31 @@ internal class HistoryAdapter(
         }
 
         private fun bind(event: HistoryWithdrawnEvent) {
-            title.text = getHostname(event.exchangeBaseUrl)
-            summary.setText(event.title)
-
-            showAmounts(event.amountWithdrawnEffective, 
event.amountWithdrawnRaw)
+            summary.text = cleanExchange(event.exchangeBaseUrl)
+            amountWithdrawn.text =
+                context.getString(R.string.amount_positive, 
event.amountWithdrawnEffective)
+            amountWithdrawn.paintFlags = paintFlags
         }
 
         private fun bind(event: HistoryRefundedEvent) {
-            title.text = event.orderShortInfo.summary
-            summary.setText(event.title)
-
-            showAmounts(event.amountRefundedEffective, event.amountRefundedRaw)
+            summary.text = event.orderShortInfo.summary
+            amountWithdrawn.text =
+                context.getString(R.string.amount_positive, 
event.amountRefundedEffective)
+            amountWithdrawn.paintFlags = paintFlags
         }
 
         private fun bind(event: HistoryTipAcceptedEvent) {
-            title.setText(event.title)
             summary.text = null
-            showAmounts(event.tipRaw, event.tipRaw)
+            amountWithdrawn.text = context.getString(R.string.amount_positive, 
event.tipRaw)
+            amountWithdrawn.paintFlags = paintFlags
         }
 
         private fun bind(event: HistoryTipDeclinedEvent) {
-            title.setText(event.title)
             summary.text = null
-            showAmounts(event.tipAmount, event.tipAmount)
+            amountWithdrawn.text = context.getString(R.string.amount_positive, 
event.tipAmount)
             amountWithdrawn.paintFlags = amountWithdrawn.paintFlags or 
STRIKE_THRU_TEXT_FLAG
         }
 
-        private fun showAmounts(effective: Amount, raw: Amount) {
-            @SuppressLint("SetTextI18n")
-            amountWithdrawn.text = "+$raw"
-            val calculatedFee = raw - effective
-            if (calculatedFee.isZero()) {
-                fee.visibility = GONE
-                feeLabel.visibility = GONE
-            } else {
-                @SuppressLint("SetTextI18n")
-                fee.text = "-$calculatedFee"
-                fee.visibility = VISIBLE
-                feeLabel.visibility = VISIBLE
-            }
-            amountWithdrawn.paintFlags = fee.paintFlags
-        }
-
-        private fun getHostname(url: String): String {
-            return url.toUri().host!!
-        }
-
     }
 
     internal inner class HistoryPaymentViewHolder(v: View) : 
HistoryEventViewHolder(v) {
@@ -182,7 +153,6 @@ internal class HistoryAdapter(
 
         override fun bind(event: HistoryEvent) {
             super.bind(event)
-            summary.setText(event.title)
             when (event) {
                 is HistoryPaymentSentEvent -> bind(event)
                 is HistoryPaymentAbortedEvent -> bind(event)
@@ -191,23 +161,29 @@ internal class HistoryAdapter(
         }
 
         private fun bind(event: HistoryPaymentSentEvent) {
-            title.text = event.orderShortInfo.summary
-            @SuppressLint("SetTextI18n")
-            amountPaidWithFees.text = "-${event.amountPaidWithFees}"
+            summary.text = event.orderShortInfo.summary
+            amountPaidWithFees.text =
+                context.getString(R.string.amount_negative, 
event.amountPaidWithFees)
         }
 
         private fun bind(event: HistoryPaymentAbortedEvent) {
-            title.text = event.orderShortInfo.summary
-            @SuppressLint("SetTextI18n")
-            amountPaidWithFees.text = "-${event.amountLost}"
+            summary.text = event.orderShortInfo.summary
+            amountPaidWithFees.text = 
context.getString(R.string.amount_negative, event.amountLost)
         }
 
         private fun bind(event: HistoryRefreshedEvent) {
-            title.text = ""
+            val res = when (event.refreshReason) {
+                RefreshReason.MANUAL -> 
R.string.history_event_refresh_reason_manual
+                RefreshReason.PAY -> R.string.history_event_refresh_reason_pay
+                RefreshReason.REFUND -> 
R.string.history_event_refresh_reason_refund
+                RefreshReason.ABORT_PAY -> 
R.string.history_event_refresh_reason_abort_pay
+                RefreshReason.RECOUP -> 
R.string.history_event_refresh_reason_recoup
+                RefreshReason.BACKUP_RESTORED -> 
R.string.history_event_refresh_reason_backup_restored
+            }
+            summary.text = context.getString(res)
             val fee = event.amountRefreshedRaw - event.amountRefreshedEffective
-            @SuppressLint("SetTextI18n")
             if (fee.isZero()) amountPaidWithFees.text = null
-            else amountPaidWithFees.text = "-$fee"
+            else amountPaidWithFees.text = 
context.getString(R.string.amount_negative, fee)
         }
 
     }
diff --git 
a/wallet/src/main/java/net/taler/wallet/history/HistoryEventFragment.kt 
b/wallet/src/main/java/net/taler/wallet/history/HistoryEventFragment.kt
new file mode 100644
index 0000000..f0dec75
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/history/HistoryEventFragment.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.history
+
+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 androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import kotlinx.android.synthetic.main.fragment_history_event.*
+import net.taler.common.toAbsoluteTime
+import net.taler.wallet.R
+import net.taler.wallet.WalletViewModel
+import net.taler.wallet.cleanExchange
+
+class HistoryEventFragment : Fragment() {
+
+    private val model: WalletViewModel by activityViewModels()
+    private val historyManager by lazy { model.historyManager }
+    private val event by lazy { requireNotNull(historyManager.selectedEvent) }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        if (model.devMode.value == true) setHasOptionsMenu(true)
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_history_event, container, 
false)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        val event = event as HistoryWithdrawnEvent
+
+        timeView.text = event.timestamp.ms.toAbsoluteTime(requireContext())
+        effectiveAmountLabel.text = getString(R.string.withdraw_total)
+        effectiveAmountView.text = event.amountWithdrawnEffective.toString()
+        chosenAmountLabel.text = getString(R.string.amount_chosen)
+        chosenAmountView.text =
+            getString(R.string.amount_positive, 
event.amountWithdrawnRaw.toString())
+        val fee = event.amountWithdrawnRaw - event.amountWithdrawnEffective
+        feeView.text = getString(R.string.amount_negative, fee.toString())
+        exchangeView.text = cleanExchange(event.exchangeBaseUrl)
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
+        inflater.inflate(R.menu.history_event, menu)
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return when (item.itemId) {
+            R.id.show_json -> {
+                
JsonDialogFragment.new(event.json.toString(2)).show(parentFragmentManager, null)
+                true
+            }
+            else -> super.onOptionsItemSelected(item)
+        }
+    }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt 
b/wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt
index 2586ef8..b0f6728 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/history/HistoryFragment.kt
@@ -28,10 +28,14 @@ import android.view.ViewGroup
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
 import kotlinx.android.synthetic.main.fragment_show_history.*
+import net.taler.common.exhaustive
+import net.taler.common.fadeIn
+import net.taler.common.fadeOut
 import net.taler.wallet.R
 import net.taler.wallet.WalletViewModel
 
@@ -73,8 +77,7 @@ class HistoryFragment : Fragment(), OnEventClickListener {
             historyProgressBar.visibility = if (show) VISIBLE else INVISIBLE
         })
         historyManager.history.observe(viewLifecycleOwner, Observer { history 
->
-            historyEmptyState.visibility = if (history.isEmpty()) VISIBLE else 
INVISIBLE
-            historyAdapter.update(history)
+            onHistoryResult(history)
         })
 
         // kicks off initial load, needs to be adapted if showAll state is 
ever saved
@@ -106,9 +109,29 @@ class HistoryFragment : Fragment(), OnEventClickListener {
     }
 
     override fun onEventClicked(event: HistoryEvent) {
-        if (model.devMode.value != true) return
-        JsonDialogFragment.new(event.json.toString(4))
-            .show(parentFragmentManager, null)
+        when (event) {
+            is HistoryWithdrawnEvent -> {
+                historyManager.selectedEvent = event
+                
findNavController().navigate(R.id.action_walletHistory_to_historyEventFragment)
+            }
+            else -> {
+                if (model.devMode.value != true) return
+                JsonDialogFragment.new(event.json.toString(2))
+                    .show(parentFragmentManager, null)
+            }
+        }.exhaustive
+    }
+
+    private fun onHistoryResult(result: HistoryResult) = when (result) {
+        HistoryResult.Error -> {
+            historyList.fadeOut()
+            historyEmptyState.text = getString(R.string.history_error)
+            historyEmptyState.fadeIn()
+        }
+        is HistoryResult.Success -> {
+            historyEmptyState.visibility = if (result.history.isEmpty()) 
VISIBLE else INVISIBLE
+            historyAdapter.update(result.history)
+        }
     }
 
 }
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt 
b/wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt
index c350daa..7ce4f5b 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/history/HistoryManager.kt
@@ -29,6 +29,11 @@ import kotlinx.coroutines.flow.onCompletion
 import kotlinx.coroutines.flow.onStart
 import net.taler.wallet.backend.WalletBackendApi
 
+sealed class HistoryResult {
+    object Error : HistoryResult()
+    class Success(val history: History) : HistoryResult()
+}
+
 @Suppress("EXPERIMENTAL_API_USAGE")
 class HistoryManager(
     private val walletBackendApi: WalletBackendApi,
@@ -40,7 +45,9 @@ class HistoryManager(
 
     val showAll = MutableLiveData<Boolean>()
 
-    val history: LiveData<History> = showAll.switchMap { showAll ->
+    var selectedEvent: HistoryEvent? = null
+
+    val history: LiveData<HistoryResult> = showAll.switchMap { showAll ->
         loadHistory(showAll)
             .onStart { mProgress.postValue(true) }
             .onCompletion { mProgress.postValue(false) }
@@ -50,7 +57,7 @@ class HistoryManager(
     private fun loadHistory(showAll: Boolean) = callbackFlow {
         walletBackendApi.sendRequest("getHistory", null) { isError, result ->
             if (isError) {
-                // TODO show error message in [WalletHistory] fragment
+                offer(HistoryResult.Error)
                 close()
                 return@sendRequest
             }
@@ -62,7 +69,8 @@ class HistoryManager(
                 history.add(event)
             }
             history.reverse()  // show latest first
-            offer(if (showAll) history else history.filter { it.showToUser } 
as History)
+            val filtered = if (showAll) history else history.filter { 
it.showToUser } as History
+            offer(HistoryResult.Success(filtered))
             close()
         }
         awaitClose()
diff --git 
a/wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt 
b/wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt
index f51dba9..5421db3 100644
--- a/wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/history/JsonDialogFragment.kt
@@ -20,6 +20,8 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import androidx.fragment.app.DialogFragment
 import kotlinx.android.synthetic.main.fragment_json.*
 import net.taler.wallet.R
@@ -47,4 +49,9 @@ class JsonDialogFragment : DialogFragment() {
         jsonView.text = json
     }
 
+    override fun onStart() {
+        super.onStart()
+        dialog?.window?.setLayout(MATCH_PARENT, WRAP_CONTENT)
+    }
+
 }
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 ea04e24..5d0fe63 100644
--- a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -30,6 +30,7 @@ import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.wallet.R
 import net.taler.wallet.WalletViewModel
+import net.taler.wallet.cleanExchange
 import net.taler.wallet.withdraw.WithdrawStatus.Loading
 import net.taler.wallet.withdraw.WithdrawStatus.TermsOfServiceReviewRequired
 import net.taler.wallet.withdraw.WithdrawStatus.Withdrawing
@@ -115,9 +116,7 @@ class PromptWithdrawFragment : Fragment() {
         feeView.fadeIn()
 
         exchangeIntroView.fadeIn()
-        withdrawExchangeUrl.text = exchange.let {
-            if (it.startsWith("https://";)) it.substring(8) else it
-        }.trimEnd('/')
+        withdrawExchangeUrl.text = cleanExchange(exchange)
         withdrawExchangeUrl.fadeIn()
 
         withdrawCard.fadeIn()
diff --git a/wallet/src/main/res/layout/fragment_history_event.xml 
b/wallet/src/main/res/layout/fragment_history_event.xml
new file mode 100644
index 0000000..4224093
--- /dev/null
+++ b/wallet/src/main/res/layout/fragment_history_event.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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/>
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android";
+    xmlns:app="http://schemas.android.com/apk/res-auto";
+    xmlns:tools="http://schemas.android.com/tools";
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".history.HistoryEventFragment">
+
+    <TextView
+        android:id="@+id/timeView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_margin="16dp"
+        android:gravity="center"
+        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
+        app:layout_constraintBottom_toTopOf="@+id/effectiveAmountLabel"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintVertical_chainStyle="packed"
+        tools:text="23 March 2020 23:42pm" />
+
+    <TextView
+        android:id="@+id/effectiveAmountLabel"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:gravity="center"
+        app:layout_constraintBottom_toTopOf="@+id/effectiveAmountView"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/timeView"
+        tools:text="@string/withdraw_total" />
+
+    <TextView
+        android:id="@+id/effectiveAmountView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="16dp"
+        android:gravity="center"
+        android:textColor="@color/green"
+        android:textSize="24sp"
+        app:layout_constraintBottom_toTopOf="@+id/chosenAmountLabel"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/effectiveAmountLabel"
+        tools:text="23.42 TESTKUDOS" />
+
+    <TextView
+        android:id="@+id/chosenAmountLabel"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:gravity="center"
+        app:layout_constraintBottom_toTopOf="@+id/chosenAmountView"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/effectiveAmountView"
+        tools:text="@string/amount_chosen" />
+
+    <TextView
+        android:id="@+id/chosenAmountView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="16dp"
+        android:gravity="center"
+        android:textSize="24sp"
+        app:layout_constraintBottom_toTopOf="@+id/feeLabel"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/chosenAmountLabel"
+        tools:text="24 TESTKUDOS" />
+
+    <TextView
+        android:id="@+id/feeLabel"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:gravity="center"
+        android:text="@string/withdraw_fees"
+        app:layout_constraintBottom_toTopOf="@+id/feeView"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/chosenAmountView" />
+
+    <TextView
+        android:id="@+id/feeView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="16dp"
+        android:gravity="center"
+        android:textColor="@color/red"
+        android:textSize="24sp"
+        app:layout_constraintBottom_toTopOf="@+id/exchangeLabel"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/feeLabel"
+        tools:text="-0.38 TESTKUDOS" />
+
+    <TextView
+        android:id="@+id/exchangeLabel"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:gravity="center"
+        android:text="@string/withdraw_exchange"
+        app:layout_constraintBottom_toTopOf="@+id/exchangeView"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/feeView" />
+
+    <TextView
+        android:id="@+id/exchangeView"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="16dp"
+        android:gravity="center"
+        android:textSize="24sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.5"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/exchangeLabel"
+        tools:text="exchange.demo.taler.net" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/layout/history_payment.xml 
b/wallet/src/main/res/layout/history_payment.xml
index 3839038..33cb676 100644
--- a/wallet/src/main/res/layout/history_payment.xml
+++ b/wallet/src/main/res/layout/history_payment.xml
@@ -19,11 +19,11 @@
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginStart="16dp"
-    android:layout_marginTop="8dp"
-    android:layout_marginEnd="16dp"
-    android:layout_marginBottom="8dp"
-    android:background="?attr/selectableItemBackground">
+    android:background="?attr/selectableItemBackground"
+    android:paddingStart="16dp"
+    android:paddingTop="8dp"
+    android:paddingEnd="16dp"
+    android:paddingBottom="8dp">
 
     <ImageView
         android:id="@+id/icon"
@@ -32,36 +32,36 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
-        app:srcCompat="@drawable/history_withdrawn"
         app:tint="?android:colorControlNormal"
-        tools:ignore="ContentDescription" />
+        tools:ignore="ContentDescription"
+        tools:src="@drawable/ic_cash_usd_outline" />
 
     <TextView
         android:id="@+id/title"
         style="@style/HistoryTitle"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginStart="16dp"
         android:layout_marginEnd="8dp"
         app:layout_constraintEnd_toStartOf="@+id/amountPaidWithFees"
         app:layout_constraintStart_toEndOf="@+id/icon"
         app:layout_constraintTop_toTopOf="parent"
-        tools:text="Lots of books with very long titles" />
+        tools:text="@string/history_event_payment_sent" />
 
     <TextView
         android:id="@+id/summary"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginStart="16dp"
         android:layout_marginTop="8dp"
         app:layout_constrainedWidth="true"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/amountPaidWithFees"
+        app:layout_constraintEnd_toStartOf="@+id/time"
         app:layout_constraintHorizontal_bias="0.0"
         app:layout_constraintStart_toEndOf="@+id/icon"
         app:layout_constraintTop_toBottomOf="@+id/title"
         app:layout_constraintVertical_bias="0.0"
-        tools:text="@string/history_event_payment_sent" />
+        tools:text="Lots of books with very long titles" />
 
     <TextView
         android:id="@+id/amountPaidWithFees"
diff --git a/wallet/src/main/res/layout/history_receive.xml 
b/wallet/src/main/res/layout/history_receive.xml
index def97a2..5f386a2 100644
--- a/wallet/src/main/res/layout/history_receive.xml
+++ b/wallet/src/main/res/layout/history_receive.xml
@@ -19,11 +19,11 @@
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginStart="16dp"
-    android:layout_marginTop="8dp"
-    android:layout_marginEnd="16dp"
-    android:layout_marginBottom="8dp"
-    android:background="?attr/selectableItemBackground">
+    android:background="?attr/selectableItemBackground"
+    android:paddingStart="16dp"
+    android:paddingTop="8dp"
+    android:paddingEnd="16dp"
+    android:paddingBottom="8dp">
 
     <ImageView
         android:id="@+id/icon"
@@ -41,7 +41,7 @@
         style="@style/HistoryTitle"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginStart="16dp"
         android:layout_marginEnd="8dp"
         android:text="@string/history_event_withdrawn"
         app:layout_constraintEnd_toStartOf="@+id/amountWithdrawn"
@@ -52,34 +52,18 @@
         android:id="@+id/summary"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginStart="16dp"
         android:layout_marginTop="8dp"
         android:layout_marginEnd="8dp"
         android:layout_marginBottom="8dp"
         app:layout_constrainedWidth="true"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/feeLabel"
+        app:layout_constraintEnd_toStartOf="@+id/time"
+        app:layout_constraintHorizontal_bias="0.5"
         app:layout_constraintStart_toEndOf="@+id/icon"
         app:layout_constraintTop_toBottomOf="@+id/title"
-        tools:text="http://taler.quite-long-exchange.url"; />
-
-    <TextView
-        android:id="@+id/feeLabel"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="2dp"
-        android:text="@string/history_fee_label"
-        app:layout_constraintEnd_toStartOf="@+id/fee"
-        app:layout_constraintTop_toTopOf="@+id/fee" />
-
-    <TextView
-        android:id="@+id/fee"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textColor="@color/red"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/amountWithdrawn"
-        tools:text="0.2 TESTKUDOS" />
+        app:layout_constraintVertical_bias="0.0"
+        tools:text="exchange.taler.quite-long-domain-name.org" />
 
     <TextView
         android:id="@+id/amountWithdrawn"
@@ -96,10 +80,13 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp"
         android:textSize="14sp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/fee"
+        app:layout_constraintStart_toEndOf="@+id/summary"
+        app:layout_constraintTop_toBottomOf="@+id/amountWithdrawn"
+        app:layout_constraintVertical_bias="1.0"
         tools:text="23 min. ago" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/layout/history_row.xml 
b/wallet/src/main/res/layout/history_row.xml
index 2982008..5eac44b 100644
--- a/wallet/src/main/res/layout/history_row.xml
+++ b/wallet/src/main/res/layout/history_row.xml
@@ -19,8 +19,11 @@
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_margin="15dp"
-    android:background="?attr/selectableItemBackground">
+    android:background="?attr/selectableItemBackground"
+    android:paddingStart="16dp"
+    android:paddingTop="8dp"
+    android:paddingEnd="16dp"
+    android:paddingBottom="8dp">
 
     <ImageView
         android:id="@+id/icon"
@@ -38,7 +41,7 @@
         style="@style/HistoryTitle"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginStart="16dp"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toEndOf="@+id/icon"
         app:layout_constraintTop_toTopOf="parent"
@@ -49,7 +52,7 @@
         android:id="@+id/info"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginStart="16dp"
         android:layout_marginTop="8dp"
         android:layout_marginEnd="8dp"
         app:layout_constraintBottom_toBottomOf="parent"
diff --git a/wallet/src/main/res/layout/list_item_balance.xml 
b/wallet/src/main/res/layout/list_item_balance.xml
index dc24232..a9e15df 100644
--- a/wallet/src/main/res/layout/list_item_balance.xml
+++ b/wallet/src/main/res/layout/list_item_balance.xml
@@ -19,6 +19,7 @@
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:background="?attr/selectableItemBackground"
     android:padding="16dp">
 
     <TextView
diff --git a/wallet/src/main/res/menu/history_event.xml 
b/wallet/src/main/res/menu/history_event.xml
new file mode 100644
index 0000000..45a1e0e
--- /dev/null
+++ b/wallet/src/main/res/menu/history_event.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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/>
+  -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android";
+    xmlns:app="http://schemas.android.com/apk/res-auto";>
+    <item
+        android:id="@+id/show_json"
+        android:title="@string/history_detail_json"
+        app:showAsAction="never" />
+</menu>
diff --git a/wallet/src/main/res/navigation/nav_graph.xml 
b/wallet/src/main/res/navigation/nav_graph.xml
index 9875b8a..1ab9666 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -57,11 +57,23 @@
         android:name="net.taler.wallet.Settings"
         android:label="Settings"
         tools:layout="@layout/fragment_settings" />
+
     <fragment
         android:id="@+id/walletHistory"
         android:name="net.taler.wallet.history.HistoryFragment"
         android:label="@string/history_title"
-        tools:layout="@layout/fragment_show_history" />
+        tools:layout="@layout/fragment_show_history">
+        <action
+            android:id="@+id/action_walletHistory_to_historyEventFragment"
+            app:destination="@id/historyEventFragment" />
+    </fragment>
+
+    <fragment
+        android:id="@+id/historyEventFragment"
+        android:name="net.taler.wallet.history.HistoryEventFragment"
+        android:label="@string/history_detail_title"
+        tools:layout="@layout/fragment_history_event" />
+
     <fragment
         android:id="@+id/alreadyPaid"
         android:name="net.taler.wallet.payment.AlreadyPaidFragment"
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index bcd173f..1f028c2 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -41,6 +41,7 @@
     <string name="balances_title">Balances</string>
     <string name="amount_positive">+%s</string>
     <string name="amount_negative">-%s</string>
+    <string name="amount_chosen">Chosen Amount</string>
     <string name="balances_inbound_label">inbound</string>
     <string name="balances_empty_state">There is no digital cash in your 
wallet.\n\nYou can get test money from the demo 
bank:\n\nhttps://bank.demo.taler.net</string>
 
@@ -49,6 +50,9 @@
     <string name="history_show_all">Show All</string>
     <string name="history_reload">Reload History</string>
     <string name="history_empty">The wallet history is empty</string>
+    <string name="history_error">Could not load history</string>
+    <string name="history_detail_title">Transaction</string>
+    <string name="history_detail_json">Show JSON</string>
 
     <!-- HistoryEvents -->
     <string name="history_event_exchange_added">Exchange Added</string>
@@ -64,6 +68,12 @@
     <string name="history_event_order_redirected">Purchase Redirected</string>
     <string name="history_event_refund">Refund</string>
     <string name="history_event_refreshed">Obtained change</string>
+    <string name="history_event_refresh_reason_manual">because of manual 
request</string>
+    <string name="history_event_refresh_reason_pay">for payment</string>
+    <string name="history_event_refresh_reason_refund">for refund</string>
+    <string name="history_event_refresh_reason_abort_pay">to abort 
payment</string>
+    <string name="history_event_refresh_reason_recoup">to recoup funds</string>
+    <string name="history_event_refresh_reason_backup_restored">because of 
restoring from backup</string>
     <string name="history_event_unknown">Unknown Event</string>
 
     <string name="payment_fee">+%s payment fee</string>
diff --git a/wallet/src/main/res/values/styles.xml 
b/wallet/src/main/res/values/styles.xml
index 83f3e3a..c3e18a6 100644
--- a/wallet/src/main/res/values/styles.xml
+++ b/wallet/src/main/res/values/styles.xml
@@ -34,7 +34,7 @@
     <style name="AppTheme.Toolbar" 
parent="Widget.MaterialComponents.Toolbar.Primary" />
 
     <style name="HistoryTitle">
-        <item name="android:textSize">17sp</item>
+        <item name="android:textSize">16sp</item>
         <item name="android:textColor">?android:textColorPrimary</item>
     </style>
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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