Merge pull request #51 from zcash/feature/transaction-history
Feature/transaction history
This commit is contained in:
commit
b2908989aa
|
@ -98,6 +98,10 @@ dependencies {
|
|||
implementation Deps.AndroidX.Lifecycle.LIFECYCLE_RUNTIME_KTX
|
||||
implementation Deps.AndroidX.Navigation.FRAGMENT_KTX
|
||||
implementation Deps.AndroidX.Navigation.UI_KTX
|
||||
implementation "androidx.room:room-ktx:2.2.3"
|
||||
implementation "androidx.paging:paging-runtime-ktx:2.1.1"
|
||||
implementation 'com.google.guava:guava:27.0.1-android'
|
||||
kapt "androidx.room:room-compiler:2.2.3"
|
||||
|
||||
// Google
|
||||
implementation Deps.Google.MATERIAL
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/ZcashTheme">
|
||||
<activity android:name=".ui.MainActivity">
|
||||
<activity android:name=".ui.MainActivity" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package cash.z.ecc.android.ui.detail
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.paging.PagedListAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import cash.z.ecc.android.R
|
||||
import cash.z.wallet.sdk.entity.ConfirmedTransaction
|
||||
|
||||
class TransactionAdapter<T : ConfirmedTransaction> :
|
||||
PagedListAdapter<T, TransactionViewHolder<T>>(
|
||||
object : DiffUtil.ItemCallback<T>() {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: T,
|
||||
newItem: T
|
||||
) = oldItem.minedHeight == newItem.minedHeight
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: T,
|
||||
newItem: T
|
||||
) = oldItem.equals(newItem)
|
||||
}
|
||||
) {
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
) = TransactionViewHolder<T>(
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.item_transaction, parent, false)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(
|
||||
holder: TransactionViewHolder<T>,
|
||||
position: Int
|
||||
) = holder.bindTo(getItem(position))
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package cash.z.ecc.android.ui.detail
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import cash.z.ecc.android.R
|
||||
import cash.z.ecc.android.ext.toAppColor
|
||||
import cash.z.wallet.sdk.entity.ConfirmedTransaction
|
||||
import cash.z.wallet.sdk.ext.abbreviatedAddress
|
||||
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
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 formatter = SimpleDateFormat("M/d h:mma", Locale.getDefault())
|
||||
|
||||
fun bindTo(transaction: T?) {
|
||||
var lineOne: String = ""
|
||||
var lineTwo: String = ""
|
||||
var amount: String = ""
|
||||
var amountColor: Int = 0
|
||||
var indicatorColor: Int = 0
|
||||
|
||||
transaction?.apply {
|
||||
amount = value.convertZatoshiToZecString()
|
||||
// TODO: these might be good extension functions
|
||||
val timestamp = formatter.format(blockTimeInSeconds * 1000L)
|
||||
val isMined = blockTimeInSeconds != 0L
|
||||
when {
|
||||
!toAddress.isNullOrEmpty() -> {
|
||||
lineOne = "You paid ${toAddress?.abbreviatedAddress()}"
|
||||
lineTwo = if (isMined) "Sent $timestamp" else "Pending confirmation"
|
||||
amount = "- $amount"
|
||||
amountColor = R.color.zcashRed
|
||||
indicatorColor = R.color.colorPrimary
|
||||
}
|
||||
raw == null || raw?.isEmpty() == true -> {
|
||||
lineOne = "Unknown paid you"
|
||||
lineTwo = "Received $timestamp"
|
||||
amount = "+ $amount"
|
||||
amountColor = R.color.zcashGreen
|
||||
indicatorColor = R.color.zcashGreen
|
||||
}
|
||||
else -> {
|
||||
lineOne = "Unknown"
|
||||
lineTwo = "Unknown"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
topText.text = lineOne
|
||||
bottomText.text = lineTwo
|
||||
amountText.text = amount
|
||||
amountText.setTextColor(amountColor.toAppColor())
|
||||
indicator.setBackgroundColor(indicatorColor.toAppColor())
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.paging.PagedList
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import cash.z.ecc.android.R
|
||||
import cash.z.ecc.android.databinding.FragmentDetailBinding
|
||||
import cash.z.ecc.android.di.annotation.FragmentScope
|
||||
|
@ -11,13 +13,19 @@ import cash.z.ecc.android.ext.onClick
|
|||
import cash.z.ecc.android.ext.onClickNavUp
|
||||
import cash.z.ecc.android.feedback.FeedbackFile
|
||||
import cash.z.ecc.android.ui.base.BaseFragment
|
||||
import cash.z.wallet.sdk.entity.ConfirmedTransaction
|
||||
import cash.z.wallet.sdk.ext.twig
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import okio.Okio
|
||||
|
||||
|
||||
class WalletDetailFragment : BaseFragment<FragmentDetailBinding>() {
|
||||
|
||||
private lateinit var adapter: TransactionAdapter<ConfirmedTransaction>
|
||||
|
||||
override fun inflate(inflater: LayoutInflater): FragmentDetailBinding =
|
||||
FragmentDetailBinding.inflate(inflater)
|
||||
|
||||
|
@ -36,10 +44,23 @@ class WalletDetailFragment : BaseFragment<FragmentDetailBinding>() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun onSendFeedback() {
|
||||
mainActivity?.showSnackbar("Feedback not yet implemented.")
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
initTransactionUI()
|
||||
}
|
||||
|
||||
private fun initTransactionUI() {
|
||||
binding.recyclerTransactions.layoutManager =
|
||||
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
|
||||
adapter = TransactionAdapter()
|
||||
resumedScope.launch {
|
||||
mainActivity?.synchronizer?.clearedTransactions?.collect { onTransactionsUpdated(it) }
|
||||
}
|
||||
binding.recyclerTransactions.adapter = adapter
|
||||
}
|
||||
|
||||
private fun onSendFeedback() {
|
||||
mainActivity?.showSnackbar("Feedback not yet implemented.")
|
||||
}
|
||||
|
||||
private fun onViewLogs() {
|
||||
|
@ -63,6 +84,11 @@ class WalletDetailFragment : BaseFragment<FragmentDetailBinding>() {
|
|||
mainActivity?.navController?.navigate(R.id.action_nav_detail_to_backup_wallet)
|
||||
}
|
||||
|
||||
private fun onTransactionsUpdated(transactions: PagedList<ConfirmedTransaction>) {
|
||||
twig("got a new paged list of transactions")
|
||||
adapter.submitList(transactions)
|
||||
}
|
||||
|
||||
private fun loadLogFileAsText(): String? {
|
||||
val feedbackFile: FeedbackFile =
|
||||
mainActivity?.feedbackCoordinator?.findObserver() ?: return null
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/zcashGreen" android:pathData="M20,5.41L18.59,4 7,15.59V9H5v10h10v-2H8.41z"/>
|
||||
</vector>
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:background="@drawable/background_home">
|
||||
|
||||
<!-- -->
|
||||
|
@ -76,6 +77,21 @@
|
|||
app:layout_constraintEnd_toEndOf="@id/guideline_keyline_end"
|
||||
app:layout_constraintTop_toTopOf="@id/back_button" />
|
||||
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_transactions"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="12dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/guideline_bottom_buttons"
|
||||
app:layout_constraintStart_toStartOf="@id/guideline_keyline_start"
|
||||
app:layout_constraintEnd_toEndOf="@id/guideline_keyline_end"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_backup"
|
||||
tools:itemCount="15"
|
||||
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_transaction"
|
||||
tools:orientation="vertical" />
|
||||
|
||||
<View
|
||||
android:id="@+id/text_banner_message"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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:id="@+id/container_transaction"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background_banner"
|
||||
android:elevation="1dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<View
|
||||
android:id="@+id/indicator"
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:background="@color/zcashGreen"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transaction_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_transaction_bottom"
|
||||
app:layout_constraintStart_toEndOf="@id/indicator"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="8/23 3:24pm" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transaction_bottom"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:paddingEnd="16dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintEnd_toStartOf="@id/text_transaction_amount"
|
||||
app:layout_constraintStart_toStartOf="@id/text_transaction_top"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_transaction_top"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="funds received" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transaction_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="+ 4.244"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -38,6 +38,9 @@
|
|||
<color name="zcashBlack_dark">#171717</color>
|
||||
<color name="zcashBlack_0">#00000000</color>
|
||||
|
||||
<color name="zcashGreen">#66BB6A</color>
|
||||
<color name="zcashRed">#BB666A</color>
|
||||
|
||||
<!-- yellows -->
|
||||
<color name="zcashYellow_light">#FFD649</color>
|
||||
<color name="zcashYellow">#FFB727</color>
|
||||
|
|
Loading…
Reference in New Issue