summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorTorsten Grote <t@grobox.de>2020-01-02 10:00:48 -0300
committerTorsten Grote <t@grobox.de>2020-01-02 10:00:48 -0300
commit208d7ab1872cc7f5183a553d590ec4debc911292 (patch)
treeb3b67f07f391a3ed686f8b872373b2f07b27459f /app
parent1ec44435ab0ab098a04b3f4ee9f2599d99535c41 (diff)
downloadwallet-android-208d7ab1872cc7f5183a553d590ec4debc911292.tar.gz
wallet-android-208d7ab1872cc7f5183a553d590ec4debc911292.tar.bz2
wallet-android-208d7ab1872cc7f5183a553d590ec4debc911292.zip
Hide detailed history events by default
Also implement history changes after latest feedback
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle5
-rw-r--r--app/src/main/java/net/taler/wallet/WalletViewModel.kt32
-rw-r--r--app/src/main/java/net/taler/wallet/history/HistoryEvent.kt7
-rw-r--r--app/src/main/java/net/taler/wallet/history/WalletHistory.kt58
-rw-r--r--app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt15
-rw-r--r--app/src/main/res/layout/fragment_show_history.xml39
-rw-r--r--app/src/main/res/layout/history_payment_sent.xml11
-rw-r--r--app/src/main/res/layout/history_row.xml2
-rw-r--r--app/src/main/res/layout/history_withdrawn.xml25
-rw-r--r--app/src/main/res/menu/history.xml17
-rw-r--r--app/src/main/res/values/strings.xml6
-rw-r--r--app/src/main/res/values/styles.xml5
12 files changed, 146 insertions, 76 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 7e0f2ce..c40ddef 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -45,14 +45,15 @@ dependencies {
implementation project(":akono")
implementation 'com.google.guava:guava:28.0-android'
- def nav_version = "2.2.0-rc03"
+ def nav_version = "2.2.0-rc04"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
// ViewModel and LiveData
- def lifecycle_version = "2.1.0"
+ def lifecycle_version = "2.2.0-rc03"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
+ implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// QR codes
implementation 'com.google.zxing:core:3.4.0'
diff --git a/app/src/main/java/net/taler/wallet/WalletViewModel.kt b/app/src/main/java/net/taler/wallet/WalletViewModel.kt
index f556ff3..f932cff 100644
--- a/app/src/main/java/net/taler/wallet/WalletViewModel.kt
+++ b/app/src/main/java/net/taler/wallet/WalletViewModel.kt
@@ -18,11 +18,15 @@ package net.taler.wallet
import android.app.Application
import android.util.Log
-import androidx.lifecycle.AndroidViewModel
-import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.*
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.fasterxml.jackson.module.kotlin.readValue
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.onCompletion
+import kotlinx.coroutines.flow.onStart
import net.taler.wallet.backend.WalletBackendApi
import net.taler.wallet.history.History
import org.json.JSONObject
@@ -61,6 +65,7 @@ open class WithdrawStatus {
val tosText: String,
val tosEtag: String
) : WithdrawStatus()
+
class Success : WithdrawStatus()
data class ReceivedDetails(
val talerWithdrawUri: String,
@@ -81,6 +86,7 @@ open class PendingOperations(
)
+@Suppress("EXPERIMENTAL_API_USAGE")
class WalletViewModel(val app: Application) : AndroidViewModel(app) {
private var initialized = false
@@ -104,6 +110,18 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
value = PendingOperations(listOf())
}
+ private val mHistoryProgress = MutableLiveData<Boolean>()
+ val historyProgress: LiveData<Boolean> = mHistoryProgress
+
+ val historyShowAll = MutableLiveData<Boolean>()
+
+ val history: LiveData<History> = historyShowAll.switchMap { showAll ->
+ loadHistory(showAll)
+ .onStart { mHistoryProgress.postValue(true) }
+ .onCompletion { mHistoryProgress.postValue(false) }
+ .asLiveData(Dispatchers.IO)
+ }
+
private var activeGetBalance = 0
private var activeGetPending = 0
@@ -188,15 +206,21 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) {
}
}
- fun getHistory(cb: (r: History) -> Unit) {
+ private fun loadHistory(showAll: Boolean) = callbackFlow {
+ mHistoryProgress.postValue(true)
walletBackendApi.sendRequest("getHistory", null) { isError, result ->
if (isError) {
// TODO show error message in [WalletHistory] fragment
+ close()
return@sendRequest
}
val history: History = mapper.readValue(result.getString("history"))
- cb(history)
+ history.reverse() // show latest first
+ mHistoryProgress.postValue(false)
+ offer(if (showAll) history else history.filter { it.showToUser } as History)
+ close()
}
+ awaitClose()
}
fun withdrawTestkudos() {
diff --git a/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt b/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt
index 31473f6..b21147a 100644
--- a/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt
+++ b/app/src/main/java/net/taler/wallet/history/HistoryEvent.kt
@@ -80,7 +80,7 @@ class ReserveShortInfo(
val reserveCreationDetail: ReserveCreationDetail
)
-class History : ArrayList<HistoryEvent>()
+typealias History = ArrayList<HistoryEvent>
@JsonTypeInfo(
use = NAME,
@@ -109,7 +109,8 @@ abstract class HistoryEvent(
@get:StringRes
open val title: Int = 0,
@get:DrawableRes
- open val icon: Int = R.drawable.ic_account_balance
+ open val icon: Int = R.drawable.ic_account_balance,
+ open val showToUser: Boolean = false
)
@@ -178,6 +179,7 @@ class HistoryWithdrawnEvent(
override val layout = R.layout.history_withdrawn
override val title = R.string.history_event_withdrawn
override val icon = R.drawable.history_withdrawn
+ override val showToUser = true
}
@JsonTypeName("order-accepted")
@@ -232,6 +234,7 @@ class HistoryPaymentSentEvent(
override val layout = R.layout.history_payment_sent
override val title = R.string.history_event_payment_sent
override val icon = R.drawable.ic_cash_usd_outline
+ override val showToUser = true
}
@JsonTypeName("refreshed")
diff --git a/app/src/main/java/net/taler/wallet/history/WalletHistory.kt b/app/src/main/java/net/taler/wallet/history/WalletHistory.kt
index cdc90ae..0b2e214 100644
--- a/app/src/main/java/net/taler/wallet/history/WalletHistory.kt
+++ b/app/src/main/java/net/taler/wallet/history/WalletHistory.kt
@@ -19,11 +19,14 @@ package net.taler.wallet.history
import android.os.Bundle
import android.view.*
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProviders
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
+import kotlinx.android.synthetic.main.fragment_show_history.*
import net.taler.wallet.R
import net.taler.wallet.WalletViewModel
@@ -34,64 +37,65 @@ import net.taler.wallet.WalletViewModel
class WalletHistory : Fragment() {
lateinit var model: WalletViewModel
+ private lateinit var showAllItem: MenuItem
private val historyAdapter = WalletHistoryAdapter()
- lateinit var historyPlaceholder: View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
model = activity?.run {
- ViewModelProviders.of(this)[WalletViewModel::class.java]
+ ViewModelProvider(this)[WalletViewModel::class.java]
} ?: throw Exception("Invalid Activity")
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- activity?.menuInflater?.inflate(R.menu.history, menu)
+ inflater.inflate(R.menu.history, menu)
+ showAllItem = menu.findItem(R.id.show_all_history)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
+ R.id.show_all_history -> {
+ item.isChecked = !item.isChecked
+ model.historyShowAll.value = item.isChecked
+ true
+ }
R.id.reload_history -> {
- updateHistory()
+ model.historyShowAll.value = showAllItem.isChecked
true
}
else -> super.onOptionsItemSelected(item)
}
}
- private fun updateHistory() {
- model.getHistory {
- if (it.isEmpty()) {
- historyPlaceholder.visibility = View.VISIBLE
- }
- historyAdapter.update(it)
- }
- }
-
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- // Inflate the layout for this fragment
- val view = inflater.inflate(R.layout.fragment_show_history, container, false)
- val myLayoutManager = LinearLayoutManager(context).apply {
- reverseLayout = true // show latest events first
- }
- val myItemDecoration = DividerItemDecoration(context, myLayoutManager.orientation)
- view.findViewById<RecyclerView>(R.id.list_history).apply {
+ return inflater.inflate(R.layout.fragment_show_history, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ historyList.apply {
+ val myLayoutManager = LinearLayoutManager(context)
+ val myItemDecoration = DividerItemDecoration(context, myLayoutManager.orientation)
layoutManager = myLayoutManager
adapter = historyAdapter
addItemDecoration(myItemDecoration)
}
- historyPlaceholder = view.findViewById<View>(R.id.list_history_placeholder)
- historyPlaceholder.visibility = View.GONE
-
- updateHistory()
+ model.historyProgress.observe(this, Observer { show ->
+ historyProgressBar.visibility = if (show) VISIBLE else INVISIBLE
+ })
+ model.history.observe(this, Observer { history ->
+ historyEmptyState.visibility = if (history.isEmpty()) VISIBLE else INVISIBLE
+ historyAdapter.update(history)
+ })
- return view
+ // kicks off initial load, needs to be adapted if showAll state is ever saved
+ if (savedInstanceState == null) model.historyShowAll.value = false
}
companion object {
diff --git a/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt b/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt
index 14fc1e9..9d601e1 100644
--- a/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt
+++ b/app/src/main/java/net/taler/wallet/history/WalletHistoryAdapter.kt
@@ -64,7 +64,7 @@ internal class WalletHistoryAdapter(private var history: History = History()) :
internal abstract class HistoryEventViewHolder(protected val v: View) : ViewHolder(v) {
private val icon: ImageView = v.findViewById(R.id.icon)
- private val title: TextView = v.findViewById(R.id.title)
+ protected val title: TextView = v.findViewById(R.id.title)
private val time: TextView = v.findViewById(R.id.time)
@CallSuper
@@ -77,7 +77,15 @@ internal abstract class HistoryEventViewHolder(protected val v: View) : ViewHold
private fun getRelativeTime(timestamp: Long): CharSequence {
val now = System.currentTimeMillis()
- return getRelativeTimeSpanString(timestamp, now, MINUTE_IN_MILLIS, FORMAT_ABBREV_RELATIVE)
+ return if (now - timestamp > DAY_IN_MILLIS * 2) {
+ formatDateTime(
+ v.context,
+ timestamp,
+ FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or FORMAT_ABBREV_MONTH or FORMAT_NO_YEAR
+ )
+ } else {
+ getRelativeTimeSpanString(timestamp, now, MINUTE_IN_MILLIS, FORMAT_ABBREV_RELATIVE)
+ }
}
}
@@ -132,7 +140,8 @@ internal class HistoryPaymentSentViewHolder(v: View) : HistoryEventViewHolder(v)
super.bind(event)
event as HistoryPaymentSentEvent
- summary.text = event.orderShortInfo.summary
+ title.text = event.orderShortInfo.summary
+ summary.setText(event.title)
amountPaidWithFees.text = parseAmount(event.amountPaidWithFees).toString()
}
diff --git a/app/src/main/res/layout/fragment_show_history.xml b/app/src/main/res/layout/fragment_show_history.xml
index 6265a50..dc93889 100644
--- a/app/src/main/res/layout/fragment_show_history.xml
+++ b/app/src/main/res/layout/fragment_show_history.xml
@@ -1,28 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
-<androidx.core.widget.NestedScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <LinearLayout
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/historyList"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:scrollbars="vertical" />
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/list_history"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
+ <TextView
+ android:id="@+id/historyEmptyState"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/history_empty"
+ android:visibility="invisible"
+ tools:visibility="visible" />
- <TextView
- android:id="@+id/list_history_placeholder"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="The wallet history is empty"
- tools:visibility="gone"/>
- </LinearLayout>
+ <ProgressBar
+ android:id="@+id/historyProgressBar"
+ style="?android:progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:visibility="invisible"
+ tools:visibility="visible" />
-</androidx.core.widget.NestedScrollView> \ No newline at end of file
+</FrameLayout>
diff --git a/app/src/main/res/layout/history_payment_sent.xml b/app/src/main/res/layout/history_payment_sent.xml
index 0c39133..cf03998 100644
--- a/app/src/main/res/layout/history_payment_sent.xml
+++ b/app/src/main/res/layout/history_payment_sent.xml
@@ -22,16 +22,15 @@
<TextView
android:id="@+id/title"
+ style="@style/HistoryTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
- android:text="@string/history_event_payment_sent"
- android:textColor="?android:textColorPrimary"
- android:textSize="20sp"
app:layout_constraintEnd_toStartOf="@+id/amountPaidWithFees"
app:layout_constraintStart_toEndOf="@+id/icon"
- app:layout_constraintTop_toTopOf="parent" />
+ app:layout_constraintTop_toTopOf="parent"
+ tools:text="Lots of books with very long titles" />
<TextView
android:id="@+id/summary"
@@ -46,16 +45,18 @@
app:layout_constraintStart_toEndOf="@+id/icon"
app:layout_constraintTop_toBottomOf="@+id/title"
app:layout_constraintVertical_bias="0.0"
- tools:text="Lots of books" />
+ tools:text="@string/history_event_payment_sent" />
<TextView
android:id="@+id/amountPaidWithFees"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/red"
+ android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/time"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.0"
tools:text="0.2 TESTKUDOS" />
<TextView
diff --git a/app/src/main/res/layout/history_row.xml b/app/src/main/res/layout/history_row.xml
index cab7f0f..394ad79 100644
--- a/app/src/main/res/layout/history_row.xml
+++ b/app/src/main/res/layout/history_row.xml
@@ -18,11 +18,11 @@
tools:ignore="ContentDescription" />
<TextView
+ style="@style/HistoryTitle"
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
- android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/icon"
app:layout_constraintTop_toTopOf="parent"
diff --git a/app/src/main/res/layout/history_withdrawn.xml b/app/src/main/res/layout/history_withdrawn.xml
index e02046b..75bae07 100644
--- a/app/src/main/res/layout/history_withdrawn.xml
+++ b/app/src/main/res/layout/history_withdrawn.xml
@@ -22,29 +22,38 @@
<TextView
android:id="@+id/title"
+ style="@style/HistoryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/history_event_withdrawn"
- android:textColor="?android:textColorPrimary"
- android:textSize="20sp"
+ android:visibility="gone"
app:layout_constraintStart_toEndOf="@+id/icon"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/exchangeUrl"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="8dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@+id/fee"
- app:layout_constraintHorizontal_bias="0.0"
+ app:layout_constraintEnd_toStartOf="@+id/feeLabel"
app:layout_constraintStart_toEndOf="@+id/icon"
app:layout_constraintTop_toBottomOf="@+id/title"
- app:layout_constraintVertical_bias="0.0"
- tools:text="http://taler.exchange.url" />
+ tools:text="http://taler.quite-long-exchange.url" />
+
+ <TextView
+ android:id="@+id/feeLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="2dp"
+ android:text="@string/history_fee_label"
+ app:layout_constraintEnd_toStartOf="@+id/fee"
+ app:layout_constraintTop_toTopOf="@+id/fee" />
<TextView
android:id="@+id/fee"
@@ -76,6 +85,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/fee"
- tools:text="23 min ago" />
+ tools:text="23 min. ago" />
</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/menu/history.xml b/app/src/main/res/menu/history.xml
index c8fb3e7..8c2aa69 100644
--- a/app/src/main/res/menu/history.xml
+++ b/app/src/main/res/menu/history.xml
@@ -1,8 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
- <item android:id="@+id/reload_history"
- android:title="Reload History"
- android:orderInCategory="100"
- app:showAsAction="never"/>
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/show_all_history"
+ android:checkable="true"
+ android:checked="false"
+ android:title="@string/history_show_all"
+ app:showAsAction="never" />
+ <item
+ android:id="@+id/reload_history"
+ android:orderInCategory="100"
+ android:title="@string/history_reload"
+ app:showAsAction="never" />
</menu>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1caf41e..6a92705 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,11 +20,15 @@
<string name="history_event_exchange_added">Exchange Added</string>
<string name="history_event_exchange_updated">Exchange Updated</string>
<string name="history_event_reserve_balance_updated">Reserve Balance Updated</string>
- <string name="history_event_payment_sent">Payment Made</string>
+ <string name="history_event_payment_sent">Payment</string>
<string name="history_event_withdrawn">Withdraw</string>
<string name="history_event_order_accepted">Order Confirmed</string>
<string name="history_event_order_refused">Order Cancelled</string>
<string name="history_event_refreshed">Refresh</string>
+ <string name="history_fee_label">Fee:</string>
+ <string name="history_show_all">Show All</string>
+ <string name="history_reload">Reload History</string>
+ <string name="history_empty">The wallet history is empty</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 16dbab3..619c0c9 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -14,4 +14,9 @@
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
+ <style name="HistoryTitle">
+ <item name="android:textSize">18sp</item>
+ <item name="android:textColor">?android:textColorPrimary</item>
+ </style>
+
</resources>