gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] 02/13: [wallet] render transaction list from new t


From: gnunet
Subject: [taler-taler-android] 02/13: [wallet] render transaction list from new transactions API
Date: Mon, 18 May 2020 14:47:19 +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 bedd7b05eb0b5ee69cd5f35b283e713cf8af29dc
Author: Torsten Grote <address@hidden>
AuthorDate: Thu May 14 10:36:29 2020 -0300

    [wallet] render transaction list from new transactions API
---
 .../main/java/net/taler/common/ContractTerms.kt    |   5 +
 wallet/build.gradle                                |   4 +-
 .../java/net/taler/wallet/history/HistoryEvent.kt  |   6 +-
 .../wallet/transactions/TransactionAdapter.kt      |  83 +++-------
 .../transactions/TransactionDetailFragment.kt      |  71 ++++----
 .../wallet/transactions/TransactionManager.kt      |  23 ++-
 .../net/taler/wallet/transactions/Transactions.kt  | 178 +++++++++++++++++++++
 .../wallet/transactions/TransactionsFragment.kt    |   7 +-
 ...t_paid.xml => fragment_transaction_payment.xml} |   0
 ...raw.xml => fragment_transaction_withdrawal.xml} |   0
 .../src/main/res/layout/list_item_transaction.xml  |  89 +++++++++++
 wallet/src/main/res/menu/transactions_detail.xml   |   4 -
 wallet/src/main/res/navigation/nav_graph.xml       |   2 +-
 wallet/src/main/res/values/strings.xml             |   6 +-
 14 files changed, 351 insertions(+), 127 deletions(-)

diff --git 
a/taler-kotlin-common/src/main/java/net/taler/common/ContractTerms.kt 
b/taler-kotlin-common/src/main/java/net/taler/common/ContractTerms.kt
index cd417ef..63c3eb4 100644
--- a/taler-kotlin-common/src/main/java/net/taler/common/ContractTerms.kt
+++ b/taler-kotlin-common/src/main/java/net/taler/common/ContractTerms.kt
@@ -67,6 +67,11 @@ data class ContractProduct(
     }
 }
 
