From 1bbc48f7f9a893c13b07a5436a0b2b5f923de398 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 4 Mar 2020 16:14:29 -0300 Subject: Move pending operations into their own fragment They will be visible only in developer mode and otherwise rendered nicely for the user where appropriate. --- app/src/main/java/net/taler/wallet/MainActivity.kt | 1 + app/src/main/java/net/taler/wallet/ShowBalance.kt | 212 +++++---------------- .../main/java/net/taler/wallet/WalletViewModel.kt | 68 ++----- .../net/taler/wallet/backend/WalletBackendApi.kt | 27 ++- .../wallet/pending/PendingOperationsFragment.kt | 180 +++++++++++++++++ .../wallet/pending/PendingOperationsManager.kt | 60 ++++++ .../res/layout/fragment_pending_operations.xml | 34 ++++ app/src/main/res/layout/fragment_show_balance.xml | 16 +- app/src/main/res/menu/activity_main_drawer.xml | 4 + app/src/main/res/menu/balance.xml | 5 - app/src/main/res/menu/pending_operations.xml | 24 +++ app/src/main/res/navigation/nav_graph.xml | 10 + app/src/main/res/values/strings.xml | 2 +- 13 files changed, 385 insertions(+), 258 deletions(-) create mode 100644 app/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt create mode 100644 app/src/main/java/net/taler/wallet/pending/PendingOperationsManager.kt create mode 100644 app/src/main/res/layout/fragment_pending_operations.xml create mode 100644 app/src/main/res/menu/pending_operations.xml (limited to 'app/src') diff --git a/app/src/main/java/net/taler/wallet/MainActivity.kt b/app/src/main/java/net/taler/wallet/MainActivity.kt index ebc7136..5267056 100644 --- a/app/src/main/java/net/taler/wallet/MainActivity.kt +++ b/app/src/main/java/net/taler/wallet/MainActivity.kt @@ -99,6 +99,7 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, R.id.nav_home -> nav.navigate(R.id.showBalance) R.id.nav_settings -> nav.navigate(R.id.settings) R.id.nav_history -> nav.navigate(R.id.walletHistory) + R.id.nav_pending_operations -> nav.navigate(R.id.nav_pending_operations) } drawer_layout.closeDrawer(START) return true diff --git a/app/src/main/java/net/taler/wallet/ShowBalance.kt b/app/src/main/java/net/taler/wallet/ShowBalance.kt index 4b52426..fe1a109 100644 --- a/app/src/main/java/net/taler/wallet/ShowBalance.kt +++ b/app/src/main/java/net/taler/wallet/ShowBalance.kt @@ -28,7 +28,6 @@ import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.Button -import android.widget.LinearLayout import android.widget.TextView import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -36,132 +35,17 @@ import androidx.lifecycle.Observer import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.snackbar.Snackbar import com.google.zxing.integration.android.IntentIntegrator import com.google.zxing.integration.android.IntentIntegrator.QR_CODE_TYPES -import org.json.JSONObject -class WalletBalanceAdapter(private var myDataset: WalletBalances) : - RecyclerView.Adapter() { - - init { - setHasStableIds(false) - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { - val rowView = - LayoutInflater.from(parent.context).inflate(R.layout.balance_row, parent, false) - return MyViewHolder(rowView) - } - - override fun getItemCount(): Int { - return myDataset.byCurrency.size - } - - override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - val amount = myDataset.byCurrency[position].available - val amountIncoming = myDataset.byCurrency[position].pendingIncoming - val currencyView = holder.rowView.findViewById(R.id.balance_currency) - currencyView.text = amount.currency - val amountView = holder.rowView.findViewById(R.id.balance_amount) - amountView.text = amount.amount - - val amountIncomingRow = holder.rowView.findViewById(R.id.balance_row_pending) - - val amountIncomingView = holder.rowView.findViewById(R.id.balance_pending) - if (amountIncoming.isZero()) { - amountIncomingRow.visibility = GONE - } else { - amountIncomingRow.visibility = VISIBLE - @SuppressLint("SetTextI18n") - amountIncomingView.text = "${amountIncoming.amount} ${amountIncoming.currency}" - } - } - - fun update(updatedBalances: WalletBalances) { - this.myDataset = updatedBalances - this.notifyDataSetChanged() - } - - class MyViewHolder(val rowView: View) : RecyclerView.ViewHolder(rowView) -} - -class PendingOperationsAdapter(private var myDataset: PendingOperations) : - RecyclerView.Adapter() { - - private var listener: PendingOperationClickListener? = null - - - init { - setHasStableIds(false) - } - - fun setPendingOperationClickListener(listener: PendingOperationClickListener) { - this.listener = listener - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { - val rowView = - LayoutInflater.from(parent.context).inflate(R.layout.pending_row, parent, false) - return MyViewHolder(rowView) - } - - override fun getItemCount(): Int { - return myDataset.pending.size - } - - override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - val p = myDataset.pending[position] - val pendingContainer = holder.rowView.findViewById(R.id.pending_container) - pendingContainer.setOnClickListener { - this.listener?.onPendingOperationClick(p.type, p.detail) - } - when (p.type) { - "proposal-choice" -> { - val btn1 = holder.rowView.findViewById(R.id.button_pending_action_1) - btn1.text = btn1.context.getString(R.string.pending_operations_refuse) - btn1.visibility = VISIBLE - btn1.setOnClickListener { - this.listener?.onPendingOperationActionClick(p.type, p.detail) - } - } - else -> { - val btn1 = holder.rowView.findViewById(R.id.button_pending_action_1) - btn1.text = btn1.context.getString(R.string.pending_operations_no_action) - btn1.visibility = GONE - btn1.setOnClickListener {} - } - } - val textView = holder.rowView.findViewById(R.id.pending_text) - val subTextView = holder.rowView.findViewById(R.id.pending_subtext) - subTextView.text = p.detail.toString(1) - textView.text = p.type - } - - fun update(updatedDataset: PendingOperations) { - this.myDataset = updatedDataset - this.notifyDataSetChanged() - } - - class MyViewHolder(val rowView: View) : RecyclerView.ViewHolder(rowView) -} - -interface PendingOperationClickListener { - fun onPendingOperationClick(type: String, detail: JSONObject) - fun onPendingOperationActionClick(type: String, detail: JSONObject) -} - -class ShowBalance : Fragment(), PendingOperationClickListener { +class ShowBalance : Fragment() { private val model: WalletViewModel by activityViewModels() private val withdrawManager by lazy { model.withdrawManager } - private lateinit var pendingOperationsLabel: View private lateinit var balancesView: RecyclerView private lateinit var balancesPlaceholderView: TextView - private lateinit var balancesAdapter: WalletBalanceAdapter - - private lateinit var pendingAdapter: PendingOperationsAdapter + private lateinit var balancesAdapter: BalanceAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -187,7 +71,7 @@ class ShowBalance : Fragment(), PendingOperationClickListener { val balances = model.balances.value!! - balancesAdapter = WalletBalanceAdapter(balances) + balancesAdapter = BalanceAdapter(balances) view.findViewById(R.id.list_balances).apply { val myLayoutManager = LinearLayoutManager(context) @@ -216,23 +100,6 @@ class ShowBalance : Fragment(), PendingOperationClickListener { triggerLoading() }) - pendingAdapter = PendingOperationsAdapter(PendingOperations(listOf())) - pendingAdapter.setPendingOperationClickListener(this) - - this.pendingOperationsLabel = view.findViewById(R.id.pending_operations_label) - - view.findViewById(R.id.list_pending).apply { - val myLayoutManager = LinearLayoutManager(context) - val myItemDecoration = DividerItemDecoration(context, myLayoutManager.orientation) - layoutManager = myLayoutManager - adapter = pendingAdapter - addItemDecoration(myItemDecoration) - } - - model.pendingOperations.observe(viewLifecycleOwner, Observer { - updatePending(it) - }) - return view } @@ -244,10 +111,6 @@ class ShowBalance : Fragment(), PendingOperationClickListener { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { - R.id.retry_pending -> { - model.retryPendingNow() - true - } R.id.reload_balance -> { triggerLoading() model.balances.value = WalletBalances(false, listOf()) @@ -285,39 +148,50 @@ class ShowBalance : Fragment(), PendingOperationClickListener { balancesAdapter.update(balances) } - private fun updatePending(pendingOperations: PendingOperations) { - if (pendingOperations.pending.isEmpty()) { - pendingOperationsLabel.visibility = GONE - } else { - pendingOperationsLabel.visibility = VISIBLE - } - pendingAdapter.update(pendingOperations) +} + +class BalanceAdapter(private var myDataset: WalletBalances) : + RecyclerView.Adapter() { + + init { + setHasStableIds(false) } - override fun onPendingOperationClick(type: String, detail: JSONObject) { - val v = view ?: return - when { - else -> { - val bar = Snackbar.make( - v, - "No detail view for $type implemented yet.", - Snackbar.LENGTH_SHORT - ) - bar.show() - } - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BalanceViewHolder { + val rowView = + LayoutInflater.from(parent.context).inflate(R.layout.balance_row, parent, false) + return BalanceViewHolder(rowView) } - override fun onPendingOperationActionClick(type: String, detail: JSONObject) { - when (type) { - "proposal-choice" -> { - Log.v(TAG, "got action click on proposal-choice") - val proposalId = detail.optString("proposalId", "") - if (proposalId == "") { - return - } - model.paymentManager.abortProposal(proposalId) - } + override fun getItemCount(): Int { + return myDataset.byCurrency.size + } + + override fun onBindViewHolder(holder: BalanceViewHolder, position: Int) { + val amount = myDataset.byCurrency[position].available + val amountIncoming = myDataset.byCurrency[position].pendingIncoming + val currencyView = holder.rowView.findViewById(R.id.balance_currency) + currencyView.text = amount.currency + val amountView = holder.rowView.findViewById(R.id.balance_amount) + amountView.text = amount.amount + + val amountIncomingRow = holder.rowView.findViewById(R.id.balance_row_pending) + + val amountIncomingView = holder.rowView.findViewById(R.id.balance_pending) + if (amountIncoming.isZero()) { + amountIncomingRow.visibility = GONE + } else { + amountIncomingRow.visibility = VISIBLE + @SuppressLint("SetTextI18n") + amountIncomingView.text = "${amountIncoming.amount} ${amountIncoming.currency}" } } + + fun update(updatedBalances: WalletBalances) { + this.myDataset = updatedBalances + this.notifyDataSetChanged() + } + + class BalanceViewHolder(val rowView: View) : RecyclerView.ViewHolder(rowView) + } diff --git a/app/src/main/java/net/taler/wallet/WalletViewModel.kt b/app/src/main/java/net/taler/wallet/WalletViewModel.kt index d9e730d..2ec88af 100644 --- a/app/src/main/java/net/taler/wallet/WalletViewModel.kt +++ b/app/src/main/java/net/taler/wallet/WalletViewModel.kt @@ -37,6 +37,7 @@ import net.taler.wallet.backend.WalletBackendApi import net.taler.wallet.history.History import net.taler.wallet.history.HistoryEvent import net.taler.wallet.payment.PaymentManager +import net.taler.wallet.pending.PendingOperationsManager import net.taler.wallet.withdraw.WithdrawManager import org.json.JSONObject @@ -48,15 +49,6 @@ data class BalanceEntry(val available: Amount, val pendingIncoming: Amount) data class WalletBalances(val initialized: Boolean, val byCurrency: List) -open class PendingOperationInfo( - val type: String, - val detail: JSONObject -) - -open class PendingOperations( - val pending: List -) - @Suppress("EXPERIMENTAL_API_USAGE") class WalletViewModel(val app: Application) : AndroidViewModel(app) { @@ -65,10 +57,6 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { value = WalletBalances(false, listOf()) } - val pendingOperations = MutableLiveData().apply { - value = PendingOperations(listOf()) - } - private val mHistoryProgress = MutableLiveData() val historyProgress: LiveData = mHistoryProgress @@ -84,9 +72,16 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { val showProgressBar = MutableLiveData() private var activeGetBalance = 0 - private var activeGetPending = 0 - private val walletBackendApi = WalletBackendApi(app) + private val walletBackendApi = WalletBackendApi(app, { + activeGetBalance = 0 + getBalances() + pendingOperationsManager.getPending() + }) { + Log.i(TAG, "Received notification from wallet-core") + getBalances() + pendingOperationsManager.getPending() + } private val mapper = ObjectMapper() .registerModule(KotlinModule()) @@ -94,23 +89,8 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { val withdrawManager = WithdrawManager(walletBackendApi) val paymentManager = PaymentManager(walletBackendApi, mapper) - - init { - getBalances() - getPending() - - walletBackendApi.notificationHandler = { - Log.i(TAG, "got notification from wallet") - getBalances() - getPending() - } - walletBackendApi.connectedHandler = { - activeGetBalance = 0 - activeGetPending = 0 - getBalances() - getPending() - } - } + val pendingOperationsManager: PendingOperationsManager = + PendingOperationsManager(walletBackendApi) fun getBalances() { if (activeGetBalance > 0) { @@ -138,30 +118,6 @@ class WalletViewModel(val app: Application) : AndroidViewModel(app) { } } - private fun getPending() { - if (activeGetPending > 0) { - return - } - activeGetPending++ - walletBackendApi.sendRequest("getPendingOperations", null) { isError, result -> - activeGetPending-- - if (isError) { - Log.i(TAG, "got getPending error result") - return@sendRequest - } - Log.i(TAG, "got getPending result") - val pendingList = mutableListOf() - val pendingJson = result.getJSONArray("pendingOperations") - for (i in 0 until pendingJson.length()) { - val p = pendingJson.getJSONObject(i) - val type = p.getString("type") - pendingList.add(PendingOperationInfo(type, p)) - } - Log.i(TAG, "Got ${pendingList.size} pending operations") - pendingOperations.postValue(PendingOperations((pendingList))) - } - } - private fun loadHistory(showAll: Boolean) = callbackFlow { mHistoryProgress.postValue(true) walletBackendApi.sendRequest("getHistory", null) { isError, result -> diff --git a/app/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt b/app/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt index 8f37ff3..d447287 100644 --- a/app/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt +++ b/app/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt @@ -22,21 +22,26 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection -import android.os.* +import android.os.Handler +import android.os.IBinder +import android.os.Message +import android.os.Messenger import android.util.Log import android.util.SparseArray import org.json.JSONObject import java.lang.ref.WeakReference import java.util.* -class WalletBackendApi(private val app: Application) { +class WalletBackendApi( + private val app: Application, + private val onConnected: (() -> Unit), + private val notificationHandler: (() -> Unit) +) { private var walletBackendMessenger: Messenger? = null private val queuedMessages = LinkedList() private val handlers = SparseArray<(isError: Boolean, message: JSONObject) -> Unit>() private var nextRequestID = 1 - var notificationHandler: (() -> Unit)? = null - var connectedHandler: (() -> Unit)? = null private val walletBackendConn = object : ServiceConnection { override fun onServiceDisconnected(p0: ComponentName?) { @@ -52,15 +57,12 @@ class WalletBackendApi(private val app: Application) { val msg = Message.obtain(null, WalletBackendService.MSG_SUBSCRIBE_NOTIFY) msg.replyTo = incomingMessenger bm.send(msg) - val ch = connectedHandler - if (ch != null) { - ch() - } + onConnected.invoke() } } private class IncomingHandler(strongApi: WalletBackendApi) : Handler() { - private val weakApi = WeakReference(strongApi) + private val weakApi = WeakReference(strongApi) override fun handleMessage(msg: Message) { val api = weakApi.get() ?: return when (msg.what) { @@ -83,10 +85,7 @@ class WalletBackendApi(private val app: Application) { h(isError, json) } WalletBackendService.MSG_NOTIFY -> { - val nh = api.notificationHandler - if (nh != null) { - nh() - } + api.notificationHandler.invoke() } } } @@ -139,4 +138,4 @@ class WalletBackendApi(private val app: Application) { companion object { const val TAG = "WalletBackendApi" } -} \ No newline at end of file +} diff --git a/app/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt b/app/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt new file mode 100644 index 0000000..7595827 --- /dev/null +++ b/app/src/main/java/net/taler/wallet/pending/PendingOperationsFragment.kt @@ -0,0 +1,180 @@ +/* + * 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 + */ + +package net.taler.wallet.pending + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.View.GONE +import android.view.View.VISIBLE +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.snackbar.Snackbar +import com.google.android.material.snackbar.Snackbar.LENGTH_SHORT +import kotlinx.android.synthetic.main.fragment_pending_operations.* +import net.taler.wallet.R +import net.taler.wallet.TAG +import net.taler.wallet.WalletViewModel +import org.json.JSONObject + +interface PendingOperationClickListener { + fun onPendingOperationClick(type: String, detail: JSONObject) + fun onPendingOperationActionClick(type: String, detail: JSONObject) +} + +class PendingOperationsFragment : Fragment(), PendingOperationClickListener { + + private val model: WalletViewModel by activityViewModels() + private val pendingOperationsManager by lazy { model.pendingOperationsManager } + + private val pendingAdapter = PendingOperationsAdapter(emptyList(), this) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setHasOptionsMenu(true) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_pending_operations, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + list_pending.apply { + val myLayoutManager = LinearLayoutManager(requireContext()) + val myItemDecoration = + DividerItemDecoration(requireContext(), myLayoutManager.orientation) + layoutManager = myLayoutManager + adapter = pendingAdapter + addItemDecoration(myItemDecoration) + } + + pendingOperationsManager.pendingOperations.observe(viewLifecycleOwner, Observer { + updatePending(it) + }) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.retry_pending -> { + model.retryPendingNow() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.pending_operations, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + private fun updatePending(pendingOperations: List) { + pendingAdapter.update(pendingOperations) + } + + override fun onPendingOperationClick(type: String, detail: JSONObject) { + Snackbar.make(view!!, "No detail view for $type implemented yet.", LENGTH_SHORT).show() + } + + override fun onPendingOperationActionClick(type: String, detail: JSONObject) { + when (type) { + "proposal-choice" -> { + Log.v(TAG, "got action click on proposal-choice") + val proposalId = detail.optString("proposalId", "") + if (proposalId == "") { + return + } + model.paymentManager.abortProposal(proposalId) + } + } + } + +} + +class PendingOperationsAdapter( + private var items: List, + private val listener: PendingOperationClickListener +) : + RecyclerView.Adapter() { + + init { + setHasStableIds(false) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { + val rowView = + LayoutInflater.from(parent.context).inflate(R.layout.pending_row, parent, false) + return MyViewHolder(rowView) + } + + override fun getItemCount(): Int { + return items.size + } + + override fun onBindViewHolder(holder: MyViewHolder, position: Int) { + val p = items[position] + val pendingContainer = holder.rowView.findViewById(R.id.pending_container) + pendingContainer.setOnClickListener { + listener.onPendingOperationClick(p.type, p.detail) + } + when (p.type) { + "proposal-choice" -> { + val btn1 = holder.rowView.findViewById(R.id.button_pending_action_1) + btn1.text = btn1.context.getString(R.string.pending_operations_refuse) + btn1.visibility = VISIBLE + btn1.setOnClickListener { + listener.onPendingOperationActionClick(p.type, p.detail) + } + } + else -> { + val btn1 = holder.rowView.findViewById(R.id.button_pending_action_1) + btn1.text = btn1.context.getString(R.string.pending_operations_no_action) + btn1.visibility = GONE + btn1.setOnClickListener {} + } + } + val textView = holder.rowView.findViewById(R.id.pending_text) + val subTextView = holder.rowView.findViewById(R.id.pending_subtext) + subTextView.text = p.detail.toString(1) + textView.text = p.type + } + + fun update(items: List) { + this.items = items + this.notifyDataSetChanged() + } + + class MyViewHolder(val rowView: View) : RecyclerView.ViewHolder(rowView) + +} diff --git a/app/src/main/java/net/taler/wallet/pending/PendingOperationsManager.kt b/app/src/main/java/net/taler/wallet/pending/PendingOperationsManager.kt new file mode 100644 index 0000000..b6d5904 --- /dev/null +++ b/app/src/main/java/net/taler/wallet/pending/PendingOperationsManager.kt @@ -0,0 +1,60 @@ +/* + * 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 + */ + +package net.taler.wallet.pending + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import net.taler.wallet.TAG +import net.taler.wallet.backend.WalletBackendApi +import org.json.JSONObject + +open class PendingOperationInfo( + val type: String, + val detail: JSONObject +) + +class PendingOperationsManager(private val walletBackendApi: WalletBackendApi) { + + private var activeGetPending = 0 + + val pendingOperations = MutableLiveData>() + + internal fun getPending() { + if (activeGetPending > 0) { + return + } + activeGetPending++ + walletBackendApi.sendRequest("getPendingOperations", null) { isError, result -> + activeGetPending-- + if (isError) { + Log.i(TAG, "got getPending error result") + return@sendRequest + } + Log.i(TAG, "got getPending result") + val pendingList = mutableListOf() + val pendingJson = result.getJSONArray("pendingOperations") + for (i in 0 until pendingJson.length()) { + val p = pendingJson.getJSONObject(i) + val type = p.getString("type") + pendingList.add(PendingOperationInfo(type, p)) + } + Log.i(TAG, "Got ${pendingList.size} pending operations") + pendingOperations.postValue((pendingList)) + } + } + +} diff --git a/app/src/main/res/layout/fragment_pending_operations.xml b/app/src/main/res/layout/fragment_pending_operations.xml new file mode 100644 index 0000000..26c1be1 --- /dev/null +++ b/app/src/main/res/layout/fragment_pending_operations.xml @@ -0,0 +1,34 @@ + + + + + + + diff --git a/app/src/main/res/layout/fragment_show_balance.xml b/app/src/main/res/layout/fragment_show_balance.xml index af003eb..db50754 100644 --- a/app/src/main/res/layout/fragment_show_balance.xml +++ b/app/src/main/res/layout/fragment_show_balance.xml @@ -34,7 +34,8 @@ android:id="@+id/list_balances" android:layout_width="match_parent" android:layout_height="wrap_content" - android:scrollbars="vertical" /> + android:scrollbars="vertical" + tools:listitem="@layout/balance_row" /> - - - - + diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml index f06f0ab..7a54077 100644 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -31,6 +31,10 @@ android:id="@+id/nav_settings" android:icon="@drawable/ic_menu_manage" android:title="@string/menu_settings" /> + diff --git a/app/src/main/res/menu/balance.xml b/app/src/main/res/menu/balance.xml index 15a6016..69b5def 100644 --- a/app/src/main/res/menu/balance.xml +++ b/app/src/main/res/menu/balance.xml @@ -21,9 +21,4 @@ android:orderInCategory="100" android:title="@string/menu_balance_reload" app:showAsAction="never" /> - diff --git a/app/src/main/res/menu/pending_operations.xml b/app/src/main/res/menu/pending_operations.xml new file mode 100644 index 0000000..980ea66 --- /dev/null +++ b/app/src/main/res/menu/pending_operations.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 2cc1eaa..3b875e7 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -99,8 +99,18 @@ app:popUpTo="@id/showBalance" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 19159b9..0b69c3c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -71,7 +71,7 @@ You\'ve already paid for this order. Withdrawal accepted - Your bank will now ask you to approve a transfer to the selected change. After you\'ve confirmed the transfer with your bank, the digital cash will show in this wallet. + The wire transfer now needs to be confirmed with the bank. Once the wire transfer is complete, the digital cash will automatically show in this wallet. Do you want to withdraw (minus exchange fees not shown in this prototype) Using the exchange provider -- cgit v1.2.3