diff options
author | Torsten Grote <t@grobox.de> | 2020-05-20 11:47:26 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2020-05-20 11:47:52 -0300 |
commit | b0869289dc9fa2f983991915e77ba0260e59ed8b (patch) | |
tree | b85512148453e1f60e3fa5f596470ba5bcb3df63 /wallet/src | |
parent | 17fe2f70c3d0f34b11db9e4e66ef489bbeae7065 (diff) | |
download | taler-android-b0869289dc9fa2f983991915e77ba0260e59ed8b.tar.gz taler-android-b0869289dc9fa2f983991915e77ba0260e59ed8b.tar.bz2 taler-android-b0869289dc9fa2f983991915e77ba0260e59ed8b.zip |
[wallet] implement transaction search
Diffstat (limited to 'wallet/src')
6 files changed, 86 insertions, 25 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt index d5cee16..882b29b 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt @@ -20,6 +20,7 @@ import androidx.annotation.UiThread import androidx.annotation.WorkerThread import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.switchMap import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import kotlinx.coroutines.CoroutineScope @@ -46,26 +47,36 @@ class TransactionManager( var selectedCurrency: String? = null var selectedTransaction: Transaction? = null + val searchQuery = MutableLiveData<String>(null) + private val allTransactions = HashMap<String, List<Transaction>>() private val mTransactions = HashMap<String, MutableLiveData<TransactionsResult>>() val transactions: LiveData<TransactionsResult> @UiThread - get() { + get() = searchQuery.switchMap { query -> val currency = selectedCurrency check(currency != null) { "Did not select currency before getting transactions" } - return mTransactions.getOrPut(currency) { MutableLiveData() } + loadTransactions(query) + mTransactions[currency]!! // non-null because filled in [loadTransactions] } @UiThread - fun loadTransactions() { + fun loadTransactions(searchQuery: String? = null) { val currency = selectedCurrency ?: return - val liveData = mTransactions.getOrPut(currency) { - MutableLiveData<TransactionsResult>() + val liveData = mTransactions.getOrPut(currency) { MutableLiveData() } + if (searchQuery == null && allTransactions.containsKey(currency)) { + liveData.value = TransactionsResult.Success(allTransactions[currency]!!) } if (liveData.value == null) mProgress.value = true val request = JSONObject(mapOf("currency" to currency)) + searchQuery?.let { request.put("search", it) } walletBackendApi.sendRequest("getTransactions", request) { isError, result -> - scope.launch(Dispatchers.Default) { - onTransactionsLoaded(liveData, isError, result) + if (isError) { + liveData.postValue(TransactionsResult.Error) + } else { + val currencyToUpdate = if (searchQuery == null) currency else null + scope.launch(Dispatchers.Default) { + onTransactionsLoaded(liveData, currencyToUpdate, result) + } } } } @@ -73,13 +84,9 @@ class TransactionManager( @WorkerThread private fun onTransactionsLoaded( liveData: MutableLiveData<TransactionsResult>, - isError: Boolean, + currency: String?, // only non-null if we should update all transactions cache result: JSONObject ) { - if (isError) { - liveData.postValue(TransactionsResult.Error) - return - } val transactionsArray = result.getString("transactions") val transactions: LinkedList<Transaction> = mapper.readValue(transactionsArray) // TODO remove when fixed in wallet-core @@ -87,6 +94,10 @@ class TransactionManager( transactions.reverse() // show latest first mProgress.postValue(false) liveData.postValue(TransactionsResult.Success(transactions)) + // update all transactions on UiThread if there was a currency + currency?.let { + scope.launch(Dispatchers.Main) { allTransactions[currency] = transactions } + } } @UiThread diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt index dfd00ea..526aa94 100644 --- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt +++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt @@ -23,11 +23,11 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View -import android.view.View.INVISIBLE -import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.Toast import android.widget.Toast.LENGTH_LONG +import androidx.appcompat.widget.SearchView +import androidx.appcompat.widget.SearchView.OnQueryTextListener import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer @@ -102,14 +102,11 @@ class TransactionsFragment : Fragment(), OnTransactionClickListener, ActionMode. }) transactionManager.progress.observe(viewLifecycleOwner, Observer { show -> - progressBar.visibility = if (show) VISIBLE else INVISIBLE + if (show) progressBar.fadeIn() else progressBar.fadeOut() }) transactionManager.transactions.observe(viewLifecycleOwner, Observer { result -> onTransactionsResult(result) }) - - // kicks off initial load, needs to be adapted if showAll state is ever saved - if (savedInstanceState == null) transactionManager.loadTransactions() } override fun onActivityCreated(savedInstanceState: Bundle?) { @@ -129,12 +126,29 @@ class TransactionsFragment : Fragment(), OnTransactionClickListener, ActionMode. override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.transactions, menu) + setupSearch(menu.findItem(R.id.action_search)) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - else -> super.onOptionsItemSelected(item) - } + private fun setupSearch(item: MenuItem) { + item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem) = true + override fun onMenuItemActionCollapse(item: MenuItem): Boolean { + onSearchClosed() + return true + } + }) + val searchView = item.actionView as SearchView + searchView.setOnQueryTextListener(object : OnQueryTextListener { + override fun onQueryTextChange(newText: String) = false + override fun onQueryTextSubmit(query: String): Boolean { + // workaround to avoid issues with some emulators and keyboard devices + // firing twice if a keyboard enter is used + // see https://code.google.com/p/android/issues/detail?id=24599 + item.actionView.clearFocus() + onSearch(query) + return true + } + }) } override fun onTransactionClicked(transaction: Transaction) { @@ -152,12 +166,29 @@ class TransactionsFragment : Fragment(), OnTransactionClickListener, ActionMode. emptyState.fadeIn() } is TransactionsResult.Success -> { - emptyState.visibility = if (result.transactions.isEmpty()) VISIBLE else INVISIBLE - transactionAdapter.update(result.transactions) - list.fadeIn() + if (result.transactions.isEmpty()) { + val isSearch = transactionManager.searchQuery.value != null + emptyState.setText(if (isSearch) R.string.transactions_empty_search else R.string.transactions_empty) + emptyState.fadeIn() + list.fadeOut() + } else { + emptyState.fadeOut() + transactionAdapter.update(result.transactions) + list.fadeIn() + } } } + private fun onSearch(query: String) { + list.fadeOut() + progressBar.fadeIn() + transactionManager.searchQuery.value = query + } + + private fun onSearchClosed() { + transactionManager.searchQuery.value = null + } + override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { val inflater = mode.menuInflater inflater.inflate(R.menu.transactions_action_mode, menu) diff --git a/wallet/src/main/res/drawable/ic_search.xml b/wallet/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..13e67fe --- /dev/null +++ b/wallet/src/main/res/drawable/ic_search.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorControlNormal" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" /> +</vector> diff --git a/wallet/src/main/res/layout/app_bar_main.xml b/wallet/src/main/res/layout/app_bar_main.xml index 5ee55b2..6937e59 100644 --- a/wallet/src/main/res/layout/app_bar_main.xml +++ b/wallet/src/main/res/layout/app_bar_main.xml @@ -36,6 +36,7 @@ style="@style/AppTheme.Toolbar" android:layout_width="0dp" android:layout_height="wrap_content" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/wallet/src/main/res/menu/transactions.xml b/wallet/src/main/res/menu/transactions.xml index d4568d4..2ea8a23 100644 --- a/wallet/src/main/res/menu/transactions.xml +++ b/wallet/src/main/res/menu/transactions.xml @@ -16,4 +16,10 @@ <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/action_search" + android:icon="@drawable/ic_search" + android:title="@string/search" + app:actionViewClass="androidx.appcompat.widget.SearchView" + app:showAsAction="always|collapseActionView" /> </menu> diff --git a/wallet/src/main/res/values/strings.xml b/wallet/src/main/res/values/strings.xml index 7d76806..167ab53 100644 --- a/wallet/src/main/res/values/strings.xml +++ b/wallet/src/main/res/values/strings.xml @@ -45,6 +45,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <string name="button_back">Go Back</string> <string name="button_scan_qr_code">Scan Taler QR Code</string> + <string name="search">Search</string> <string name="menu_settings">Settings</string> <string name="menu_retry_pending_operations">Retry Pending Operations</string> @@ -61,6 +62,7 @@ GNU Taler is immune against many types of fraud, such as phishing of credit card <string name="transactions_title">Transactions</string> <string name="transactions_empty">You don\'t have any transactions</string> + <string name="transactions_empty_search">No transactions found. Try a different search.</string> <string name="transactions_error">Could not load transactions</string> <string name="transactions_detail_title">Transaction</string> <string name="transactions_detail_title_balance">Balance: %s</string> |