+data class ContractMerchant(
+    // TODO this shouldn't be nullable
+    val name: String?
+)
+
 @JsonInclude(NON_EMPTY)
 class Timestamp(
     @JsonProperty("t_ms")
diff --git a/wallet/build.gradle b/wallet/build.gradle
index f976b24..91eb324 100644
--- a/wallet/build.gradle
+++ b/wallet/build.gradle
@@ -23,7 +23,7 @@ plugins {
     id "de.undercouch.download"
 }
 
-def walletCoreVersion = "v0.7.1-dev.3"
+def walletCoreVersion = "v0.7.1-dev.4"
 
 android {
     compileSdkVersion 29
@@ -35,7 +35,7 @@ android {
         minSdkVersion 24
         targetSdkVersion 29
         versionCode 6
-        versionName "0.7.1.dev.3"
+        versionName "0.7.1.dev.4"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         buildConfigField "String", "WALLET_CORE_VERSION", 
"\"$walletCoreVersion\""
     }
diff --git a/wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt 
b/wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt
index acca679..1618988 100644
--- a/wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt
+++ b/wallet/src/main/java/net/taler/wallet/history/HistoryEvent.kt
@@ -233,7 +233,7 @@ class WithdrawHistoryEvent(
      */
     val amountWithdrawnEffective: Amount
 ) : HistoryEvent(timestamp, eventId) {
-    override val detailPageLayout = R.layout.fragment_event_withdraw
+    override val detailPageLayout = R.layout.fragment_transaction_withdrawal
     override val title = cleanExchange(exchangeBaseUrl)
     override val icon = R.drawable.transaction_withdrawal
     override val showToUser = true
@@ -298,7 +298,7 @@ class PaymentHistoryEvent(
      */
     val sessionId: String?
 ) : HistoryEvent(timestamp, eventId) {
-    override val detailPageLayout = R.layout.fragment_event_paid
+    override val detailPageLayout = R.layout.fragment_transaction_payment
     override val title = orderShortInfo.summary
     override val icon = R.drawable.ic_cash_usd_outline
     override val showToUser = true
@@ -464,7 +464,7 @@ class RefundHistoryEvent(
 ) : HistoryEvent(timestamp, eventId) {
     override val icon = R.drawable.transaction_refund
     override val title = orderShortInfo.summary
-    override val detailPageLayout = R.layout.fragment_event_paid
+    override val detailPageLayout = R.layout.fragment_transaction_payment
     override val showToUser = true
     override val displayAmount = DisplayAmount(
         amountRefundedEffective,
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
index 5aca896..044a054 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -35,24 +35,13 @@ import net.taler.common.exhaustive
 import net.taler.common.toRelativeTime
 import net.taler.wallet.R
 import net.taler.wallet.history.AmountType
-import net.taler.wallet.history.DisplayAmount
-import net.taler.wallet.history.History
-import net.taler.wallet.history.HistoryEvent
-import net.taler.wallet.history.OrderAcceptedHistoryEvent
-import net.taler.wallet.history.OrderRefusedHistoryEvent
-import net.taler.wallet.history.RefreshHistoryEvent
-import net.taler.wallet.history.RefreshReason
-import net.taler.wallet.history.ReserveBalanceUpdatedHistoryEvent
-import net.taler.wallet.history.TipAcceptedHistoryEvent
-import net.taler.wallet.history.TipDeclinedHistoryEvent
 import net.taler.wallet.transactions.TransactionAdapter.TransactionViewHolder
 
-
 internal class TransactionAdapter(
-    private val listener: OnTransactionClickListener,
-    private var transactions: History = History()
+    private val listener: OnTransactionClickListener
 ) : Adapter<TransactionViewHolder>() {
 
+    private var transactions: List<Transaction> = ArrayList()
     lateinit var tracker: SelectionTracker<String>
     val keyProvider = TransactionKeyProvider()
 
@@ -62,7 +51,7 @@ internal class TransactionAdapter(
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
TransactionViewHolder {
         val view = LayoutInflater.from(parent.context)
-            .inflate(R.layout.list_item_history, parent, false)
+            .inflate(R.layout.list_item_transaction, parent, false)
         return TransactionViewHolder(view)
     }
 
@@ -70,16 +59,16 @@ internal class TransactionAdapter(
 
     override fun onBindViewHolder(holder: TransactionViewHolder, position: 
Int) {
         val transaction = transactions[position]
-        holder.bind(transaction, tracker.isSelected(transaction.eventId))
+        holder.bind(transaction, tracker.isSelected(transaction.transactionId))
     }
 
-    fun update(updatedTransactions: History) {
+    fun update(updatedTransactions: List<Transaction>) {
         this.transactions = updatedTransactions
         this.notifyDataSetChanged()
     }
 
     fun selectAll() = transactions.forEach {
-        tracker.select(it.eventId)
+        tracker.select(it.transactionId)
     }
 
     internal open inner class TransactionViewHolder(private val v: View) : 
ViewHolder(v) {
@@ -90,11 +79,14 @@ internal class TransactionAdapter(
         protected val title: TextView = v.findViewById(R.id.title)
         private val time: TextView = v.findViewById(R.id.time)
         private val amount: TextView = v.findViewById(R.id.amount)
+        private val pendingView: TextView = v.findViewById(R.id.pendingView)
 
         private val selectableForeground = v.foreground
         private val amountColor = amount.currentTextColor
+        private val red = context.getColor(R.color.red)
+        private val green = context.getColor(R.color.green)
 
-        open fun bind(transaction: HistoryEvent, selected: Boolean) {
+        open fun bind(transaction: Transaction, selected: Boolean) {
             if (transaction.detailPageLayout != 0) {
                 v.foreground = selectableForeground
                 v.setOnClickListener { 
listener.onTransactionClicked(transaction) }
@@ -105,66 +97,43 @@ internal class TransactionAdapter(
             v.isActivated = selected
             icon.setImageResource(transaction.icon)
 
-            title.text = if (transaction.title == null) {
-                when (transaction) {
-                    is RefreshHistoryEvent -> getRefreshTitle(transaction)
-                    is OrderAcceptedHistoryEvent -> 
context.getString(R.string.transaction_order_accepted)
-                    is OrderRefusedHistoryEvent -> 
context.getString(R.string.transaction_order_refused)
-                    is TipAcceptedHistoryEvent -> 
context.getString(R.string.transaction_tip_accepted)
-                    is TipDeclinedHistoryEvent -> 
context.getString(R.string.transaction_tip_declined)
-                    is ReserveBalanceUpdatedHistoryEvent -> 
context.getString(R.string.transaction_reserve_balance_updated)
-                    else -> transaction::class.java.simpleName
-                }
-            } else transaction.title
-
+            title.text = transaction.getTitle(context)
             time.text = transaction.timestamp.ms.toRelativeTime(context)
-            bindAmount(transaction.displayAmount)
+            bindAmount(transaction)
+            pendingView.visibility = if (transaction.pending) VISIBLE else GONE
         }
 
-        private fun bindAmount(displayAmount: DisplayAmount?) {
-            if (displayAmount == null) {
+        private fun bindAmount(transaction: Transaction) {
+            val amountEffective = transaction.amountEffective
+            if (amountEffective == null) {
                 amount.visibility = GONE
             } else {
                 amount.visibility = VISIBLE
-                when (displayAmount.type) {
+                when (transaction.amountType) {
                     AmountType.Positive -> {
-                        amount.text = context.getString(
-                            R.string.amount_positive, 
displayAmount.amount.amountStr
-                        )
-                        amount.setTextColor(context.getColor(R.color.green))
+                        amount.text =
+                            context.getString(R.string.amount_positive, 
amountEffective.amountStr)
+                        amount.setTextColor(if (transaction.pending) 
amountColor else green)
                     }
                     AmountType.Negative -> {
-                        amount.text = context.getString(
-                            R.string.amount_negative, 
displayAmount.amount.amountStr
-                        )
-                        amount.setTextColor(context.getColor(R.color.red))
+                        amount.text =
+                            context.getString(R.string.amount_negative, 
amountEffective.amountStr)
+                        amount.setTextColor(if (transaction.pending) 
amountColor else red)
                     }
                     AmountType.Neutral -> {
-                        amount.text = displayAmount.amount.amountStr
+                        amount.text = amountEffective.amountStr
                         amount.setTextColor(amountColor)
                     }
                 }.exhaustive
             }
         }
 
-        private fun getRefreshTitle(transaction: RefreshHistoryEvent): String {
-            val res = when (transaction.refreshReason) {
-                RefreshReason.MANUAL -> 
R.string.transaction_refresh_reason_manual
-                RefreshReason.PAY -> R.string.transaction_refresh_reason_pay
-                RefreshReason.REFUND -> 
R.string.transaction_refresh_reason_refund
-                RefreshReason.ABORT_PAY -> 
R.string.transaction_refresh_reason_abort_pay
-                RefreshReason.RECOUP -> 
R.string.transaction_refresh_reason_recoup
-                RefreshReason.BACKUP_RESTORED -> 
R.string.transaction_refresh_reason_backup_restored
-            }
-            return context.getString(R.string.transaction_refresh) + " " + 
context.getString(res)
-        }
-
     }
 
     internal inner class TransactionKeyProvider : 
ItemKeyProvider<String>(SCOPE_MAPPED) {
-        override fun getKey(position: Int) = transactions[position].eventId
+        override fun getKey(position: Int) = 
transactions[position].transactionId
         override fun getPosition(key: String): Int {
-            return transactions.indexOfFirst { it.eventId == key }
+            return transactions.indexOfFirst { it.transactionId == key }
         }
     }
 
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
index bb70b5c..c9e51e4 100644
--- 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
+++ 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
@@ -28,26 +28,21 @@ import android.widget.Toast.LENGTH_LONG
 import androidx.core.content.ContextCompat.getColor
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
-import kotlinx.android.synthetic.main.fragment_event_paid.*
-import kotlinx.android.synthetic.main.fragment_event_withdraw.*
-import kotlinx.android.synthetic.main.fragment_event_withdraw.feeView
-import kotlinx.android.synthetic.main.fragment_event_withdraw.timeView
+import kotlinx.android.synthetic.main.fragment_transaction_payment.*
+import kotlinx.android.synthetic.main.fragment_transaction_withdrawal.*
+import kotlinx.android.synthetic.main.fragment_transaction_withdrawal.feeView
+import kotlinx.android.synthetic.main.fragment_transaction_withdrawal.timeView
 import net.taler.common.Amount
 import net.taler.common.toAbsoluteTime
 import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
 import net.taler.wallet.cleanExchange
-import net.taler.wallet.history.JsonDialogFragment
-import net.taler.wallet.history.OrderShortInfo
-import net.taler.wallet.history.PaymentHistoryEvent
-import net.taler.wallet.history.RefundHistoryEvent
-import net.taler.wallet.history.WithdrawHistoryEvent
 
 class TransactionDetailFragment : Fragment() {
 
     private val model: MainViewModel by activityViewModels()
     private val transactionManager by lazy { model.transactionManager }
-    private val event by lazy { 
requireNotNull(transactionManager.selectedEvent) }
+    private val transaction by lazy { 
requireNotNull(transactionManager.selectedTransaction) }
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -58,21 +53,22 @@ class TransactionDetailFragment : Fragment() {
         inflater: LayoutInflater, container: ViewGroup?,
         savedInstanceState: Bundle?
     ): View? {
-        return inflater.inflate(event.detailPageLayout, container, false)
+        return inflater.inflate(transaction.detailPageLayout, container, false)
     }
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         super.onActivityCreated(savedInstanceState)
-        requireActivity().title =
-            if (event.title != null) event.title else 
getString(R.string.transactions_detail_title)
+        requireActivity().apply {
+            title = transaction.getTitle(this)
+        }
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        timeView.text = event.timestamp.ms.toAbsoluteTime(requireContext())
-        when (val e = event) {
-            is WithdrawHistoryEvent -> bind(e)
-            is PaymentHistoryEvent -> bind(e)
-            is RefundHistoryEvent -> bind(e)
+        timeView.text = 
transaction.timestamp.ms.toAbsoluteTime(requireContext())
+        when (val e = transaction) {
+            is TransactionWithdrawal -> bind(e)
+            is TransactionPayment -> bind(e)
+            is TransactionRefund -> bind(e)
             else -> Toast.makeText(
                 requireContext(),
                 "event ${e.javaClass} not implement",
@@ -87,46 +83,41 @@ class TransactionDetailFragment : Fragment() {
 
     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)
         }
     }
 
-    private fun bind(event: WithdrawHistoryEvent) {
+    private fun bind(t: TransactionWithdrawal) {
         effectiveAmountLabel.text = getString(R.string.withdraw_total)
-        effectiveAmountView.text = event.amountWithdrawnEffective.toString()
+        effectiveAmountView.text = t.amountEffective.toString()
         chosenAmountLabel.text = getString(R.string.amount_chosen)
         chosenAmountView.text =
-            getString(R.string.amount_positive, 
event.amountWithdrawnRaw.toString())
-        val fee = event.amountWithdrawnRaw - event.amountWithdrawnEffective
+            getString(R.string.amount_positive, t.amountRaw.toString())
+        val fee = t.amountRaw - (t.amountEffective ?: t.amountRaw)
         feeView.text = getString(R.string.amount_negative, fee.toString())
-        exchangeView.text = cleanExchange(event.exchangeBaseUrl)
+        exchangeView.text = cleanExchange(t.exchangeBaseUrl)
     }
 
-    private fun bind(event: PaymentHistoryEvent) {
-        amountPaidWithFeesView.text = event.amountPaidWithFees.toString()
-        val fee = event.amountPaidWithFees - event.orderShortInfo.amount
-        bindOrderAndFee(event.orderShortInfo, fee)
+    private fun bind(t: TransactionPayment) {
+        amountPaidWithFeesView.text = t.amountEffective.toString()
+        val fee = (t.amountEffective ?: t.amountRaw) - t.amountRaw
+        bindOrderAndFee(t.info, t.amountRaw, fee)
     }
 
-    private fun bind(event: RefundHistoryEvent) {
+    private fun bind(t: TransactionRefund) {
         amountPaidWithFeesLabel.text = getString(R.string.transaction_refund)
         amountPaidWithFeesView.setTextColor(getColor(requireContext(), 
R.color.green))
         amountPaidWithFeesView.text =
-            getString(R.string.amount_positive, 
event.amountRefundedEffective.toString())
-        val fee = event.orderShortInfo.amount - event.amountRefundedEffective
-        bindOrderAndFee(event.orderShortInfo, fee)
+            getString(R.string.amount_positive, t.amountEffective.toString())
+        val fee = t.amountRaw - (t.amountEffective ?: t.amountRaw)
+        bindOrderAndFee(t.info, t.amountRaw, fee)
     }
 
-    private fun bindOrderAndFee(orderShortInfo: OrderShortInfo, fee: Amount) {
-        orderAmountView.text = orderShortInfo.amount.toString()
+    private fun bindOrderAndFee(info: TransactionInfo, raw: Amount, fee: 
Amount) {
+        orderAmountView.text = raw.toString()
         feeView.text = getString(R.string.amount_negative, fee.toString())
-        orderSummaryView.text = orderShortInfo.summary
-        orderIdView.text =
-            getString(R.string.transaction_order_id, orderShortInfo.orderId)
+        orderSummaryView.text = info.summary
+        orderIdView.text = getString(R.string.transaction_order_id, 
info.orderId)
     }
 
 }
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
index 850a3bb..81d53b9 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
@@ -16,6 +16,7 @@
 
 package net.taler.wallet.transactions
 
+import android.util.Log
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import com.fasterxml.jackson.databind.ObjectMapper
@@ -24,13 +25,12 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import net.taler.wallet.backend.WalletBackendApi
-import net.taler.wallet.history.History
-import net.taler.wallet.history.HistoryEvent
 import org.json.JSONObject
+import java.util.*
 
 sealed class TransactionsResult {
     object Error : TransactionsResult()
-    class Success(val transactions: History) : TransactionsResult()
+    class Success(val transactions: List<Transaction>) : TransactionsResult()
 }
 
 class TransactionManager(
@@ -43,14 +43,15 @@ class TransactionManager(
     val progress: LiveData<Boolean> = mProgress
 
     var selectedCurrency: String? = null
-    var selectedEvent: HistoryEvent? = null
+    var selectedTransaction: Transaction? = null
 
     private val mTransactions = MutableLiveData<TransactionsResult>()
     val transactions: LiveData<TransactionsResult> = mTransactions
 
     fun loadTransactions() {
         mProgress.postValue(true)
-        walletBackendApi.sendRequest("getHistory", null) { isError, result ->
+        val request = JSONObject(mapOf("currency" to selectedCurrency))
+        walletBackendApi.sendRequest("getTransactions", request) { isError, 
result ->
             scope.launch(Dispatchers.Default) {
                 onTransactionsLoaded(isError, result)
             }
@@ -62,15 +63,9 @@ class TransactionManager(
             mTransactions.postValue(TransactionsResult.Error)
             return
         }
-        val transactions = History()
-        val json = result.getJSONArray("history")
-        val currency = selectedCurrency
-        for (i in 0 until json.length()) {
-            val event: HistoryEvent = mapper.readValue(json.getString(i))
-            if (event.showToUser && (currency == null || 
event.isCurrency(currency))) {
-                transactions.add(event)
-            }
-        }
+        Log.e("TEST", result.toString(2))  // TODO remove once API finalized
+        val transactionsArray = result.getString("transactions")
+        val transactions: LinkedList<Transaction> = 
mapper.readValue(transactionsArray)
         transactions.reverse()  // show latest first
         mProgress.postValue(false)
         mTransactions.postValue(TransactionsResult.Success(transactions))
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
new file mode 100644
index 0000000..2a0da3c
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
@@ -0,0 +1,178 @@
+/*
+ * 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.transactions
+
+import android.content.Context
+import androidx.annotation.DrawableRes
+import androidx.annotation.LayoutRes
+import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.annotation.JsonSubTypes
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type
+import com.fasterxml.jackson.annotation.JsonTypeInfo
+import com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY
+import com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME
+import com.fasterxml.jackson.annotation.JsonTypeName
+import net.taler.common.Amount
+import net.taler.common.ContractMerchant
+import net.taler.common.ContractProduct
+import net.taler.common.Timestamp
+import net.taler.wallet.R
+import net.taler.wallet.cleanExchange
+import net.taler.wallet.history.AmountType
+
+@JsonTypeInfo(use = NAME, include = PROPERTY, property = "type")
+@JsonSubTypes(
+    Type(value = TransactionWithdrawal::class, name = "withdrawal"),
+    Type(value = TransactionPayment::class, name = "payment"),
+    Type(value = TransactionRefund::class, name = "refund"),
+    Type(value = TransactionTip::class, name = "tip"),
+    Type(value = TransactionRefresh::class, name = "refresh")
+)
+abstract class Transaction(
+    val transactionId: String,
+    val timestamp: Timestamp,
+    val pending: Boolean,
+    val amountRaw: Amount,
+    val amountEffective: Amount?
+) {
+    @get:DrawableRes
+    abstract val icon: Int
+
+    @get:LayoutRes
+    abstract val detailPageLayout: Int
+
+    abstract val amountType: AmountType
+
+    abstract fun getTitle(context: Context): String
+}
+
+@JsonTypeName("withdrawal")
+class TransactionWithdrawal(
+    transactionId: String,
+    timestamp: Timestamp,
+    pending: Boolean,
+    val exchangeBaseUrl: String = "unknown",  // TODO fix in wallet-core
+    val confirmed: Boolean,
+    val bankConfirmationUrl: String?,
+    @JsonProperty("amountEffective")  // TODO remove when fixed in wallet-core
+    amountRaw: Amount,
+    @JsonProperty("amountRaw")  // TODO remove when fixed in wallet-core
+    amountEffective: Amount?
+) : Transaction(transactionId, timestamp, pending, amountRaw, amountEffective) 
{
+    override val icon = R.drawable.transaction_withdrawal
+    override val detailPageLayout = R.layout.fragment_transaction_withdrawal
+    override val amountType = AmountType.Positive
+    override fun getTitle(context: Context) = cleanExchange(exchangeBaseUrl)
+}
+
+@JsonTypeName("payment")
+class TransactionPayment(
+    transactionId: String,
+    timestamp: Timestamp,
+    pending: Boolean,
+    val info: TransactionInfo,
+    val status: PaymentStatus,
+    amountRaw: Amount,
+    amountEffective: Amount?
+) : Transaction(transactionId, timestamp, pending, amountRaw, amountEffective) 
{
+    override val icon = R.drawable.ic_cash_usd_outline
+    override val detailPageLayout = R.layout.fragment_transaction_payment
+    override val amountType = AmountType.Negative
+    override fun getTitle(context: Context) = info.merchant.name ?: 
info.summary
+}
+
+class TransactionInfo(
+    val orderId: String,
+    val merchant: ContractMerchant,
+    val summary: String,
+    @get:JsonProperty("description_i18n")
+    val summaryI18n: Map<String, String>?,
+    val products: List<ContractProduct>,
+    val fulfillmentUrl: String
+)
+
+enum class PaymentStatus {
+    @JsonProperty("aborted")
+    Aborted,
+
+    @JsonProperty("failed")
+    Failed,
+
+    @JsonProperty("paid")
+    Paid,
+
+    @JsonProperty("offered")
+    Offered,
+
+    @JsonProperty("accepted")
+    Accepted
+}
+
+@JsonTypeName("refund")
+class TransactionRefund(
+    transactionId: String,
+    timestamp: Timestamp,
+    pending: Boolean,
+    val refundedTransactionId: String,
+    val info: TransactionInfo,
+    val amountInvalid: Amount,
+    amountRaw: Amount,
+    amountEffective: Amount?
+) : Transaction(transactionId, timestamp, pending, amountRaw, amountEffective) 
{
+    override val icon = R.drawable.transaction_refund
+    override val detailPageLayout = R.layout.fragment_transaction_payment
+    override val amountType = AmountType.Positive
+    override fun getTitle(context: Context): String {
+        return context.getString(R.string.transaction_refund, 
info.merchant.name)
+    }
+}
+
+@JsonTypeName("tip")
+class TransactionTip(
+    transactionId: String,
+    timestamp: Timestamp,
+    pending: Boolean,
+    // TODO status: TipStatus,
+    val exchangeBaseUrl: String,
+    val merchant: ContractMerchant,
+    amountRaw: Amount,
+    amountEffective: Amount?
+) : Transaction(transactionId, timestamp, pending, amountRaw, amountEffective) 
{
+    override val icon = R.drawable.transaction_tip_accepted // TODO different 
when declined
+    override val detailPageLayout = R.layout.fragment_transaction_payment
+    override val amountType = AmountType.Positive
+    override fun getTitle(context: Context): String {
+        return context.getString(R.string.transaction_tip_from, merchant.name)
+    }
+}
+
+@JsonTypeName("refresh")
+class TransactionRefresh(
+    transactionId: String,
+    timestamp: Timestamp,
+    pending: Boolean,
+    val exchangeBaseUrl: String,
+    amountRaw: Amount,
+    amountEffective: Amount?
+) : Transaction(transactionId, timestamp, pending, amountRaw, amountEffective) 
{
+    override val icon = R.drawable.transaction_refresh
+    override val detailPageLayout = R.layout.fragment_transaction_payment
+    override val amountType = AmountType.Negative
+    override fun getTitle(context: Context): String {
+        return context.getString(R.string.transaction_refresh)
+    }
+}
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
index 2b5337f..dfd00ea 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
@@ -42,10 +42,9 @@ import net.taler.common.fadeIn
 import net.taler.common.fadeOut
 import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
-import net.taler.wallet.history.HistoryEvent
 
 interface OnTransactionClickListener {
-    fun onTransactionClicked(transaction: HistoryEvent)
+    fun onTransactionClicked(transaction: Transaction)
 }
 
 class TransactionsFragment : Fragment(), OnTransactionClickListener, 
ActionMode.Callback {
@@ -138,10 +137,10 @@ class TransactionsFragment : Fragment(), 
OnTransactionClickListener, ActionMode.
         }
     }
 
-    override fun onTransactionClicked(transaction: HistoryEvent) {
+    override fun onTransactionClicked(transaction: Transaction) {
         if (actionMode != null) return // don't react on clicks while in 
action mode
         if (transaction.detailPageLayout != 0) {
-            transactionManager.selectedEvent = transaction
+            transactionManager.selectedTransaction = transaction
             findNavController().navigate(R.id.action_nav_transaction_detail)
         }
     }
diff --git a/wallet/src/main/res/layout/fragment_event_paid.xml 
b/wallet/src/main/res/layout/fragment_transaction_payment.xml
similarity index 100%
rename from wallet/src/main/res/layout/fragment_event_paid.xml
rename to wallet/src/main/res/layout/fragment_transaction_payment.xml
diff --git a/wallet/src/main/res/layout/fragment_event_withdraw.xml 
b/wallet/src/main/res/layout/fragment_transaction_withdrawal.xml
similarity index 100%
rename from wallet/src/main/res/layout/fragment_event_withdraw.xml
rename to wallet/src/main/res/layout/fragment_transaction_withdrawal.xml
diff --git a/wallet/src/main/res/layout/list_item_transaction.xml 
b/wallet/src/main/res/layout/list_item_transaction.xml
new file mode 100644
index 0000000..058b170
--- /dev/null
+++ b/wallet/src/main/res/layout/list_item_transaction.xml
@@ -0,0 +1,89 @@
+<?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="wrap_content"
+    android:background="@drawable/selectable_background"
+    android:foreground="?attr/selectableItemBackground"
+    android:paddingStart="16dp"
+    android:paddingTop="8dp"
+    android:paddingEnd="16dp"
+    android:paddingBottom="8dp">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:tint="?android:colorControlNormal"
+        tools:ignore="ContentDescription"
+        tools:src="@drawable/ic_cash_usd_outline" />
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/TransactionTitle"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="8dp"
+        app:layout_constraintEnd_toStartOf="@+id/amount"
+        app:layout_constraintStart_toEndOf="@+id/icon"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="@string/transaction_payment" />
+
+    <TextView
+        android:id="@+id/amount"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="24sp"
+        app:layout_constraintBottom_toTopOf="@+id/pendingView"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="- 1337.23" />
+
+    <TextView
+        android:id="@+id/time"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="8dp"
+        android:textSize="14sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@+id/amount"
+        app:layout_constraintStart_toStartOf="@+id/title"
+        app:layout_constraintTop_toBottomOf="@+id/title"
+        tools:text="23 min ago" />
+
+    <TextView
+        android:id="@+id/pendingView"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/transaction_pending"
+        android:textSize="14sp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="1.0"
+        app:layout_constraintStart_toEndOf="@+id/time"
+        app:layout_constraintTop_toBottomOf="@+id/amount"
+        tools:visibility="visible" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/wallet/src/main/res/menu/transactions_detail.xml 
b/wallet/src/main/res/menu/transactions_detail.xml
index 388e3c4..d4568d4 100644
--- a/wallet/src/main/res/menu/transactions_detail.xml
+++ b/wallet/src/main/res/menu/transactions_detail.xml
@@ -16,8 +16,4 @@
 
 <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/transactions_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 8e717c1..5523d8b 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -71,7 +71,7 @@
         android:id="@+id/nav_transactions_detail"
         android:name="net.taler.wallet.transactions.TransactionDetailFragment"
         android:label="@string/transactions_detail_title"
-        tools:layout="@layout/fragment_event_withdraw" />
+        tools:layout="@layout/fragment_transaction_withdrawal" />
 
     <fragment
         android:id="@+id/alreadyPaid"
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index 56ff2ef..44b2dad 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -80,8 +80,10 @@ GNU Taler is immune against many types of fraud, such as 
phishing of credit card
     <string name="transaction_order_refused">Purchase Cancelled</string>
     <string name="transaction_tip_accepted">Tip Accepted</string>
     <string name="transaction_tip_declined">Tip Declined</string>
-    <string name="transaction_refund">Refund</string>
-    <string name="transaction_refresh">Obtained change</string>
+    <string name="transaction_tip_from">Tip from %s</string>
+    <string name="transaction_refund">Refund from %s</string>
+    <string name="transaction_pending">PENDING</string>
+    <string name="transaction_refresh">Coin expiry change fee</string>
     <string name="transaction_refresh_reason_manual">because of manual 
request</string>
     <string name="transaction_refresh_reason_pay">for payment</string>
     <string name="transaction_refresh_reason_refund">for refund</string>

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



reply via email to

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