Updated on 2026-08-14

This commit is contained in:
Tangem 2020-09-07 17:27:33 +03:00
parent 00e47d3988
commit 7bce07d944
12 changed files with 228 additions and 16 deletions

View file

@ -6,7 +6,6 @@ import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
import com.tangem.blockchain.common.Blockchain
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
@ -34,16 +33,16 @@ fun String.toQrCode(): Bitmap {
return bmp
}
fun BigDecimal.toFormattedString(blockchain: Blockchain): String {
fun BigDecimal.toFormattedString(decimals: Int): String {
val symbols = DecimalFormatSymbols(Locale.US)
symbols.decimalSeparator = '.'
val df = DecimalFormat()
df.decimalFormatSymbols = symbols
df.maximumFractionDigits = blockchain.decimals()
df.maximumFractionDigits = decimals
df.minimumFractionDigits = 0
df.isGroupingUsed = false
val bd = BigDecimal(unscaledValue(), scale())
bd.setScale(blockchain.decimals(), BigDecimal.ROUND_DOWN)
bd.setScale(decimals, BigDecimal.ROUND_DOWN)
return df.format(bd)
}

View file

@ -24,6 +24,10 @@ fun Fragment.getDrawable(@DrawableRes drawableResId: Int): Drawable? {
return ContextCompat.getDrawable(requireContext(), drawableResId)
}
fun Context.getDrawableCompat(@DrawableRes drawableResId: Int): Drawable? {
return ContextCompat.getDrawable(this, drawableResId)
}
fun View.show(show: Boolean) {
if (show) this.visibility = View.VISIBLE else this.visibility = View.GONE
}

View file

@ -0,0 +1,36 @@
package com.tangem.tap.features.wallet.models
import com.tangem.blockchain.common.TransactionData
import com.tangem.tap.common.extensions.toFormattedString
data class PendingTransaction(
val address: String,
val amount: String,
val currency: String,
val type: PendingTransactionType
)
enum class PendingTransactionType { Incoming, Outcoming }
fun TransactionData.toPendingTransaction(walletAddress: String): PendingTransaction {
val type: PendingTransactionType = if (this.sourceAddress == walletAddress) {
PendingTransactionType.Outcoming
} else {
PendingTransactionType.Incoming
}
val address = if (this.sourceAddress == walletAddress) {
this.destinationAddress
} else {
this.sourceAddress
}
return PendingTransaction(
address,
this.amount.value?.toFormattedString(amount.decimals) ?: "?",
this.amount.currencySymbol,
type
)
}
fun List<TransactionData>.toPendingTransactions(walletAddress: String): List<PendingTransaction>{
return this.map { it.toPendingTransaction(walletAddress) }
}

View file

@ -7,6 +7,7 @@ import com.tangem.tap.common.extensions.toFiatString
import com.tangem.tap.common.extensions.toFormattedString
import com.tangem.tap.common.extensions.toQrCode
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.wallet.models.toPendingTransactions
import com.tangem.tap.features.wallet.ui.BalanceStatus
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import com.tangem.tap.features.wallet.ui.TokenData
@ -37,7 +38,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
} else {
AddressData(wallet.address, wallet.shareUrl, wallet.exploreUrl)
}
val currentArtworkId = state.globalState.scanNoteResponse?.verifyResponse?.artworkInfo?.id
val currentArtworkId = state.globalState.scanNoteResponse?.verifyResponse?.artworkInfo?.id
val cardImage = if (newState.cardImage?.artworkId == currentArtworkId) {
newState.cardImage
} else {
@ -61,7 +62,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
val tokenFiatRate = state.globalState.fiatRates.getRateForCryptoCurrency(token.currencySymbol)
val tokenFiatAmount = tokenFiatRate?.let { token.value?.toFiatString(it) }
TokenData(
token.value?.toFormattedString(action.wallet.blockchain) ?: "",
token.value?.toFormattedString(token.decimals) ?: "",
token.currencySymbol, tokenFiatAmount)
} else {
null
@ -70,16 +71,20 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
val fiatRate = state.globalState.fiatRates.getRateForCryptoCurrency(action.wallet.blockchain.currency)
val fiatAmount = fiatRate?.let { amount?.toFiatString(it) }
val pendingTransactions = action.wallet.transactions
.toPendingTransactions(action.wallet.address)
val sendButtonEnabled = amount?.isZero() == false || token?.value?.isZero() == false
newState = newState.copy(
state = ProgressState.Done, wallet = action.wallet,
currencyData = BalanceWidgetData(
BalanceStatus.VerifiedOnline, action.wallet.blockchain.fullName,
currencySymbol = action.wallet.blockchain.currency,
amount?.toFormattedString(action.wallet.blockchain),
amount?.toFormattedString(action.wallet.blockchain.decimals()),
token = tokenData,
fiatAmount = fiatAmount
),
pendingTransactions = pendingTransactions,
mainButton = WalletMainButton.SendButton(sendButtonEnabled)
)
}

