summaryrefslogtreecommitdiff
path: root/wallet/src/main/java/net/taler/wallet/transactions
diff options
context:
space:
mode:
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/transactions')
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt57
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/ReserveTransaction.kt59
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt497
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt38
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt17
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt72
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt16
7 files changed, 74 insertions, 682 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt
deleted file mode 100644
index 2337059..0000000
--- a/wallet/src/main/java/net/taler/wallet/transactions/JsonDialogFragment.kt
+++ /dev/null
@@ -1,57 +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.transactions
-
-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
-
-class JsonDialogFragment : DialogFragment() {
-
- companion object {
- fun new(json: String): JsonDialogFragment {
- return JsonDialogFragment().apply {
- arguments = Bundle().apply { putString("json", json) }
- }
- }
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- return inflater.inflate(R.layout.fragment_json, container, false)
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- val json = requireArguments().getString("json")
- 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/transactions/ReserveTransaction.kt b/wallet/src/main/java/net/taler/wallet/transactions/ReserveTransaction.kt
deleted file mode 100644
index e497e9a..0000000
--- a/wallet/src/main/java/net/taler/wallet/transactions/ReserveTransaction.kt
+++ /dev/null
@@ -1,59 +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.transactions
-
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.fasterxml.jackson.annotation.JsonSubTypes
-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.Timestamp
-
-
-@JsonTypeInfo(
- use = NAME,
- include = PROPERTY,
- property = "type"
-)
-@JsonSubTypes(
- JsonSubTypes.Type(value = ReserveDepositTransaction::class, name = "DEPOSIT")
-)
-abstract class ReserveTransaction
-
-
-@JsonTypeName("DEPOSIT")
-class ReserveDepositTransaction(
- /**
- * Amount withdrawn.
- */
- val amount: String,
- /**
- * Sender account payto://-URL
- */
- @JsonProperty("sender_account_url")
- val senderAccountUrl: String,
- /**
- * Transfer details uniquely identifying the transfer.
- */
- @JsonProperty("wire_reference")
- val wireReference: String,
- /**
- * Timestamp of the incoming wire transfer.
- */
- val timestamp: Timestamp
-) : ReserveTransaction()
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt b/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
deleted file mode 100644
index 34942d0..0000000
--- a/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
+++ /dev/null
@@ -1,497 +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.transactions
-
-import androidx.annotation.DrawableRes
-import androidx.annotation.LayoutRes
-import com.fasterxml.jackson.annotation.JsonInclude
-import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY
-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.Timestamp
-import net.taler.wallet.R
-import net.taler.wallet.cleanExchange
-import org.json.JSONObject
-
-enum class ReserveType {
- /**
- * Manually created.
- */
- @JsonProperty("manual")
- MANUAL,
-
- /**
- * Withdrawn from a bank that has "tight" Taler integration
- */
- @JsonProperty("taler-bank-withdraw")
- @Suppress("unused")
- TALER_BANK_WITHDRAW,
-}
-
-@JsonInclude(NON_EMPTY)
-class ReserveCreationDetail(val type: ReserveType, val bankUrl: String?)
-
-enum class RefreshReason {
- @JsonProperty("manual")
- @Suppress("unused")
- MANUAL,
-
- @JsonProperty("pay")
- PAY,
-
- @JsonProperty("refund")
- @Suppress("unused")
- REFUND,
-
- @JsonProperty("abort-pay")
- @Suppress("unused")
- ABORT_PAY,
-
- @JsonProperty("recoup")
- @Suppress("unused")
- RECOUP,
-
- @JsonProperty("backup-restored")
- @Suppress("unused")
- BACKUP_RESTORED
-}
-
-@JsonInclude(NON_EMPTY)
-class ReserveShortInfo(
- /**
- * The exchange that the reserve will be at.
- */
- val exchangeBaseUrl: String,
- /**
- * Key to query more details
- */
- val reservePub: String,
- /**
- * Detail about how the reserve has been created.
- */
- val reserveCreationDetail: ReserveCreationDetail
-)
-
-sealed class AmountType {
- object Positive : AmountType()
- object Negative : AmountType()
- object Neutral : AmountType()
-}
-
-class DisplayAmount(
- val amount: Amount,
- val type: AmountType
-)
-
-typealias Transactions = ArrayList<Transaction>
-
-@JsonTypeInfo(
- use = NAME,
- include = PROPERTY,
- property = "type",
- defaultImpl = UnknownTransaction::class
-)
-/** missing:
-AuditorComplaintSent = "auditor-complained-sent",
-AuditorComplaintProcessed = "auditor-complaint-processed",
-AuditorTrustAdded = "auditor-trust-added",
-AuditorTrustRemoved = "auditor-trust-removed",
-ExchangeTermsAccepted = "exchange-terms-accepted",
-ExchangePolicyChanged = "exchange-policy-changed",
-ExchangeTrustAdded = "exchange-trust-added",
-ExchangeTrustRemoved = "exchange-trust-removed",
-FundsDepositedToSelf = "funds-deposited-to-self",
-FundsRecouped = "funds-recouped",
-ReserveCreated = "reserve-created",
- */
-@JsonSubTypes(
- Type(value = ExchangeAddedEvent::class, name = "exchange-added"),
- Type(value = ExchangeUpdatedEvent::class, name = "exchange-updated"),
- Type(value = ReserveBalanceUpdatedTransaction::class, name = "reserve-balance-updated"),
- Type(value = WithdrawTransaction::class, name = "withdrawn"),
- Type(value = OrderAcceptedTransaction::class, name = "order-accepted"),
- Type(value = OrderRefusedTransaction::class, name = "order-refused"),
- Type(value = OrderRedirectedTransaction::class, name = "order-redirected"),
- Type(value = PaymentTransaction::class, name = "payment-sent"),
- Type(value = PaymentAbortedTransaction::class, name = "payment-aborted"),
- Type(value = TipAcceptedTransaction::class, name = "tip-accepted"),
- Type(value = TipDeclinedTransaction::class, name = "tip-declined"),
- Type(value = RefundTransaction::class, name = "refund"),
- Type(value = RefreshTransaction::class, name = "refreshed")
-)
-abstract class Transaction(
- val timestamp: Timestamp,
- val eventId: String,
- @get:LayoutRes
- open val detailPageLayout: Int = 0,
- @get:DrawableRes
- open val icon: Int = R.drawable.ic_account_balance,
- open val showToUser: Boolean = false
-) {
- abstract val title: String?
- open lateinit var json: JSONObject
- open val displayAmount: DisplayAmount? = null
- open fun isCurrency(currency: String): Boolean = true
-}
-
-
-class UnknownTransaction(timestamp: Timestamp, eventId: String) : Transaction(timestamp, eventId) {
- override val title: String? = null
-}
-
-@JsonTypeName("exchange-added")
-class ExchangeAddedEvent(
- timestamp: Timestamp,
- eventId: String,
- val exchangeBaseUrl: String,
- val builtIn: Boolean
-) : Transaction(timestamp, eventId) {
- override val title = cleanExchange(exchangeBaseUrl)
-}
-
-@JsonTypeName("exchange-updated")
-class ExchangeUpdatedEvent(
- timestamp: Timestamp,
- eventId: String,
- val exchangeBaseUrl: String
-) : Transaction(timestamp, eventId) {
- override val title = cleanExchange(exchangeBaseUrl)
-}
-
-
-@JsonTypeName("reserve-balance-updated")
-class ReserveBalanceUpdatedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Condensed information about the reserve.
- */
- val reserveShortInfo: ReserveShortInfo,
- /**
- * Amount currently left in the reserve.
- */
- val reserveBalance: Amount,
- /**
- * Amount we expected to be in the reserve at that time,
- * considering ongoing withdrawals from that reserve.
- */
- val reserveAwaitedAmount: Amount,
- /**
- * Amount that hasn't been withdrawn yet.
- */
- val reserveUnclaimedAmount: Amount
-) : Transaction(timestamp, eventId) {
- override val title: String? = null
- override val displayAmount = DisplayAmount(reserveBalance, AmountType.Neutral)
- override fun isCurrency(currency: String) = reserveBalance.currency == currency
-}
-
-@JsonTypeName("withdrawn")
-class WithdrawTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Exchange that was withdrawn from.
- */
- val exchangeBaseUrl: String,
- /**
- * Unique identifier for the withdrawal session, can be used to
- * query more detailed information from the wallet.
- */
- val withdrawalGroupId: String,
- val withdrawalSource: WithdrawalSource,
- /**
- * Amount that has been subtracted from the reserve's balance
- * for this withdrawal.
- */
- val amountWithdrawnRaw: Amount,
- /**
- * Amount that actually was added to the wallet's balance.
- */
- val amountWithdrawnEffective: Amount
-) : Transaction(timestamp, eventId) {
- override val detailPageLayout = R.layout.fragment_event_withdraw
- override val title = cleanExchange(exchangeBaseUrl)
- override val icon = R.drawable.transaction_withdrawal
- override val showToUser = true
- override val displayAmount = DisplayAmount(amountWithdrawnEffective, AmountType.Positive)
- override fun isCurrency(currency: String) = amountWithdrawnRaw.currency == currency
-}
-
-@JsonTypeName("order-accepted")
-class OrderAcceptedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Condensed info about the order.
- */
- val orderShortInfo: OrderShortInfo
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.ic_add_circle
- override val title: String? = null
- override fun isCurrency(currency: String) = orderShortInfo.amount.currency == currency
-}
-
-@JsonTypeName("order-refused")
-class OrderRefusedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Condensed info about the order.
- */
- val orderShortInfo: OrderShortInfo
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.ic_cancel
- override val title: String? = null
- override fun isCurrency(currency: String) = orderShortInfo.amount.currency == currency
-}
-
-@JsonTypeName("payment-sent")
-class PaymentTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Condensed info about the order that we already paid for.
- */
- val orderShortInfo: OrderShortInfo,
- /**
- * Set to true if the payment has been previously sent
- * to the merchant successfully, possibly with a different session ID.
- */
- val replay: Boolean,
- /**
- * Number of coins that were involved in the payment.
- */
- val numCoins: Int,
- /**
- * Amount that was paid, including deposit and wire fees.
- */
- val amountPaidWithFees: Amount,
- /**
- * Session ID that the payment was (re-)submitted under.
- */
- val sessionId: String?
-) : Transaction(timestamp, eventId) {
- override val detailPageLayout = R.layout.fragment_event_paid
- override val title = orderShortInfo.summary
- override val icon = R.drawable.ic_cash_usd_outline
- override val showToUser = true
- override val displayAmount = DisplayAmount(amountPaidWithFees, AmountType.Negative)
- override fun isCurrency(currency: String) = orderShortInfo.amount.currency == currency
-}
-
-@JsonTypeName("payment-aborted")
-class PaymentAbortedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Condensed info about the order that we already paid for.
- */
- val orderShortInfo: OrderShortInfo,
- /**
- * Amount that was lost due to refund and refreshing fees.
- */
- val amountLost: Amount
-) : Transaction(timestamp, eventId) {
- override val title = orderShortInfo.summary
- override val icon = R.drawable.transaction_payment_aborted
- override val showToUser = true
- override val displayAmount = DisplayAmount(amountLost, AmountType.Negative)
- override fun isCurrency(currency: String) = orderShortInfo.amount.currency == currency
-}
-
-@JsonTypeName("refreshed")
-class RefreshTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Amount that is now available again because it has
- * been refreshed.
- */
- val amountRefreshedEffective: Amount,
- /**
- * Amount that we spent for refreshing.
- */
- val amountRefreshedRaw: Amount,
- /**
- * Why was the refreshing done?
- */
- val refreshReason: RefreshReason,
- val numInputCoins: Int,
- val numRefreshedInputCoins: Int,
- val numOutputCoins: Int,
- /**
- * Identifier for a refresh group, contains one or
- * more refresh session IDs.
- */
- val refreshGroupId: String
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.transaction_refresh
- override val title: String? = null
- override val showToUser = !(amountRefreshedRaw - amountRefreshedEffective).isZero()
- override val displayAmount: DisplayAmount?
- get() {
- return if (showToUser) DisplayAmount(
- amountRefreshedRaw - amountRefreshedEffective,
- AmountType.Negative
- )
- else null
- }
-
- override fun isCurrency(currency: String) = amountRefreshedRaw.currency == currency
-}
-
-@JsonTypeName("order-redirected")
-class OrderRedirectedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Condensed info about the new order that contains a
- * product (identified by the fulfillment URL) that we've already paid for.
- */
- val newOrderShortInfo: OrderShortInfo,
- /**
- * Condensed info about the order that we already paid for.
- */
- val alreadyPaidOrderShortInfo: OrderShortInfo
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.ic_directions
- override val title = newOrderShortInfo.summary
- override fun isCurrency(currency: String) = newOrderShortInfo.amount.currency == currency
-}
-
-@JsonTypeName("tip-accepted")
-class TipAcceptedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Unique identifier for the tip to query more information.
- */
- val tipId: String,
- /**
- * Raw amount of the tip, without extra fees that apply.
- */
- val tipRaw: Amount
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.transaction_tip_accepted
- override val title: String? = null
- override val showToUser = true
- override val displayAmount = DisplayAmount(tipRaw, AmountType.Positive)
- override fun isCurrency(currency: String) = tipRaw.currency == currency
-}
-
-@JsonTypeName("tip-declined")
-class TipDeclinedTransaction(
- timestamp: Timestamp,
- eventId: String,
- /**
- * Unique identifier for the tip to query more information.
- */
- val tipId: String,
- /**
- * Raw amount of the tip, without extra fees that apply.
- */
- val tipAmount: Amount
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.transaction_tip_declined
- override val title: String? = null
- override val showToUser = true
- override val displayAmount = DisplayAmount(tipAmount, AmountType.Neutral)
- override fun isCurrency(currency: String) = tipAmount.currency == currency
-}
-
-@JsonTypeName("refund")
-class RefundTransaction(
- timestamp: Timestamp,
- eventId: String,
- val orderShortInfo: OrderShortInfo,
- /**
- * Unique identifier for this refund.
- * (Identifies multiple refund permissions that were obtained at once.)
- */
- val refundGroupId: String,
- /**
- * Part of the refund that couldn't be applied because
- * the refund permissions were expired.
- */
- val amountRefundedInvalid: Amount,
- /**
- * Amount that has been refunded by the merchant.
- */
- val amountRefundedRaw: Amount,
- /**
- * Amount will be added to the wallet's balance after fees and refreshing.
- */
- val amountRefundedEffective: Amount
-) : Transaction(timestamp, eventId) {
- override val icon = R.drawable.transaction_refund
- override val title = orderShortInfo.summary
- override val detailPageLayout = R.layout.fragment_event_paid
- override val showToUser = true
- override val displayAmount = DisplayAmount(amountRefundedEffective, AmountType.Positive)
- override fun isCurrency(currency: String) = amountRefundedRaw.currency == currency
-}
-
-@JsonTypeInfo(
- use = NAME,
- include = PROPERTY,
- property = "type"
-)
-@JsonSubTypes(
- Type(value = WithdrawalSourceReserve::class, name = "reserve")
-)
-abstract class WithdrawalSource
-
-@Suppress("unused")
-@JsonTypeName("tip")
-class WithdrawalSourceTip(
- val tipId: String
-) : WithdrawalSource()
-
-@JsonTypeName("reserve")
-class WithdrawalSourceReserve(
- val reservePub: String
-) : WithdrawalSource()
-
-data class OrderShortInfo(
- /**
- * Wallet-internal identifier of the proposal.
- */
- val proposalId: String,
- /**
- * Order ID, uniquely identifies the order within a merchant instance.
- */
- val orderId: String,
- /**
- * Base URL of the merchant.
- */
- val merchantBaseUrl: String,
- /**
- * Amount that must be paid for the contract.
- */
- val amount: Amount,
- /**
- * Summary of the proposal, given by the merchant.
- */
- val summary: String
-)
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 440d07f..5aca896 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -34,13 +34,23 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder
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 devMode: Boolean,
- private val listener: OnEventClickListener,
- private var transactions: Transactions = Transactions()
+ private val listener: OnTransactionClickListener,
+ private var transactions: History = History()
) : Adapter<TransactionViewHolder>() {
lateinit var tracker: SelectionTracker<String>
@@ -52,7 +62,7 @@ internal class TransactionAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
val view = LayoutInflater.from(parent.context)
- .inflate(R.layout.list_item_transaction, parent, false)
+ .inflate(R.layout.list_item_history, parent, false)
return TransactionViewHolder(view)
}
@@ -63,7 +73,7 @@ internal class TransactionAdapter(
holder.bind(transaction, tracker.isSelected(transaction.eventId))
}
- fun update(updatedTransactions: Transactions) {
+ fun update(updatedTransactions: History) {
this.transactions = updatedTransactions
this.notifyDataSetChanged()
}
@@ -84,8 +94,8 @@ internal class TransactionAdapter(
private val selectableForeground = v.foreground
private val amountColor = amount.currentTextColor
- open fun bind(transaction: Transaction, selected: Boolean) {
- if (devMode || transaction.detailPageLayout != 0) {
+ open fun bind(transaction: HistoryEvent, selected: Boolean) {
+ if (transaction.detailPageLayout != 0) {
v.foreground = selectableForeground
v.setOnClickListener { listener.onTransactionClicked(transaction) }
} else {
@@ -97,12 +107,12 @@ internal class TransactionAdapter(
title.text = if (transaction.title == null) {
when (transaction) {
- is RefreshTransaction -> getRefreshTitle(transaction)
- is OrderAcceptedTransaction -> context.getString(R.string.transaction_order_accepted)
- is OrderRefusedTransaction -> context.getString(R.string.transaction_order_refused)
- is TipAcceptedTransaction -> context.getString(R.string.transaction_tip_accepted)
- is TipDeclinedTransaction -> context.getString(R.string.transaction_tip_declined)
- is ReserveBalanceUpdatedTransaction -> context.getString(R.string.transaction_reserve_balance_updated)
+ 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
@@ -137,7 +147,7 @@ internal class TransactionAdapter(
}
}
- private fun getRefreshTitle(transaction: RefreshTransaction): String {
+ 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
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 909a7bf..bb70b5c 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionDetailFragment.kt
@@ -37,6 +37,11 @@ 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() {
@@ -65,9 +70,9 @@ class TransactionDetailFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
timeView.text = event.timestamp.ms.toAbsoluteTime(requireContext())
when (val e = event) {
- is WithdrawTransaction -> bind(e)
- is PaymentTransaction -> bind(e)
- is RefundTransaction -> bind(e)
+ is WithdrawHistoryEvent -> bind(e)
+ is PaymentHistoryEvent -> bind(e)
+ is RefundHistoryEvent -> bind(e)
else -> Toast.makeText(
requireContext(),
"event ${e.javaClass} not implement",
@@ -90,7 +95,7 @@ class TransactionDetailFragment : Fragment() {
}
}
- private fun bind(event: WithdrawTransaction) {
+ private fun bind(event: WithdrawHistoryEvent) {
effectiveAmountLabel.text = getString(R.string.withdraw_total)
effectiveAmountView.text = event.amountWithdrawnEffective.toString()
chosenAmountLabel.text = getString(R.string.amount_chosen)
@@ -101,13 +106,13 @@ class TransactionDetailFragment : Fragment() {
exchangeView.text = cleanExchange(event.exchangeBaseUrl)
}
- private fun bind(event: PaymentTransaction) {
+ private fun bind(event: PaymentHistoryEvent) {
amountPaidWithFeesView.text = event.amountPaidWithFees.toString()
val fee = event.amountPaidWithFees - event.orderShortInfo.amount
bindOrderAndFee(event.orderShortInfo, fee)
}
- private fun bind(event: RefundTransaction) {
+ private fun bind(event: RefundHistoryEvent) {
amountPaidWithFeesLabel.text = getString(R.string.transaction_refund)
amountPaidWithFeesView.setTextColor(getColor(requireContext(), R.color.green))
amountPaidWithFeesView.text =
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 549b2a8..850a3bb 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
@@ -18,70 +18,62 @@ package net.taler.wallet.transactions
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.asLiveData
-import androidx.lifecycle.switchMap
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.onCompletion
-import kotlinx.coroutines.flow.onStart
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
sealed class TransactionsResult {
object Error : TransactionsResult()
- class Success(val transactions: Transactions) : TransactionsResult()
+ class Success(val transactions: History) : TransactionsResult()
}
-@Suppress("EXPERIMENTAL_API_USAGE")
class TransactionManager(
private val walletBackendApi: WalletBackendApi,
+ private val scope: CoroutineScope,
private val mapper: ObjectMapper
) {
private val mProgress = MutableLiveData<Boolean>()
val progress: LiveData<Boolean> = mProgress
- val showAll = MutableLiveData<Boolean>()
-
var selectedCurrency: String? = null
- var selectedEvent: Transaction? = null
+ var selectedEvent: HistoryEvent? = null
- val transactions: LiveData<TransactionsResult> = showAll.switchMap { showAll ->
- loadTransactions(showAll)
- .onStart { mProgress.postValue(true) }
- .onCompletion { mProgress.postValue(false) }
- .asLiveData(Dispatchers.IO)
- }
+ private val mTransactions = MutableLiveData<TransactionsResult>()
+ val transactions: LiveData<TransactionsResult> = mTransactions
- private fun loadTransactions(showAll: Boolean) = callbackFlow {
+ fun loadTransactions() {
+ mProgress.postValue(true)
walletBackendApi.sendRequest("getHistory", null) { isError, result ->
- launch(Dispatchers.Default) {
- if (isError) {
- offer(TransactionsResult.Error)
- close()
- return@launch
- }
- val transactions = Transactions()
- val json = result.getJSONArray("history")
- val currency = selectedCurrency
- for (i in 0 until json.length()) {
- val event: Transaction = mapper.readValue(json.getString(i))
- event.json = json.getJSONObject(i)
- if (currency == null || event.isCurrency(currency)) {
- transactions.add(event)
- }
- }
- transactions.reverse() // show latest first
- val filtered =
- if (showAll) transactions else transactions.filter { it.showToUser } as Transactions
- offer(TransactionsResult.Success(filtered))
- close()
+ scope.launch(Dispatchers.Default) {
+ onTransactionsLoaded(isError, result)
+ }
+ }
+ }
+
+ private fun onTransactionsLoaded(isError: Boolean, result: JSONObject) {
+ if (isError) {
+ 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)
}
}
- awaitClose()
+ transactions.reverse() // show latest first
+ mProgress.postValue(false)
+ mTransactions.postValue(TransactionsResult.Success(transactions))
}
}
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 e7adaf1..2b5337f 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
@@ -42,17 +42,18 @@ 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 OnEventClickListener {
- fun onTransactionClicked(transaction: Transaction)
+interface OnTransactionClickListener {
+ fun onTransactionClicked(transaction: HistoryEvent)
}
-class TransactionsFragment : Fragment(), OnEventClickListener, ActionMode.Callback {
+class TransactionsFragment : Fragment(), OnTransactionClickListener, ActionMode.Callback {
private val model: MainViewModel by activityViewModels()
private val transactionManager by lazy { model.transactionManager }
- private val transactionAdapter by lazy { TransactionAdapter(model.devMode.value == true, this) }
+ private val transactionAdapter by lazy { TransactionAdapter(this) }
private val currency by lazy { transactionManager.selectedCurrency!! }
private var tracker: SelectionTracker<String>? = null
private var actionMode: ActionMode? = null
@@ -109,7 +110,7 @@ class TransactionsFragment : Fragment(), OnEventClickListener, ActionMode.Callba
})
// kicks off initial load, needs to be adapted if showAll state is ever saved
- if (savedInstanceState == null) transactionManager.showAll.value = model.devMode.value
+ if (savedInstanceState == null) transactionManager.loadTransactions()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
@@ -137,14 +138,11 @@ class TransactionsFragment : Fragment(), OnEventClickListener, ActionMode.Callba
}
}
- override fun onTransactionClicked(transaction: Transaction) {
+ override fun onTransactionClicked(transaction: HistoryEvent) {
if (actionMode != null) return // don't react on clicks while in action mode
if (transaction.detailPageLayout != 0) {
transactionManager.selectedEvent = transaction
findNavController().navigate(R.id.action_nav_transaction_detail)
- } else if (model.devMode.value == true) {
- JsonDialogFragment.new(transaction.json.toString(2))
- .show(parentFragmentManager, null)
}
}