gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-android] 01/04: Move pending operations into their own fra


From: gnunet
Subject: [taler-wallet-android] 01/04: Move pending operations into their own fragment
Date: Thu, 05 Mar 2020 16:49:36 +0100

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository wallet-android.

commit 1bbc48f7f9a893c13b07a5436a0b2b5f923de398
Author: Torsten Grote <address@hidden>
AuthorDate: Wed Mar 4 16:14:29 2020 -0300

    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 ++++++
 .../fragment_pending_operations.xml}               |  32 ++--
 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 -
 .../menu/{balance.xml => pending_operations.xml}   |   5 -
 app/src/main/res/navigation/nav_graph.xml          |  10 +
 app/src/main/res/values/strings.xml                |   2 +-
 13 files changed, 342 insertions(+), 280 deletions(-)

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<WalletBalanceAdapter.MyViewHolder>() {
-
-    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<TextView>(R.id.balance_currency)
-        currencyView.text = amount.currency
-        val amountView = 
holder.rowView.findViewById<TextView>(R.id.balance_amount)
-        amountView.text = amount.amount
-
-        val amountIncomingRow = 
holder.rowView.findViewById<View>(R.id.balance_row_pending)
-
-        val amountIncomingView = 
holder.rowView.findViewById<TextView>(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<PendingOperationsAdapter.MyViewHolder>() {
-
-    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<LinearLayout>(R.id.pending_container)
-        pendingContainer.setOnClickListener {
-            this.listener?.onPendingOperationClick(p.type, p.detail)
-        }
-        when (p.type) {
-            "proposal-choice" -> {
-                val btn1 = 
holder.rowView.findViewById<TextView>(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<TextView>(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<TextView>(R.id.pending_text)
-        val subTextView = 
holder.rowView.findViewById<TextView>(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<RecyclerView>(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<View>(R.id.pending_operations_label)
-
-        view.findViewById<RecyclerView>(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<BalanceAdapter.BalanceViewHolder>() {
+
+    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<TextView>(R.id.balance_currency)
+        currencyView.text = amount.currency
+        val amountView = 
holder.rowView.findViewById<TextView>(R.id.balance_amount)
+        amountView.text = amount.amount
+
+        val amountIncomingRow = 
holder.rowView.findViewById<View>(R.id.balance_row_pending)
+
+        val amountIncomingView = 
holder.rowView.findViewById<TextView>(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<BalanceEntry>)
 
-open class PendingOperationInfo(
-    val type: String,
-    val detail: JSONObject
-)
-
-open class PendingOperations(
-    val pending: List<PendingOperationInfo>
-)
-
 
 @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<PendingOperations>().apply {
-        value = PendingOperations(listOf())
-    }
-
     private val mHistoryProgress = MutableLiveData<Boolean>()
     val historyProgress: LiveData<Boolean> = mHistoryProgress
 
@@ -84,9 +72,16 @@ class WalletViewModel(val app: Application) : 
AndroidViewModel(app) {
     val showProgressBar = MutableLiveData<Boolean>()
 
     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<PendingOperationInfo>()
-            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<Message>()
     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<WalletBackendApi>(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 <http://www.gnu.org/licenses/>
+ */
+
+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<PendingOperationInfo>) {
+        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<PendingOperationInfo>,
+    private val listener: PendingOperationClickListener
+) :
+    RecyclerView.Adapter<PendingOperationsAdapter.MyViewHolder>() {
+
+    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<LinearLayout>(R.id.pending_container)
+        pendingContainer.setOnClickListener {
+            listener.onPendingOperationClick(p.type, p.detail)
+        }
+        when (p.type) {
+            "proposal-choice" -> {
+                val btn1 = 
holder.rowView.findViewById<TextView>(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<TextView>(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<TextView>(R.id.pending_text)
+        val subTextView = 
holder.rowView.findViewById<TextView>(R.id.pending_subtext)
+        subTextView.text = p.detail.toString(1)
+        textView.text = p.type
+    }
+
+    fun update(items: List<PendingOperationInfo>) {
+        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 <http://www.gnu.org/licenses/>
+ */
+
+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<List<PendingOperationInfo>>()
+
+    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<PendingOperationInfo>()
+            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/menu/activity_main_drawer.xml 
b/app/src/main/res/layout/fragment_pending_operations.xml
similarity index 50%
copy from app/src/main/res/menu/activity_main_drawer.xml
copy to app/src/main/res/layout/fragment_pending_operations.xml
index f06f0ab..26c1be1 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/layout/fragment_pending_operations.xml
@@ -14,23 +14,21 @@
   ~ GNU Taler; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
   -->
 
-<menu xmlns:android="http://schemas.android.com/apk/res/android";
+<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";
-        tools:showIn="navigation_view">
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
 
-    <group android:checkableBehavior="single">
-        <item
-                android:id="@+id/nav_home"
-                android:icon="@drawable/ic_home_black_24dp"
-                android:title="@string/menu_home" />
-        <item
-                android:id="@+id/nav_history"
-                android:icon="@drawable/ic_history_black_24dp"
-                android:title="@string/menu_history" />
-        <item
-                android:id="@+id/nav_settings"
-                android:icon="@drawable/ic_menu_manage"
-                android:title="@string/menu_settings" />
-    </group>
+    <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/list_pending"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:scrollbars="vertical"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            tools:listitem="@layout/pending_row" />
 
-</menu>
+</androidx.constraintlayout.widget.ConstraintLayout>
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" />
 
         <TextView
                 android:id="@+id/list_balances_placeholder"
@@ -60,17 +61,6 @@
                 android:layout_height="wrap_content"
                 android:text="@string/button_scan_qr_code" />
 
-        <TextView
-                android:id="@+id/pending_operations_label"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/pending_operations_label" />
-
-        <androidx.recyclerview.widget.RecyclerView
-                android:id="@+id/list_pending"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:scrollbars="vertical" />
-
     </LinearLayout>
+
 </androidx.core.widget.NestedScrollView>
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" />
+        <item
+                android:id="@+id/nav_pending_operations"
+                android:icon="@drawable/history_refresh"
+                android:title="Pending Operations" />
     </group>
 
 </menu>
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" />
-    <item
-            android:id="@+id/retry_pending"
-            android:orderInCategory="100"
-            android:title="@string/menu_retry_pending_operations"
-            app:showAsAction="never" />
 </menu>
diff --git a/app/src/main/res/menu/balance.xml 
b/app/src/main/res/menu/pending_operations.xml
similarity index 85%
copy from app/src/main/res/menu/balance.xml
copy to app/src/main/res/menu/pending_operations.xml
index 15a6016..980ea66 100644
--- a/app/src/main/res/menu/balance.xml
+++ b/app/src/main/res/menu/pending_operations.xml
@@ -16,11 +16,6 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android";
         xmlns:app="http://schemas.android.com/apk/res-auto";>
-    <item
-            android:id="@+id/reload_balance"
-            android:orderInCategory="100"
-            android:title="@string/menu_balance_reload"
-            app:showAsAction="never" />
     <item
             android:id="@+id/retry_pending"
             android:orderInCategory="100"
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" />
     </fragment>
 
+    <fragment
+            android:id="@+id/nav_pending_operations"
+            android:name="net.taler.wallet.pending.PendingOperationsFragment"
+            android:label="Pending Operations"
+            tools:layout="@layout/fragment_pending_operations" />
+
     <action
             android:id="@+id/action_global_promptPayment"
             app:destination="@id/promptPayment" />
 
+    <action
+            android:id="@+id/action_global_pending_operations"
+            app:destination="@id/nav_pending_operations" />
+
 </navigation>
\ 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 @@
     <string name="payment_already_paid">You\'ve already paid for this 
order.</string>
 
     <string name="withdraw_accepted">Withdrawal accepted</string>
-    <string name="withdraw_success_info">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.</string>
+    <string name="withdraw_success_info">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.</string>
     <string name="withdraw_do_you_want">Do you want to withdraw</string>
     <string name="withdraw_fees">(minus exchange fees not shown in this 
prototype)</string>
     <string name="withdraw_exchange">Using the exchange provider</string>

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]