Merge pull request #51 from zcash/feature/transaction-history

Feature/transaction history
This commit is contained in:
Kevin Gorham 2020-01-04 16:20:25 -05:00 committed by GitHub
commit b2908989aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 219 additions and 3 deletions

View File

@ -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

View File

@ -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" />

View File

@ -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))
}

View File

@ -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())
}
}

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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>

View File

@ -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>