diff options
author | Torsten Grote <t@grobox.de> | 2020-03-05 14:39:13 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2020-03-05 14:39:13 -0300 |
commit | 630f19931a093e5c0b4440a138a0717a8ce47e78 (patch) | |
tree | e17288d906572d828b2eb69659880d01e80179dd | |
parent | b9f573b313303f10cff638b7cc28a9018c1eda55 (diff) | |
download | wallet-android-630f19931a093e5c0b4440a138a0717a8ce47e78.tar.gz wallet-android-630f19931a093e5c0b4440a138a0717a8ce47e78.tar.bz2 wallet-android-630f19931a093e5c0b4440a138a0717a8ce47e78.zip |
Factor out history code from ViewModel
Show history event JSON only in developer mode
-rw-r--r-- | app/src/main/java/net/taler/wallet/WalletViewModel.kt | 49 | ||||
-rw-r--r-- | app/src/main/java/net/taler/wallet/history/HistoryManager.kt | 71 | ||||
-rw-r--r-- | app/src/main/java/net/taler/wallet/history/WalletHistoryFragment.kt (renamed from app/src/main/java/net/taler/wallet/history/WalletHistory.kt) | 72 | ||||
-rw-r--r-- | app/src/main/res/navigation/nav_graph.xml | 4 | ||||
-rw-r--r-- | app/src/main/res/values/strings.xml | 10 |
5 files changed, 113 insertions, 93 deletions
diff --git a/app/src/main/java/net/taler/wallet/WalletViewModel.kt b/app/src/main/java/net/taler/wallet/WalletViewModel.kt index bec662a..14a800f 100644 --- a/app/src/main/java/net/taler/wallet/WalletViewModel.kt +++ b/app/src/main/java/net/taler/wallet/WalletViewModel.kt @@ -22,21 +22,12 @@ import androidx.annotation.UiThread import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asLiveData import androidx.lifecycle.distinctUntilChanged -import androidx.lifecycle.switchMap import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 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 net.taler.wallet.history.HistoryEvent +import net.taler.wallet.history.HistoryManager import net.taler.wallet.payment.PaymentManager import net.taler.wallet.pending.PendingOperationsManager import net.taler.wallet.withdraw.WithdrawManager @@ -46,26 +37,12 @@ const val TAG = "taler-wallet" data class BalanceItem(val available: Amount, val pendingIncoming: Amount) -@Suppress("EXPERIMENTAL_API_USAGE") class WalletViewModel(val app: Application) : AndroidViewModel(app) { private val mBalances = MutableLiveData<List<BalanceItem>>() val balances: LiveData<List<BalanceItem>> = mBalances.distinctUntilChanged() val devMode = MutableLiveData(BuildConfig.DEBUG) - - 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) - } - val showProgressBar = MutableLiveData<Boolean>() private var activeGetBalance = 0 @@ -88,6 +65,7 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { val paymentManager = PaymentManager(walletBackendApi, mapper) val pendingOperationsManager: PendingOperationsManager = PendingOperationsManager(walletBackendApi) + val historyManager = HistoryManager(walletBackendApi, mapper) override fun onCleared() { walletBackendApi.destroy() @@ -123,29 +101,6 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { } } - 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() - val json = result.getJSONArray("history") - for (i in 0 until json.length()) { - val event: HistoryEvent = mapper.readValue(json.getString(i)) - event.json = json.getJSONObject(i) - history.add(event) - } - history.reverse() // show latest first - mHistoryProgress.postValue(false) - offer(if (showAll) history else history.filter { it.showToUser } as History) - close() - } - awaitClose() - } - @UiThread fun dangerouslyReset() { walletBackendApi.sendRequest("reset", null) diff --git a/app/src/main/java/net/taler/wallet/history/HistoryManager.kt b/app/src/main/java/net/taler/wallet/history/HistoryManager.kt new file mode 100644 index 0000000..c350daa --- /dev/null +++ b/app/src/main/java/net/taler/wallet/history/HistoryManager.kt @@ -0,0 +1,71 @@ +/* + * This file is part of GNU Taler + * (C) 2020 Taler Systems S.A. + * + * GNU Taler is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3, or (at your option) any later version. + * + * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +package net.taler.wallet.history + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asLiveData +import androidx.lifecycle.switchMap +import com.fasterxml.jackson.databind.ObjectMapper +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 + +@Suppress("EXPERIMENTAL_API_USAGE") +class HistoryManager( + private val walletBackendApi: WalletBackendApi, + private val mapper: ObjectMapper +) { + + private val mProgress = MutableLiveData<Boolean>() + val progress: LiveData<Boolean> = mProgress + + val showAll = MutableLiveData<Boolean>() + + val history: LiveData<History> = showAll.switchMap { showAll -> + loadHistory(showAll) + .onStart { mProgress.postValue(true) } + .onCompletion { mProgress.postValue(false) } + .asLiveData(Dispatchers.IO) + } + + private fun loadHistory(showAll: Boolean) = callbackFlow { + walletBackendApi.sendRequest("getHistory", null) { isError, result -> + if (isError) { + // TODO show error message in [WalletHistory] fragment + close() + return@sendRequest + } + val history = History() + val json = result.getJSONArray("history") + for (i in 0 until json.length()) { + val event: HistoryEvent = mapper.readValue(json.getString(i)) + event.json = json.getJSONObject(i) + history.add(event) + } + history.reverse() // show latest first + offer(if (showAll) history else history.filter { it.showToUser } as History) + close() + } + awaitClose() + } + +} diff --git a/app/src/main/java/net/taler/wallet/history/WalletHistory.kt b/app/src/main/java/net/taler/wallet/history/WalletHistoryFragment.kt index bb37ffa..75b7d02 100644 --- a/app/src/main/java/net/taler/wallet/history/WalletHistory.kt +++ b/app/src/main/java/net/taler/wallet/history/WalletHistoryFragment.kt @@ -16,7 +16,6 @@ package net.taler.wallet.history - import android.os.Bundle import android.view.LayoutInflater import android.view.Menu @@ -27,10 +26,11 @@ import android.view.View.INVISIBLE import android.view.View.VISIBLE import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL import kotlinx.android.synthetic.main.fragment_show_history.* import net.taler.wallet.R import net.taler.wallet.WalletViewModel @@ -39,44 +39,16 @@ interface OnEventClickListener { fun onEventClicked(event: HistoryEvent) } -/** - * Wallet history. - * - */ -class WalletHistory : Fragment(), OnEventClickListener { +class WalletHistoryFragment : Fragment(), OnEventClickListener { - private lateinit var model: WalletViewModel + private val model: WalletViewModel by activityViewModels() + private val historyManager by lazy { model.historyManager } private lateinit var showAllItem: MenuItem private val historyAdapter = WalletHistoryAdapter(this) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) - - model = activity?.run { - ViewModelProvider(this)[WalletViewModel::class.java] - } ?: throw Exception("Invalid Activity") - - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - 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 -> { - model.historyShowAll.value = showAllItem.isChecked - true - } - else -> super.onOptionsItemSelected(item) - } } override fun onCreateView( @@ -88,26 +60,46 @@ class WalletHistory : Fragment(), OnEventClickListener { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { historyList.apply { - val myLayoutManager = LinearLayoutManager(context) - val myItemDecoration = DividerItemDecoration(context, myLayoutManager.orientation) - layoutManager = myLayoutManager + layoutManager = LinearLayoutManager(context) adapter = historyAdapter - addItemDecoration(myItemDecoration) + addItemDecoration(DividerItemDecoration(context, VERTICAL)) } - model.historyProgress.observe(viewLifecycleOwner, Observer { show -> + historyManager.progress.observe(viewLifecycleOwner, Observer { show -> historyProgressBar.visibility = if (show) VISIBLE else INVISIBLE }) - model.history.observe(viewLifecycleOwner, Observer { history -> + historyManager.history.observe(viewLifecycleOwner, Observer { history -> historyEmptyState.visibility = if (history.isEmpty()) VISIBLE else INVISIBLE historyAdapter.update(history) }) // kicks off initial load, needs to be adapted if showAll state is ever saved - if (savedInstanceState == null) model.historyShowAll.value = false + if (savedInstanceState == null) historyManager.showAll.value = model.devMode.value + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.history, menu) + showAllItem = menu.findItem(R.id.show_all_history) + showAllItem.isChecked = historyManager.showAll.value == true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.show_all_history -> { + item.isChecked = !item.isChecked + historyManager.showAll.value = item.isChecked + true + } + R.id.reload_history -> { + historyManager.showAll.value = showAllItem.isChecked + true + } + else -> super.onOptionsItemSelected(item) + } } override fun onEventClicked(event: HistoryEvent) { + if (model.devMode.value != true) return JsonDialogFragment.new(event.json.toString(4)) .show(parentFragmentManager, null) } diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 648c88e..3a14e8b 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -59,8 +59,8 @@ tools:layout="@layout/fragment_settings" /> <fragment android:id="@+id/walletHistory" - android:name="net.taler.wallet.history.WalletHistory" - android:label="History" + android:name="net.taler.wallet.history.WalletHistoryFragment" + android:label="@string/history_title" tools:layout="@layout/fragment_show_history" /> <fragment android:id="@+id/alreadyPaid" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ca69756..3be1745 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -42,6 +42,12 @@ <string name="balances_inbound">inbound</string> <string name="balances_empty_state">There is no digital cash in your wallet.\n\nYou can get test money from the demo bank:\n\nhttps://bank.demo.taler.net</string> + <string name="history_title">History</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> + <!-- HistoryEvents --> <string name="history_event_exchange_added">Exchange Added</string> <string name="history_event_exchange_updated">Exchange Updated</string> @@ -57,10 +63,6 @@ <string name="history_event_refund">Refund</string> <string name="history_event_refreshed">Obtained change</string> <string name="history_event_unknown">Unknown Event</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> <string name="payment_fee">+%s payment fee</string> <string name="payment_button_confirm">Confirm Payment</string> |