From 73c1f6988d735b00dd328dd9bb02566f987e3e96 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 17 Feb 2023 10:25:07 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../rv => common}/ShimmerRecyclerAdapter.kt | 2 +- .../wallet/saltPay/HistoryTransactionData.kt | 21 ---- .../ui/wallet/saltPay/SaltPayWalletView.kt | 39 ++++-- .../ui/wallet/saltPay/rv/HistoryItemData.kt | 74 ++++++++++++ .../saltPay/rv/TransactionHistoryAdapter.kt | 103 ---------------- .../ui/wallet/saltPay/rv/TxHistoryAdapter.kt | 112 ++++++++++++++++++ 6 files changed, 214 insertions(+), 137 deletions(-) rename app/src/main/java/com/tangem/tap/{features/wallet/ui/wallet/saltPay/rv => common}/ShimmerRecyclerAdapter.kt (95%) delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/HistoryTransactionData.kt create mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TransactionHistoryAdapter.kt create mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/ShimmerRecyclerAdapter.kt b/app/src/main/java/com/tangem/tap/common/ShimmerRecyclerAdapter.kt similarity index 95% rename from app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/ShimmerRecyclerAdapter.kt rename to app/src/main/java/com/tangem/tap/common/ShimmerRecyclerAdapter.kt index fc59d49155..4d56172588 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/ShimmerRecyclerAdapter.kt +++ b/app/src/main/java/com/tangem/tap/common/ShimmerRecyclerAdapter.kt @@ -1,4 +1,4 @@ -package com.tangem.tap.features.wallet.ui.wallet.saltPay.rv +package com.tangem.tap.common import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/HistoryTransactionData.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/HistoryTransactionData.kt deleted file mode 100644 index 50b80f0b37..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/HistoryTransactionData.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet.saltPay - -import com.tangem.blockchain.common.TransactionData -import com.tangem.blockchain.common.TransactionStatus -import com.tangem.tap.features.wallet.models.PendingTransactionType - -/** -[REDACTED_AUTHOR] - */ -data class HistoryTransactionData( - val transactionData: TransactionData, - private val walletAddress: String, -) { - fun isInProgress(): Boolean = transactionData.status == TransactionStatus.Unconfirmed - - fun getTransactionType(): PendingTransactionType = when { - transactionData.sourceAddress.lowercase() == walletAddress.lowercase() -> PendingTransactionType.Outgoing - transactionData.destinationAddress.lowercase() == walletAddress.lowercase() -> PendingTransactionType.Incoming - else -> PendingTransactionType.Unknown - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt index e1d9cbb642..62dccf8f6d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/SaltPayWalletView.kt @@ -6,6 +6,8 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager import com.tangem.blockchain.extensions.Result import com.tangem.domain.common.extensions.debounce import com.tangem.domain.common.extensions.withMainContext +import com.tangem.tap.common.ShimmerData +import com.tangem.tap.common.ShimmerRecyclerAdapter import com.tangem.tap.common.extensions.animateVisibility import com.tangem.tap.common.extensions.beginDelayedTransition import com.tangem.tap.common.extensions.formatAmountAsSpannedString @@ -18,9 +20,9 @@ import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.ui.WalletFragment import com.tangem.tap.features.wallet.ui.wallet.WalletView -import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.ShimmerData -import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.ShimmerRecyclerAdapter -import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.TransactionHistoryAdapter +import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryItemData +import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.HistoryTransactionData +import com.tangem.tap.features.wallet.ui.wallet.saltPay.rv.TxHistoryAdapter import com.tangem.tap.mainScope import com.tangem.tap.scope import com.tangem.tap.store @@ -85,7 +87,7 @@ class SaltPayWalletView : WalletView() { txWidget.rvTxHistoryShimmer.adapter = adapter txWidget.rvTxHistoryShimmer.addItemDecoration(SpaceItemDecoration.vertical(10F)) - txWidget.rvTxHistory.adapter = TransactionHistoryAdapter() + txWidget.rvTxHistory.adapter = TxHistoryAdapter() txWidget.rvTxHistory.addItemDecoration(SpaceItemDecoration.vertical(10F)) handleTxInit() @@ -147,18 +149,31 @@ class SaltPayWalletView : WalletView() { // val walletAddress = "0xDA94Aae02a4Db0e09E1Cf240E3a0973ba89052cf" when (val result = walletManager.getTransactionHistory(walletAddress, wallet.blockchain, setOf(token))) { is Result.Success -> { - val tokensHistory = result.data + val dateAssociatedHistory = mutableMapOf>() + + result.data .filter { it.contractAddress == token.contractAddress } - .sortedBy { it.date?.timeInMillis ?: 0 } - .map { HistoryTransactionData(it, walletAddress) } + .sortedByDescending { it.date?.timeInMillis ?: 0 } + .forEach { + val txData = HistoryTransactionData(it, walletAddress) + val list = dateAssociatedHistory[txData.date] ?: mutableListOf() + list.add(txData) + dateAssociatedHistory[txData.date] = list + } + + val dataList = mutableListOf() + dateAssociatedHistory.forEach { entry -> + dataList.add(HistoryItemData.Date(entry.key)) + entry.value.forEach { dataList.add(HistoryItemData.TransactionData(it)) } + } // .toMutableList().apply { clear() } delay(300) withMainContext { - if (tokensHistory.isEmpty()) { + if (dataList.isEmpty()) { handleTxEmpty() } else { - handleTxSuccess(tokensHistory) + handleTxSuccess(dataList) } } } @@ -185,7 +200,7 @@ class SaltPayWalletView : WalletView() { txWidget.groupShimmer.show() } - private fun handleTxSuccess(dataList: List) = with(txWidget) { + private fun handleTxSuccess(dataList: List) = with(txWidget) { groupShimmer.hide() groupEmpty.hide() groupError.hide() @@ -212,7 +227,7 @@ class SaltPayWalletView : WalletView() { groupError.show() } - private fun updateTxHistoryWidget(dataList: List) = with(txWidget) { - (rvTxHistory.adapter as TransactionHistoryAdapter).submitList(dataList) + private fun updateTxHistoryWidget(dataList: List) = with(txWidget) { + (rvTxHistory.adapter as TxHistoryAdapter).submitList(dataList) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt new file mode 100644 index 0000000000..0aa75abfba --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/HistoryItemData.kt @@ -0,0 +1,74 @@ +package com.tangem.tap.features.wallet.ui.wallet.saltPay.rv + +import com.tangem.blockchain.common.TransactionData +import com.tangem.blockchain.common.TransactionStatus +import com.tangem.common.extensions.guard +import com.tangem.tap.common.extensions.toFormattedCurrencyString +import com.tangem.tap.features.wallet.models.PendingTransactionType +import java.text.SimpleDateFormat +import java.util.* + +/** +[REDACTED_AUTHOR] + */ +sealed class HistoryItemData( + val viewType: Int, + val itemId: Long, +) { + data class Date(val date: String) : HistoryItemData(0, date.hashCode().toLong()) + data class TransactionData(val data: HistoryTransactionData) : HistoryItemData(1, data.hash.hashCode().toLong()) +} + +data class HistoryTransactionData( + private val transactionData: TransactionData, + private val walletAddress: String, +) { + + val isInProgress: Boolean = transactionData.status == TransactionStatus.Unconfirmed + + val transactionType: PendingTransactionType = when { + transactionData.sourceAddress.lowercase() == walletAddress.lowercase() -> PendingTransactionType.Outgoing + transactionData.destinationAddress.lowercase() == walletAddress.lowercase() -> PendingTransactionType.Incoming + else -> PendingTransactionType.Unknown + } + + val hash: String = transactionData.hash?.let { + "${it.substring(0..5)}...${it.substring(it.length - 4)}" + } ?: "" + + val time: String = transactionData.date?.let { + SimpleDateFormat("hh:MM").format(it.time) + } ?: "00:00" + + val date: String = calculateDate() + + val txSign: String = when (transactionType) { + PendingTransactionType.Incoming -> "+" + PendingTransactionType.Outgoing -> "-" + PendingTransactionType.Unknown -> "" + } + + val amountValue: String = transactionData.amount.value + ?.toFormattedCurrencyString(8, transactionData.amount.currencySymbol) ?: "0" + + private fun calculateDate(): String { + val calendarTx = transactionData.date.guard { return "Unknown" } + + val calendarNow = Calendar.getInstance() + val oldDateFormatter = SimpleDateFormat("dd.MM.yyyy") + + val date = if (calendarTx.get(Calendar.YEAR) == calendarNow.get(Calendar.YEAR)) { + val dayOfYearTx = calendarTx.get(Calendar.DAY_OF_YEAR) + val dayOfYearNow = calendarNow.get(Calendar.DAY_OF_YEAR) + when { + dayOfYearNow == dayOfYearTx -> "Today" + dayOfYearNow - dayOfYearTx == 1 -> "Tomorrow" + else -> oldDateFormatter.format(calendarTx.time) + } + } else { + oldDateFormatter.format(calendarTx.time) + } + + return date + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TransactionHistoryAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TransactionHistoryAdapter.kt deleted file mode 100644 index bc5f923aff..0000000000 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TransactionHistoryAdapter.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.tangem.tap.features.wallet.ui.wallet.saltPay.rv - -import android.graphics.PorterDuff -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.tangem.tap.common.extensions.getColor -import com.tangem.tap.common.extensions.setDrawable -import com.tangem.tap.common.extensions.show -import com.tangem.tap.common.extensions.toFormattedCurrencyString -import com.tangem.tap.features.wallet.models.PendingTransactionType -import com.tangem.tap.features.wallet.ui.wallet.saltPay.HistoryTransactionData -import com.tangem.wallet.R -import com.tangem.wallet.databinding.ItemSaltPayTxHistoryBinding - -/** -[REDACTED_AUTHOR] - */ -internal class TransactionHistoryAdapter : ListAdapter(DiffUtilCallback) { - - override fun getItemId(position: Int): Long { - return if (currentList.isEmpty()) 0 - else currentList[position].transactionData.hash.hashCode().toLong() - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionItemVH { - val inflater = LayoutInflater.from(parent.context) - val layout = ItemSaltPayTxHistoryBinding.inflate(inflater, parent, false) - return TransactionItemVH(layout) - } - - override fun onBindViewHolder(holder: TransactionItemVH, position: Int) { - holder.bind(currentList[position]) - } - - object DiffUtilCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame( - oldItem: HistoryTransactionData, - newItem: HistoryTransactionData, - ) = oldItem == newItem - - override fun areItemsTheSame( - oldItem: HistoryTransactionData, - newItem: HistoryTransactionData, - ) = oldItem == newItem - } -} - -internal class TransactionItemVH( - private val binding: ItemSaltPayTxHistoryBinding, -) : RecyclerView.ViewHolder(binding.root) { - - fun bind(data: HistoryTransactionData) = with(binding) { - setupImage(data) - setupTitle(data) - setupSubtitle(data) - setupBalance(data) - } - - private fun setupImage(data: HistoryTransactionData) = with(binding) { - val drawable = when (data.getTransactionType()) { - PendingTransactionType.Incoming -> R.drawable.ic_tx_incoming - PendingTransactionType.Outgoing -> R.drawable.ic_tx_outgoing - PendingTransactionType.Unknown -> null - } - drawable?.let { imvTx.setDrawable(it) } - - if (data.isInProgress()) { - imvTx.setColorFilter(imvTx.getColor(R.color.icon_attention), PorterDuff.Mode.MULTIPLY) - } else { - imvTx.clearColorFilter() - } - } - - private fun setupTitle(data: HistoryTransactionData) = with(binding) { - val hash = data.transactionData.hash ?: return@with - - val formattedHash = "${hash.substring(0..5)}...${hash.substring(hash.length - 4)}" - tvTxHash.text = formattedHash - } - - private fun setupSubtitle(data: HistoryTransactionData) = with(binding) { - val inProgress = data.isInProgress() - tvTxStatus.show(inProgress) - tvTxTime.show(!inProgress) - - val time = data.transactionData.date?.timeInMillis.toString() ?: "none" - tvTxTime.text = time - } - - private fun setupBalance(data: HistoryTransactionData) = with(binding) { - val sign = when (data.getTransactionType()) { - PendingTransactionType.Incoming -> "+" - PendingTransactionType.Outgoing -> "-" - PendingTransactionType.Unknown -> "" - } - val amount = data.transactionData.amount - tvTxAmountSign.text = sign - tvTxAmountValue.text = amount.value?.toFormattedCurrencyString(8, amount.currencySymbol) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt new file mode 100644 index 0000000000..60e9d1dfd7 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/saltPay/rv/TxHistoryAdapter.kt @@ -0,0 +1,112 @@ +package com.tangem.tap.features.wallet.ui.wallet.saltPay.rv + +import android.graphics.PorterDuff +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.tangem.tap.common.extensions.getColor +import com.tangem.tap.common.extensions.setDrawable +import com.tangem.tap.common.extensions.show +import com.tangem.tap.features.wallet.models.PendingTransactionType +import com.tangem.wallet.R +import com.tangem.wallet.databinding.ItemSaltPayTxHistoryBinding +import com.tangem.wallet.databinding.ItemSaltPayTxHistoryDateBinding + +/** +[REDACTED_AUTHOR] + */ +internal class TxHistoryAdapter : ListAdapter(DiffUtilCallback) { + + override fun getItemId(position: Int): Long { + return if (currentList.isEmpty()) 0L + else currentList[position].itemId + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseTxHistoryVH { + val inflater = LayoutInflater.from(parent.context) + + return when (viewType) { + 0 -> { + val layout = ItemSaltPayTxHistoryDateBinding.inflate(inflater, parent, false) + DateItemVH(layout) + } + 1 -> { + val layout = ItemSaltPayTxHistoryBinding.inflate(inflater, parent, false) + TransactionItemVH(layout) + } + else -> throw UnsupportedOperationException() + } + } + + override fun getItemViewType(position: Int): Int = currentList[position].viewType + + override fun onBindViewHolder(holder: BaseTxHistoryVH, position: Int) { + holder.bind(currentList[position]) + } + + private object DiffUtilCallback : DiffUtil.ItemCallback() { + override fun areContentsTheSame(oldItem: HistoryItemData, newItem: HistoryItemData) = oldItem == newItem + override fun areItemsTheSame(oldItem: HistoryItemData, newItem: HistoryItemData) = oldItem == newItem + } +} + +internal abstract class BaseTxHistoryVH(layout: View) : RecyclerView.ViewHolder(layout) { + abstract fun bind(data: HistoryItemData) +} + +private class DateItemVH( + private val binding: ItemSaltPayTxHistoryDateBinding, +) : BaseTxHistoryVH(binding.root) { + + override fun bind(data: HistoryItemData) = with(binding) { + val vhData = (data as? HistoryItemData.Date)?.date ?: return + + tvTitleDate.text = vhData + } +} + +private class TransactionItemVH( + private val binding: ItemSaltPayTxHistoryBinding, +) : BaseTxHistoryVH(binding.root) { + + override fun bind(data: HistoryItemData) { + val vhData = (data as? HistoryItemData.TransactionData)?.data ?: return + setupImage(vhData) + setupTitle(vhData) + setupSubtitle(vhData) + setupBalance(vhData) + } + + private fun setupImage(data: HistoryTransactionData) = with(binding) { + val drawable = when (data.transactionType) { + PendingTransactionType.Incoming -> R.drawable.ic_tx_incoming + PendingTransactionType.Outgoing -> R.drawable.ic_tx_outgoing + PendingTransactionType.Unknown -> null + } + drawable?.let { imvTx.setDrawable(it) } + + if (data.isInProgress) { + imvTx.setColorFilter(imvTx.getColor(R.color.icon_attention), PorterDuff.Mode.SRC_ATOP) + } else { + imvTx.clearColorFilter() + } + } + + private fun setupTitle(data: HistoryTransactionData) = with(binding) { + tvTxHash.text = data.hash + } + + private fun setupSubtitle(data: HistoryTransactionData) = with(binding) { + tvTxStatus.show(data.isInProgress) + tvTxTime.show(!data.isInProgress) + tvTxTime.text = data.time + } + + private fun setupBalance(data: HistoryTransactionData) = with(binding) { + tvTxAmountSign.text = data.txSign + tvTxAmountValue.text = data.amountValue + } +} \ No newline at end of file