View file

@ -3,6 +3,7 @@ package com.tangem.tap.features.wallet.redux
import android.graphics.Bitmap
import com.tangem.blockchain.common.Wallet
import com.tangem.tap.common.entities.Button
import com.tangem.tap.features.wallet.models.PendingTransaction
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
import org.rekotlin.StateType
@ -10,6 +11,7 @@ data class WalletState(
val state: ProgressState = ProgressState.Done,
val cardImage: Artwork? = null,
val wallet: Wallet? = null,
val pendingTransactions: List<PendingTransaction> = emptyList(),
val addressData: AddressData? = null,
val currencyData: BalanceWidgetData = BalanceWidgetData(),
val payIdData: PayIdData = PayIdData(),

View file

@ -0,0 +1,62 @@
package com.tangem.tap.features.wallet.ui
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.getDrawableCompat
import com.tangem.tap.features.wallet.models.PendingTransaction
import com.tangem.tap.features.wallet.models.PendingTransactionType
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.layout_pending_transaction.view.*
class PendingTransactionsAdapter
: ListAdapter<PendingTransaction, PendingTransactionsAdapter.TransactionsViewHolder>(DiffUtilCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionsViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.layout_pending_transaction, parent, false)
return TransactionsViewHolder(layout)
}
override fun onBindViewHolder(holder: TransactionsViewHolder, position: Int) {
holder.bind(currentList[position])
}
object DiffUtilCallback : DiffUtil.ItemCallback<PendingTransaction>() {
override fun areContentsTheSame(
oldItem: PendingTransaction, newItem: PendingTransaction
) = oldItem == newItem
override fun areItemsTheSame(
oldItem: PendingTransaction, newItem: PendingTransaction
) = oldItem == newItem
}
class TransactionsViewHolder(val view: View) :
RecyclerView.ViewHolder(view) {
fun bind(transaction: PendingTransaction) {
val transactionDescriptionRes = when (transaction.type) {
PendingTransactionType.Incoming -> R.string.wallet_pending_transaction_incoming
PendingTransactionType.Outcoming -> R.string.wallet_pending_transaction_outcoming
}
val image = when (transaction.type) {
PendingTransactionType.Incoming -> R.drawable.ic_arrow_down
PendingTransactionType.Outcoming -> R.drawable.ic_arrow_right
}
view.tv_pending_transaction.text = view.context.getString(
transactionDescriptionRes, transaction.amount, transaction.currency
)
view.tv_pending_transaction_address.text = transaction.address
view.iv_pending_transaction.setImageDrawable(view.context.getDrawableCompat(image))
}
}
}

View file

@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.transition.TransitionInflater
import com.tangem.tap.common.extensions.getDrawable
import com.tangem.tap.common.extensions.hide
@ -26,6 +27,9 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
private var qrDialog: QrDialog? = null
private var payIdDialog: PayIdDialog? = null
private lateinit var viewAdapter: PendingTransactionsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
@ -55,7 +59,6 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
toolbar.setNavigationOnClickListener {
store.dispatch(NavigationAction.PopBackTo())
}
@ -63,8 +66,17 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
btn_scan.setOnClickListener {
store.dispatch(WalletAction.Scan)
}
setupTransactionsRecyclerView()
}
private fun setupTransactionsRecyclerView() {
viewAdapter = PendingTransactionsAdapter()
rv_pending_transaction.layoutManager = LinearLayoutManager(context)
rv_pending_transaction.adapter = viewAdapter
}
override fun newState(state: WalletState) {
if (activity == null) return
@ -76,6 +88,8 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
setupAddressCard(state)
setupCardImage(state.cardImage?.artwork)
viewAdapter.submitList(state.pendingTransactions)
if (state.qrCode != null && state.addressData?.shareUrl != null) {
if (qrDialog == null) qrDialog = QrDialog(requireContext())
qrDialog?.showQr(state.qrCode, state.addressData.shareUrl)