155 lines
8.0 KiB
Kotlin
155 lines
8.0 KiB
Kotlin
package cash.z.ecc.android.ui.history
|
|
|
|
import android.graphics.drawable.Drawable
|
|
import android.view.View
|
|
import android.widget.ImageView
|
|
import android.widget.TextView
|
|
import androidx.annotation.StringRes
|
|
import androidx.lifecycle.lifecycleScope
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
import cash.z.ecc.android.R
|
|
import cash.z.ecc.android.ext.WalletZecFormmatter
|
|
import cash.z.ecc.android.ext.goneIf
|
|
import cash.z.ecc.android.ext.locale
|
|
import cash.z.ecc.android.ext.toAppColor
|
|
import cash.z.ecc.android.ext.toAppInt
|
|
import cash.z.ecc.android.ext.toColoredSpan
|
|
import cash.z.ecc.android.sdk.db.entity.ConfirmedTransaction
|
|
import cash.z.ecc.android.sdk.ext.ZcashSdk
|
|
import cash.z.ecc.android.sdk.ext.isShielded
|
|
import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress
|
|
import cash.z.ecc.android.ui.MainActivity
|
|
import cash.z.ecc.android.ui.util.toUtf8Memo
|
|
import kotlinx.coroutines.launch
|
|
import java.text.SimpleDateFormat
|
|
|
|
class TransactionViewHolder<T : ConfirmedTransaction>(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
|
|
|
private val indicator = itemView.findViewById<View>(R.id.indicator)
|
|
private val amountText = itemView.findViewById<TextView>(R.id.text_transaction_amount)
|
|
private val topText = itemView.findViewById<TextView>(R.id.text_transaction_top)
|
|
private val bottomText = itemView.findViewById<TextView>(R.id.text_transaction_bottom)
|
|
private val transactionArrow = itemView.findViewById<ImageView>(R.id.image_transaction_arrow)
|
|
private val formatter = SimpleDateFormat(itemView.context.getString(R.string.format_transaction_history_date_time), itemView.context.locale())
|
|
private val iconMemo = itemView.findViewById<ImageView>(R.id.image_memo)
|
|
|
|
fun bindTo(transaction: T?) {
|
|
val mainActivity = itemView.context as MainActivity
|
|
mainActivity.lifecycleScope.launch {
|
|
// update view
|
|
var lineOne: CharSequence = ""
|
|
var lineTwo = ""
|
|
var amountZec = ""
|
|
var amountDisplay = ""
|
|
var amountColor: Int = R.color.text_light
|
|
var lineOneColor: Int = R.color.text_light
|
|
var lineTwoColor: Int = R.color.text_light_dimmed
|
|
var indicatorBackground: Int = R.color.text_light_dimmed
|
|
var arrowRotation: Int = R.integer.transaction_arrow_rotation_send
|
|
var arrowBackgroundTint: Int = R.color.text_light
|
|
var isLineOneSpanned = false
|
|
|
|
transaction?.apply {
|
|
itemView.setOnClickListener {
|
|
onTransactionClicked(this)
|
|
}
|
|
itemView.setOnLongClickListener {
|
|
onTransactionLongPressed(this)
|
|
true
|
|
}
|
|
amountZec = WalletZecFormmatter.toZecStringShort(value)
|
|
// TODO: these might be good extension functions
|
|
val timestamp = formatter.format(blockTimeInSeconds * 1000L)
|
|
val isMined = blockTimeInSeconds != 0L
|
|
when {
|
|
!toAddress.isNullOrEmpty() -> {
|
|
indicatorBackground = if (isMined) R.color.zcashRed else R.color.zcashGray
|
|
lineOne = "${if (isMined) str(R.string.transaction_address_you_paid) else str(R.string.transaction_address_paying)} ${toAddress?.toAbbreviatedAddress()}"
|
|
lineTwo = if (isMined) "${str(R.string.transaction_status_sent)} $timestamp" else str(R.string.transaction_status_pending)
|
|
// TODO: this logic works but is sloppy. Find a more robust solution to displaying information about expiration (such as expires in 1 block, etc). Then if it is way beyond expired, remove it entirely. Perhaps give the user a button for that (swipe to dismiss?)
|
|
if (!isMined && (expiryHeight != null) && (expiryHeight!! < mainActivity.latestHeight ?: -1)) lineTwo = str(R.string.transaction_status_expired)
|
|
amountDisplay = "- $amountZec"
|
|
if (isMined) {
|
|
arrowRotation = R.integer.transaction_arrow_rotation_send
|
|
amountColor = R.color.transaction_sent
|
|
if (toAddress.isShielded()) {
|
|
lineOneColor = R.color.zcashYellow
|
|
} else {
|
|
toAddress?.toAbbreviatedAddress()?.let {
|
|
lineOne = lineOne.toColoredSpan(R.color.zcashBlueDark, it)
|
|
}
|
|
}
|
|
} else {
|
|
arrowRotation = R.integer.transaction_arrow_rotation_pending
|
|
}
|
|
}
|
|
toAddress.isNullOrEmpty() && value > 0L && minedHeight > 0 -> {
|
|
indicatorBackground = R.color.zcashGreen
|
|
val senderAddress = mainActivity.getSender(transaction)
|
|
lineOne = "${str(R.string.transaction_received_from)} $senderAddress"
|
|
lineTwo = "${str(R.string.transaction_received)} $timestamp"
|
|
amountDisplay = "+ $amountZec"
|
|
if (senderAddress.isShielded()) {
|
|
amountColor = R.color.zcashYellow
|
|
lineOneColor = R.color.zcashYellow
|
|
} else {
|
|
senderAddress.toAbbreviatedAddress().let {
|
|
lineOne = if (senderAddress.equals(str(R.string.unknown), true)) {
|
|
lineOne.toColoredSpan(R.color.zcashYellow, it)
|
|
} else {
|
|
lineOne.toColoredSpan(R.color.zcashBlueDark, it)
|
|
}
|
|
}
|
|
}
|
|
arrowRotation = R.integer.transaction_arrow_rotation_received
|
|
}
|
|
else -> {
|
|
lineOne = str(R.string.unknown)
|
|
lineTwo = str(R.string.unknown)
|
|
amountDisplay = amountZec
|
|
amountColor = R.color.text_light
|
|
arrowRotation = R.integer.transaction_arrow_rotation_received
|
|
}
|
|
}
|
|
// sanitize amount
|
|
if (value < ZcashSdk.MINERS_FEE_ZATOSHI * 10) amountDisplay = "< 0.0001"
|
|
else if (amountZec.length > 10) { // 10 allows 3 digits to the left and 6 to the right of the decimal
|
|
amountDisplay = str(R.string.transaction_instruction_tap)
|
|
}
|
|
}
|
|
|
|
topText.text = lineOne
|
|
bottomText.text = lineTwo
|
|
amountText.text = amountDisplay
|
|
amountText.setTextColor(amountColor.toAppColor())
|
|
if (!isLineOneSpanned) {
|
|
topText.setTextColor(lineOneColor.toAppColor())
|
|
}
|
|
bottomText.setTextColor(lineTwoColor.toAppColor())
|
|
indicator.setBackgroundColor(indicatorBackground.toAppColor())
|
|
transactionArrow.setColorFilter(arrowBackgroundTint.toAppColor())
|
|
transactionArrow.rotation = arrowRotation.toAppInt().toFloat()
|
|
|
|
var bottomTextRightDrawable: Drawable? = null
|
|
iconMemo.goneIf(!transaction?.memo.toUtf8Memo().isNotEmpty())
|
|
bottomText.setCompoundDrawablesWithIntrinsicBounds(null, null, bottomTextRightDrawable, null)
|
|
}
|
|
}
|
|
|
|
private fun onTransactionClicked(transaction: ConfirmedTransaction) {
|
|
(itemView.context as MainActivity).apply {
|
|
historyViewModel.selectedTransaction.value = transaction
|
|
safeNavigate(R.id.action_nav_history_to_nav_transaction)
|
|
}
|
|
}
|
|
|
|
private fun onTransactionLongPressed(transaction: ConfirmedTransaction) {
|
|
val mainActivity = itemView.context as MainActivity
|
|
transaction.toAddress?.let {
|
|
mainActivity.copyText(it, "Transaction Address")
|
|
}
|
|
}
|
|
|
|
private inline fun str(@StringRes resourceId: Int) = itemView.context.getString(resourceId)
|
|
}
|