gnunet-svn
[Top][All Lists]
Advanced

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

[taler-taler-android] branch master updated (ea2abca -> f920fa7)


From: gnunet
Subject: [taler-taler-android] branch master updated (ea2abca -> f920fa7)
Date: Thu, 16 Apr 2020 20:07:29 +0200

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

torsten-grote pushed a change to branch master
in repository taler-android.

    from ea2abca  [wallet] show simplified transactions per currency
     new 0682c6b  [wallet] change main screen if there is only one currency
     new be8c9a2  [wallet] Add unique ID to transactions
     new f920fa7  [wallet] allow transactions to be selected by long tap

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../main/res/drawable/selectable_background.xml    |  5 --
 merchant-terminal/src/main/res/values/colors.xml   |  6 --
 .../main/res/drawable/selectable_background.xml    | 10 ++-
 .../src/main/res/values-night/colors.xml           |  0
 .../src/main/res/values/colors.xml                 | 10 +--
 wallet/build.gradle                                |  4 +
 .../src/main/java/net/taler/wallet/MainActivity.kt | 10 +--
 .../src/main/java/net/taler/wallet/MainFragment.kt | 81 ++++---------------
 wallet/src/main/java/net/taler/wallet/Utils.kt     | 11 +++
 .../taler/wallet/{ => balances}/BalanceAdapter.kt  |  6 +-
 .../BalancesFragment.kt}                           | 66 ++++------------
 .../net/taler/wallet/transactions/Transaction.kt   | 48 +++++++-----
 .../wallet/transactions/TransactionAdapter.kt      | 47 +++++++++--
 .../wallet/transactions/TransactionsFragment.kt    | 91 +++++++++++++++++++---
 .../src/main/res/drawable/ic_delete.xml            |  3 +-
 wallet/src/main/res/drawable/ic_select_all.xml     | 10 +++
 ...ment_transactions.xml => fragment_balances.xml} | 29 ++++---
 wallet/src/main/res/layout/fragment_main.xml       | 22 +-----
 .../src/main/res/layout/fragment_transactions.xml  |  7 +-
 .../src/main/res/layout/list_item_transaction.xml  |  3 +-
 .../src/main/res/menu/transactions_action_mode.xml | 17 ++--
 wallet/src/main/res/navigation/nav_graph.xml       | 50 ++++++------
 wallet/src/main/res/values/colors.xml              |  3 -
 wallet/src/main/res/values/strings.xml             |  3 +
 wallet/src/main/res/values/styles.xml              |  2 +
 25 files changed, 290 insertions(+), 254 deletions(-)
 delete mode 100644 
merchant-terminal/src/main/res/drawable/selectable_background.xml
 rename wallet/src/main/res/menu/fragment_main.xml => 
taler-kotlin-common/src/main/res/drawable/selectable_background.xml (72%)
 rename {merchant-terminal => 
taler-kotlin-common}/src/main/res/values-night/colors.xml (100%)
 copy {wallet => taler-kotlin-common}/src/main/res/values/colors.xml (77%)
 rename wallet/src/main/java/net/taler/wallet/{ => balances}/BalanceAdapter.kt 
(94%)
 copy wallet/src/main/java/net/taler/wallet/{MainFragment.kt => 
balances/BalancesFragment.kt} (59%)
 copy cashier/src/main/res/drawable/ic_clear.xml => 
wallet/src/main/res/drawable/ic_delete.xml (60%)
 create mode 100644 wallet/src/main/res/drawable/ic_select_all.xml
 copy wallet/src/main/res/layout/{fragment_transactions.xml => 
fragment_balances.xml} (71%)
 copy cashier/src/main/res/menu/balance.xml => 
wallet/src/main/res/menu/transactions_action_mode.xml (73%)

diff --git a/merchant-terminal/src/main/res/drawable/selectable_background.xml 
b/merchant-terminal/src/main/res/drawable/selectable_background.xml
deleted file mode 100644
index b82de92..0000000
--- a/merchant-terminal/src/main/res/drawable/selectable_background.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<selector xmlns:android="http://schemas.android.com/apk/res/android";>
-    <item android:drawable="@color/selectedBackground" 
android:state_activated="true" />
-    <item android:drawable="@android:color/transparent" />
-</selector>
\ No newline at end of file
diff --git a/merchant-terminal/src/main/res/values/colors.xml 
b/merchant-terminal/src/main/res/values/colors.xml
index bf0c849..950c107 100644
--- a/merchant-terminal/src/main/res/values/colors.xml
+++ b/merchant-terminal/src/main/res/values/colors.xml
@@ -4,11 +4,5 @@
     <color name="colorPrimaryDark">#5D4037</color>
     <color name="colorAccent">#FFEB3B</color>
 
-    <color name="highlightedBackground">#E4E4E4</color>
-    <color name="selectedBackground">#DADADA</color>
     <color name="bottomButtons">#9E9D24</color>
-
-    <color name="green">#388E3C</color>
-    <color name="red">#C62828</color>
-
 </resources>
diff --git a/wallet/src/main/res/menu/fragment_main.xml 
b/taler-kotlin-common/src/main/res/drawable/selectable_background.xml
similarity index 72%
rename from wallet/src/main/res/menu/fragment_main.xml
rename to taler-kotlin-common/src/main/res/drawable/selectable_background.xml
index d4568d4..3c383a8 100644
--- a/wallet/src/main/res/menu/fragment_main.xml
+++ b/taler-kotlin-common/src/main/res/drawable/selectable_background.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ~ This file is part of GNU Taler
   ~ (C) 2020 Taler Systems S.A.
   ~
@@ -14,6 +15,7 @@
   ~ GNU Taler; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
   -->
 
-<menu xmlns:android="http://schemas.android.com/apk/res/android";
-    xmlns:app="http://schemas.android.com/apk/res-auto";>
-</menu>
+<selector xmlns:android="http://schemas.android.com/apk/res/android";>
+    <item android:drawable="@color/selectedBackground" 
android:state_activated="true" />
+    <item android:drawable="@android:color/transparent" />
+</selector>
diff --git a/merchant-terminal/src/main/res/values-night/colors.xml 
b/taler-kotlin-common/src/main/res/values-night/colors.xml
similarity index 100%
rename from merchant-terminal/src/main/res/values-night/colors.xml
rename to taler-kotlin-common/src/main/res/values-night/colors.xml
diff --git a/wallet/src/main/res/values/colors.xml 
b/taler-kotlin-common/src/main/res/values/colors.xml
similarity index 77%
copy from wallet/src/main/res/values/colors.xml
copy to taler-kotlin-common/src/main/res/values/colors.xml
index a6b1731..c916442 100644
--- a/wallet/src/main/res/values/colors.xml
+++ b/taler-kotlin-common/src/main/res/values/colors.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ~ This file is part of GNU Taler
   ~ (C) 2020 Taler Systems S.A.
   ~
@@ -15,10 +16,9 @@
   -->
 
 <resources>
-    <color name="colorPrimary">#283593</color>
-    <color name="colorPrimaryDark">#1A237E</color>
-    <color name="colorAccent">#AE1010</color>
+    <color name="highlightedBackground">#E4E4E4</color>
+    <color name="selectedBackground">#DADADA</color>
 
+    <color name="green">#388E3C</color>
     <color name="red">#C62828</color>
-    <color name="green">#558B2F</color>
 </resources>
diff --git a/wallet/build.gradle b/wallet/build.gradle
index 0095b27..a872e8c 100644
--- a/wallet/build.gradle
+++ b/wallet/build.gradle
@@ -71,6 +71,10 @@ dependencies {
     implementation 'com.google.android.material:material:1.1.0'
     implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
 
+    // Lists and Selection
+    implementation "androidx.recyclerview:recyclerview:1.1.0"
+    implementation "androidx.recyclerview:recyclerview-selection:1.1.0-rc01"
+
     // Navigation Library
     implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
     implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
diff --git a/wallet/src/main/java/net/taler/wallet/MainActivity.kt 
b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
index fa78b16..b6e9a7a 100644
--- a/wallet/src/main/java/net/taler/wallet/MainActivity.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainActivity.kt
@@ -75,7 +75,7 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
 
         setSupportActionBar(toolbar)
         val appBarConfiguration = AppBarConfiguration(
-            setOf(R.id.showBalance, R.id.settings, 
R.id.nav_pending_operations),
+            setOf(R.id.nav_main, R.id.nav_settings, 
R.id.nav_pending_operations),
             drawer_layout
         )
         toolbar.setupWithNavController(nav, appBarConfiguration)
@@ -113,8 +113,8 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
 
     override fun onNavigationItemSelected(item: MenuItem): Boolean {
         when (item.itemId) {
-            R.id.nav_home -> nav.navigate(R.id.showBalance)
-            R.id.nav_settings -> nav.navigate(R.id.settings)
+            R.id.nav_home -> nav.navigate(R.id.nav_main)
+            R.id.nav_settings -> nav.navigate(R.id.nav_settings)
             R.id.nav_pending_operations -> 
nav.navigate(R.id.nav_pending_operations)
         }
         drawer_layout.closeDrawer(START)
@@ -142,12 +142,12 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
         when {
             url.toLowerCase(ROOT).startsWith("taler://pay/") -> {
                 Log.v(TAG, "navigating!")
-                nav.navigate(R.id.action_showBalance_to_promptPayment)
+                nav.navigate(R.id.action_nav_main_to_promptPayment)
                 model.paymentManager.preparePay(url)
             }
             url.toLowerCase(ROOT).startsWith("taler://withdraw/") -> {
                 Log.v(TAG, "navigating!")
-                nav.navigate(R.id.action_showBalance_to_promptWithdraw)
+                nav.navigate(R.id.action_nav_main_to_promptWithdraw)
                 model.withdrawManager.getWithdrawalInfo(url)
             }
             url.toLowerCase(ROOT).startsWith("taler://refund/") -> {
diff --git a/wallet/src/main/java/net/taler/wallet/MainFragment.kt 
b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
index e0e6f51..0bc6084 100644
--- a/wallet/src/main/java/net/taler/wallet/MainFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainFragment.kt
@@ -17,41 +17,20 @@
 package net.taler.wallet
 
 import android.os.Bundle
-import android.transition.TransitionManager.beginDelayedTransition
 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 androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
-import androidx.navigation.fragment.findNavController
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
-import com.google.zxing.integration.android.IntentIntegrator
-import com.google.zxing.integration.android.IntentIntegrator.QR_CODE
 import kotlinx.android.synthetic.main.fragment_main.*
+import net.taler.wallet.balances.BalancesFragment
+import net.taler.wallet.transactions.TransactionsFragment
 
-interface BalanceClickListener {
-    fun onBalanceClick(currency: String)
-}
-
-class MainFragment : Fragment(), BalanceClickListener {
+class MainFragment : Fragment() {
 
     private val model: MainViewModel by activityViewModels()
 
-    private val balancesAdapter = BalanceAdapter(this)
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setHasOptionsMenu(true)
-    }
-
     override fun onCreateView(
         inflater: LayoutInflater,
         container: ViewGroup?,
@@ -61,18 +40,12 @@ class MainFragment : Fragment(), BalanceClickListener {
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        mainList.apply {
-            layoutManager = LinearLayoutManager(context)
-            adapter = balancesAdapter
-            addItemDecoration(DividerItemDecoration(context, VERTICAL))
-        }
-
         model.balances.observe(viewLifecycleOwner, Observer {
             onBalancesChanged(it.values.toList())
         })
 
         mainFab.setOnClickListener {
-            onScanButtonClicked()
+            scanQrCode(requireActivity())
         }
     }
 
@@ -81,44 +54,18 @@ class MainFragment : Fragment(), BalanceClickListener {
         model.loadBalances()
     }
 
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        return when (item.itemId) {
-            else -> super.onOptionsItemSelected(item)
-        }
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
-        inflater.inflate(R.menu.fragment_main, menu)
-        super.onCreateOptionsMenu(menu, inflater)
-    }
-
-    private fun onScanButtonClicked() {
-        IntentIntegrator(activity).apply {
-            setPrompt("")
-            setBeepEnabled(true)
-            setOrientationLocked(false)
-        }.initiateScan(listOf(QR_CODE))
-    }
-
     private fun onBalancesChanged(balances: List<BalanceItem>) {
-        delayedTransition()
-        if (balances.isEmpty()) {
-            mainEmptyState.visibility = VISIBLE
-            mainList.visibility = GONE
-        } else {
-            balancesAdapter.setItems(balances)
-            mainEmptyState.visibility = GONE
-            mainList.visibility = VISIBLE
+        if (childFragmentManager.fragments.isEmpty()) {
+            val f = if (balances.size == 1) {
+                model.transactionManager.selectedCurrency = 
balances[0].available.currency
+                TransactionsFragment()
+            } else {
+                BalancesFragment()
+            }
+            childFragmentManager.beginTransaction()
+                .add(R.id.mainFragmentContainer, f)
+                .commitNow()
         }
     }
 
-    private fun delayedTransition() {
-        beginDelayedTransition(view as ViewGroup)
-    }
-
-    override fun onBalanceClick(currency: String) {
-        model.transactionManager.selectedCurrency = currency
-        findNavController().navigate(R.id.nav_transactions)
-    }
-
 }
diff --git a/wallet/src/main/java/net/taler/wallet/Utils.kt 
b/wallet/src/main/java/net/taler/wallet/Utils.kt
index ae8712f..b41a202 100644
--- a/wallet/src/main/java/net/taler/wallet/Utils.kt
+++ b/wallet/src/main/java/net/taler/wallet/Utils.kt
@@ -16,6 +16,17 @@
 
 package net.taler.wallet
 
+import android.app.Activity
+import com.google.zxing.integration.android.IntentIntegrator
+
+fun scanQrCode(activity: Activity) {
+    IntentIntegrator(activity).apply {
+        setPrompt("")
+        setBeepEnabled(true)
+        setOrientationLocked(false)
+    }.initiateScan(listOf(IntentIntegrator.QR_CODE))
+}
+
 fun cleanExchange(exchange: String) = exchange.let {
     if (it.startsWith("https://";)) it.substring(8) else it
 }.trimEnd('/')
diff --git a/wallet/src/main/java/net/taler/wallet/BalanceAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
similarity index 94%
rename from wallet/src/main/java/net/taler/wallet/BalanceAdapter.kt
rename to wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
index b7b2ef0..0ccfeb2 100644
--- a/wallet/src/main/java/net/taler/wallet/BalanceAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalanceAdapter.kt
@@ -14,7 +14,7 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet
+package net.taler.wallet.balances
 
 import android.view.LayoutInflater
 import android.view.View
@@ -24,7 +24,9 @@ import android.view.ViewGroup
 import android.widget.TextView
 import androidx.recyclerview.widget.RecyclerView
 import androidx.recyclerview.widget.RecyclerView.Adapter
-import net.taler.wallet.BalanceAdapter.BalanceViewHolder
+import net.taler.wallet.BalanceItem
+import net.taler.wallet.R
+import net.taler.wallet.balances.BalanceAdapter.BalanceViewHolder
 
 class BalanceAdapter(private val listener: BalanceClickListener) : 
Adapter<BalanceViewHolder>() {
 
diff --git a/wallet/src/main/java/net/taler/wallet/MainFragment.kt 
b/wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt
similarity index 59%
copy from wallet/src/main/java/net/taler/wallet/MainFragment.kt
copy to wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt
index e0e6f51..0a2b29a 100644
--- a/wallet/src/main/java/net/taler/wallet/MainFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/balances/BalancesFragment.kt
@@ -14,16 +14,14 @@
  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-package net.taler.wallet
+package net.taler.wallet.balances
 
 import android.os.Bundle
 import android.transition.TransitionManager.beginDelayedTransition
 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.INVISIBLE
 import android.view.View.VISIBLE
 import android.view.ViewGroup
 import androidx.fragment.app.Fragment
@@ -31,38 +29,34 @@ import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
 import androidx.navigation.fragment.findNavController
 import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
-import com.google.zxing.integration.android.IntentIntegrator
-import com.google.zxing.integration.android.IntentIntegrator.QR_CODE
-import kotlinx.android.synthetic.main.fragment_main.*
+import kotlinx.android.synthetic.main.fragment_balances.*
+import net.taler.common.fadeIn
+import net.taler.wallet.BalanceItem
+import net.taler.wallet.MainViewModel
+import net.taler.wallet.R
 
 interface BalanceClickListener {
     fun onBalanceClick(currency: String)
 }
 
-class MainFragment : Fragment(), BalanceClickListener {
+class BalancesFragment : Fragment(),
+    BalanceClickListener {
 
     private val model: MainViewModel by activityViewModels()
 
     private val balancesAdapter = BalanceAdapter(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_main, container, false)
+        return inflater.inflate(R.layout.fragment_balances, container, false)
     }
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         mainList.apply {
-            layoutManager = LinearLayoutManager(context)
             adapter = balancesAdapter
             addItemDecoration(DividerItemDecoration(context, VERTICAL))
         }
@@ -70,55 +64,23 @@ class MainFragment : Fragment(), BalanceClickListener {
         model.balances.observe(viewLifecycleOwner, Observer {
             onBalancesChanged(it.values.toList())
         })
-
-        mainFab.setOnClickListener {
-            onScanButtonClicked()
-        }
-    }
-
-    override fun onStart() {
-        super.onStart()
-        model.loadBalances()
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        return when (item.itemId) {
-            else -> super.onOptionsItemSelected(item)
-        }
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
-        inflater.inflate(R.menu.fragment_main, menu)
-        super.onCreateOptionsMenu(menu, inflater)
-    }
-
-    private fun onScanButtonClicked() {
-        IntentIntegrator(activity).apply {
-            setPrompt("")
-            setBeepEnabled(true)
-            setOrientationLocked(false)
-        }.initiateScan(listOf(QR_CODE))
     }
 
     private fun onBalancesChanged(balances: List<BalanceItem>) {
-        delayedTransition()
+        beginDelayedTransition(view as ViewGroup)
         if (balances.isEmpty()) {
             mainEmptyState.visibility = VISIBLE
             mainList.visibility = GONE
         } else {
             balancesAdapter.setItems(balances)
-            mainEmptyState.visibility = GONE
-            mainList.visibility = VISIBLE
+            mainEmptyState.visibility = INVISIBLE
+            mainList.fadeIn()
         }
     }
 
-    private fun delayedTransition() {
-        beginDelayedTransition(view as ViewGroup)
-    }
-
     override fun onBalanceClick(currency: String) {
         model.transactionManager.selectedCurrency = currency
-        findNavController().navigate(R.id.nav_transactions)
+        findNavController().navigate(R.id.action_nav_main_to_nav_transactions)
     }
 
 }
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
index c0142d5..34942d0 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transaction.kt
@@ -18,7 +18,6 @@ package net.taler.wallet.transactions
 
 import androidx.annotation.DrawableRes
 import androidx.annotation.LayoutRes
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties
 import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY
 import com.fasterxml.jackson.annotation.JsonProperty
@@ -140,13 +139,9 @@ ReserveCreated = "reserve-created",
     Type(value = RefundTransaction::class, name = "refund"),
     Type(value = RefreshTransaction::class, name = "refreshed")
 )
-@JsonIgnoreProperties(
-    value = [
-        "eventId"
-    ]
-)
 abstract class Transaction(
     val timestamp: Timestamp,
+    val eventId: String,
     @get:LayoutRes
     open val detailPageLayout: Int = 0,
     @get:DrawableRes
@@ -160,24 +155,26 @@ abstract class Transaction(
 }
 
 
-class UnknownTransaction(timestamp: Timestamp) : Transaction(timestamp) {
+class UnknownTransaction(timestamp: Timestamp, eventId: String) : 
Transaction(timestamp, eventId) {
     override val title: String? = null
 }
 
 @JsonTypeName("exchange-added")
 class ExchangeAddedEvent(
     timestamp: Timestamp,
+    eventId: String,
     val exchangeBaseUrl: String,
     val builtIn: Boolean
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val title = cleanExchange(exchangeBaseUrl)
 }
 
 @JsonTypeName("exchange-updated")
 class ExchangeUpdatedEvent(
     timestamp: Timestamp,
+    eventId: String,
     val exchangeBaseUrl: String
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val title = cleanExchange(exchangeBaseUrl)
 }
 
@@ -185,6 +182,7 @@ class ExchangeUpdatedEvent(
 @JsonTypeName("reserve-balance-updated")
 class ReserveBalanceUpdatedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Condensed information about the reserve.
      */
@@ -202,7 +200,7 @@ class ReserveBalanceUpdatedTransaction(
      * Amount that hasn't been withdrawn yet.
      */
     val reserveUnclaimedAmount: Amount
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val title: String? = null
     override val displayAmount = DisplayAmount(reserveBalance, 
AmountType.Neutral)
     override fun isCurrency(currency: String) = reserveBalance.currency == 
currency
@@ -211,6 +209,7 @@ class ReserveBalanceUpdatedTransaction(
 @JsonTypeName("withdrawn")
 class WithdrawTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Exchange that was withdrawn from.
      */
@@ -230,7 +229,7 @@ class WithdrawTransaction(
      * Amount that actually was added to the wallet's balance.
      */
     val amountWithdrawnEffective: Amount
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val detailPageLayout = R.layout.fragment_event_withdraw
     override val title = cleanExchange(exchangeBaseUrl)
     override val icon = R.drawable.transaction_withdrawal
@@ -242,11 +241,12 @@ class WithdrawTransaction(
 @JsonTypeName("order-accepted")
 class OrderAcceptedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Condensed info about the order.
      */
     val orderShortInfo: OrderShortInfo
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.ic_add_circle
     override val title: String? = null
     override fun isCurrency(currency: String) = orderShortInfo.amount.currency 
== currency
@@ -255,11 +255,12 @@ class OrderAcceptedTransaction(
 @JsonTypeName("order-refused")
 class OrderRefusedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Condensed info about the order.
      */
     val orderShortInfo: OrderShortInfo
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.ic_cancel
     override val title: String? = null
     override fun isCurrency(currency: String) = orderShortInfo.amount.currency 
== currency
@@ -268,6 +269,7 @@ class OrderRefusedTransaction(
 @JsonTypeName("payment-sent")
 class PaymentTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Condensed info about the order that we already paid for.
      */
@@ -289,7 +291,7 @@ class PaymentTransaction(
      * Session ID that the payment was (re-)submitted under.
      */
     val sessionId: String?
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val detailPageLayout = R.layout.fragment_event_paid
     override val title = orderShortInfo.summary
     override val icon = R.drawable.ic_cash_usd_outline
@@ -301,6 +303,7 @@ class PaymentTransaction(
 @JsonTypeName("payment-aborted")
 class PaymentAbortedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Condensed info about the order that we already paid for.
      */
@@ -309,7 +312,7 @@ class PaymentAbortedTransaction(
      * Amount that was lost due to refund and refreshing fees.
      */
     val amountLost: Amount
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val title = orderShortInfo.summary
     override val icon = R.drawable.transaction_payment_aborted
     override val showToUser = true
@@ -320,6 +323,7 @@ class PaymentAbortedTransaction(
 @JsonTypeName("refreshed")
 class RefreshTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Amount that is now available again because it has
      * been refreshed.
@@ -341,7 +345,7 @@ class RefreshTransaction(
      * more refresh session IDs.
      */
     val refreshGroupId: String
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.transaction_refresh
     override val title: String? = null
     override val showToUser = !(amountRefreshedRaw - 
amountRefreshedEffective).isZero()
@@ -360,6 +364,7 @@ class RefreshTransaction(
 @JsonTypeName("order-redirected")
 class OrderRedirectedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Condensed info about the new order that contains a
      * product (identified by the fulfillment URL) that we've already paid for.
@@ -369,7 +374,7 @@ class OrderRedirectedTransaction(
      * Condensed info about the order that we already paid for.
      */
     val alreadyPaidOrderShortInfo: OrderShortInfo
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.ic_directions
     override val title = newOrderShortInfo.summary
     override fun isCurrency(currency: String) = 
newOrderShortInfo.amount.currency == currency
@@ -378,6 +383,7 @@ class OrderRedirectedTransaction(
 @JsonTypeName("tip-accepted")
 class TipAcceptedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Unique identifier for the tip to query more information.
      */
@@ -386,7 +392,7 @@ class TipAcceptedTransaction(
      * Raw amount of the tip, without extra fees that apply.
      */
     val tipRaw: Amount
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.transaction_tip_accepted
     override val title: String? = null
     override val showToUser = true
@@ -397,6 +403,7 @@ class TipAcceptedTransaction(
 @JsonTypeName("tip-declined")
 class TipDeclinedTransaction(
     timestamp: Timestamp,
+    eventId: String,
     /**
      * Unique identifier for the tip to query more information.
      */
@@ -405,7 +412,7 @@ class TipDeclinedTransaction(
      * Raw amount of the tip, without extra fees that apply.
      */
     val tipAmount: Amount
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.transaction_tip_declined
     override val title: String? = null
     override val showToUser = true
@@ -416,6 +423,7 @@ class TipDeclinedTransaction(
 @JsonTypeName("refund")
 class RefundTransaction(
     timestamp: Timestamp,
+    eventId: String,
     val orderShortInfo: OrderShortInfo,
     /**
      * Unique identifier for this refund.
@@ -435,7 +443,7 @@ class RefundTransaction(
      * Amount will be added to the wallet's balance after fees and refreshing.
      */
     val amountRefundedEffective: Amount
-) : Transaction(timestamp) {
+) : Transaction(timestamp, eventId) {
     override val icon = R.drawable.transaction_refund
     override val title = orderShortInfo.summary
     override val detailPageLayout = R.layout.fragment_event_paid
diff --git 
a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt 
b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
index 809f6a9..a72b8a8 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -18,13 +18,17 @@ package net.taler.wallet.transactions
 
 import android.content.Context
 import android.view.LayoutInflater
+import android.view.MotionEvent
 import android.view.View
 import android.view.View.GONE
 import android.view.View.VISIBLE
 import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.TextView
-import androidx.annotation.CallSuper
+import androidx.recyclerview.selection.ItemDetailsLookup
+import androidx.recyclerview.selection.ItemKeyProvider
+import androidx.recyclerview.selection.SelectionTracker
+import androidx.recyclerview.widget.RecyclerView
 import androidx.recyclerview.widget.RecyclerView.Adapter
 import androidx.recyclerview.widget.RecyclerView.ViewHolder
 import net.taler.common.exhaustive
@@ -39,6 +43,9 @@ internal class TransactionAdapter(
     private var transactions: Transactions = Transactions()
 ) : Adapter<TransactionViewHolder>() {
 
+    lateinit var tracker: SelectionTracker<String>
+    val keyProvider = TransactionKeyProvider()
+
     init {
         setHasStableIds(false)
     }
@@ -52,8 +59,8 @@ internal class TransactionAdapter(
     override fun getItemCount(): Int = transactions.size
 
     override fun onBindViewHolder(holder: TransactionViewHolder, position: 
Int) {
-        val event = transactions[position]
-        holder.bind(event)
+        val transaction = transactions[position]
+        holder.bind(transaction, tracker.isSelected(transaction.eventId))
     }
 
     fun update(updatedTransactions: Transactions) {
@@ -61,6 +68,10 @@ internal class TransactionAdapter(
         this.notifyDataSetChanged()
     }
 
+    fun selectAll() = transactions.forEach {
+        tracker.select(it.eventId)
+    }
+
     internal open inner class TransactionViewHolder(private val v: View) : 
ViewHolder(v) {
 
         protected val context: Context = v.context
@@ -73,15 +84,15 @@ internal class TransactionAdapter(
         private val selectableBackground = v.background
         private val amountColor = amount.currentTextColor
 
-        @CallSuper
-        open fun bind(transaction: Transaction) {
+        open fun bind(transaction: Transaction, selected: Boolean) {
             if (devMode || transaction.detailPageLayout != 0) {
                 v.background = selectableBackground
-                v.setOnClickListener { listener.onEventClicked(transaction) }
+                v.setOnClickListener { 
listener.onTransactionClicked(transaction) }
             } else {
                 v.background = null
                 v.setOnClickListener(null)
             }
+            v.isActivated = selected
             icon.setImageResource(transaction.icon)
 
             title.text = if (transaction.title == null) {
@@ -140,4 +151,28 @@ internal class TransactionAdapter(
 
     }
 
+    internal inner class TransactionKeyProvider : 
ItemKeyProvider<String>(SCOPE_MAPPED) {
+        override fun getKey(position: Int) = transactions[position].eventId
+        override fun getPosition(key: String): Int {
+            return transactions.indexOfFirst { it.eventId == key }
+        }
+    }
+
+}
+
+internal class TransactionLookup(
+    private val list: RecyclerView,
+    private val adapter: TransactionAdapter
+) : ItemDetailsLookup<String>() {
+    override fun getItemDetails(e: MotionEvent): ItemDetails<String>? {
+        list.findChildViewUnder(e.x, e.y)?.let { view ->
+            val holder = list.getChildViewHolder(view)
+            val position = holder.adapterPosition
+            return object : ItemDetails<String>() {
+                override fun getPosition(): Int = position
+                override fun getSelectionKey(): String = 
adapter.keyProvider.getKey(position)
+            }
+        }
+        return null
+    }
 }
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 4f62547..e7adaf1 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionsFragment.kt
@@ -17,6 +17,7 @@
 package net.taler.wallet.transactions
 
 import android.os.Bundle
+import android.view.ActionMode
 import android.view.LayoutInflater
 import android.view.Menu
 import android.view.MenuInflater
@@ -25,12 +26,16 @@ 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.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
 import androidx.navigation.fragment.findNavController
+import androidx.recyclerview.selection.SelectionPredicates
+import androidx.recyclerview.selection.SelectionTracker
+import androidx.recyclerview.selection.StorageStrategy
 import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL
 import kotlinx.android.synthetic.main.fragment_transactions.*
 import net.taler.common.fadeIn
@@ -39,15 +44,18 @@ import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
 
 interface OnEventClickListener {
-    fun onEventClicked(event: Transaction)
+    fun onTransactionClicked(transaction: Transaction)
 }
 
-class TransactionsFragment : Fragment(), OnEventClickListener {
+class TransactionsFragment : Fragment(), OnEventClickListener, 
ActionMode.Callback {
 
     private val model: MainViewModel by activityViewModels()
     private val transactionManager by lazy { model.transactionManager }
+
     private val transactionAdapter by lazy { 
TransactionAdapter(model.devMode.value == true, this) }
     private val currency by lazy { transactionManager.selectedCurrency!! }
+    private var tracker: SelectionTracker<String>? = null
+    private var actionMode: ActionMode? = null
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -63,10 +71,35 @@ class TransactionsFragment : Fragment(), 
OnEventClickListener {
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         list.apply {
-            layoutManager = LinearLayoutManager(context)
             adapter = transactionAdapter
             addItemDecoration(DividerItemDecoration(context, VERTICAL))
         }
+        val tracker = SelectionTracker.Builder(
+            "transaction-selection-id",
+            list,
+            transactionAdapter.keyProvider,
+            TransactionLookup(list, transactionAdapter),
+            StorageStrategy.createStringStorage()
+        ).withSelectionPredicate(
+            SelectionPredicates.createSelectAnything()
+        ).build()
+        savedInstanceState?.let { tracker.onRestoreInstanceState(it) }
+        transactionAdapter.tracker = tracker
+        this.tracker = tracker
+        tracker.addObserver(object : 
SelectionTracker.SelectionObserver<String>() {
+            override fun onItemStateChanged(key: String, selected: Boolean) {
+                if (selected && actionMode == null) {
+                    actionMode = 
requireActivity().startActionMode(this@TransactionsFragment)
+                    updateActionModeTitle()
+                } else if (actionMode != null) {
+                    if (selected || tracker.hasSelection()) {
+                        updateActionModeTitle()
+                    } else {
+                        actionMode!!.finish()
+                    }
+                }
+            }
+        })
 
         transactionManager.progress.observe(viewLifecycleOwner, Observer { 
show ->
             progressBar.visibility = if (show) VISIBLE else INVISIBLE
@@ -89,6 +122,11 @@ class TransactionsFragment : Fragment(), 
OnEventClickListener {
         })
     }
 
+    override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+        tracker?.onSaveInstanceState(outState)
+    }
+
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
         inflater.inflate(R.menu.transactions, menu)
     }
@@ -99,12 +137,13 @@ class TransactionsFragment : Fragment(), 
OnEventClickListener {
         }
     }
 
-    override fun onEventClicked(event: Transaction) {
-        if (event.detailPageLayout != 0) {
-            transactionManager.selectedEvent = event
-            
findNavController().navigate(R.id.action_nav_transactions_to_nav_transaction_detail)
+    override fun onTransactionClicked(transaction: Transaction) {
+        if (actionMode != null) return // don't react on clicks while in 
action mode
+        if (transaction.detailPageLayout != 0) {
+            transactionManager.selectedEvent = transaction
+            findNavController().navigate(R.id.action_nav_transaction_detail)
         } else if (model.devMode.value == true) {
-            JsonDialogFragment.new(event.json.toString(2))
+            JsonDialogFragment.new(transaction.json.toString(2))
                 .show(parentFragmentManager, null)
         }
     }
@@ -118,6 +157,40 @@ class TransactionsFragment : Fragment(), 
OnEventClickListener {
         is TransactionsResult.Success -> {
             emptyState.visibility = if (result.transactions.isEmpty()) VISIBLE 
else INVISIBLE
             transactionAdapter.update(result.transactions)
+            list.fadeIn()
+        }
+    }
+
+    override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
+        val inflater = mode.menuInflater
+        inflater.inflate(R.menu.transactions_action_mode, menu)
+        return true
+    }
+
+    override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
+        return false // no update needed
+    }
+
+    override fun onActionItemClicked(mode: ActionMode, item: MenuItem): 
Boolean {
+        when (item.itemId) {
+            R.id.transaction_delete -> {
+                val s = "Not yet implemented. Pester Florian! ;)"
+                Toast.makeText(requireContext(), s, LENGTH_LONG).show()
+                mode.finish()
+            }
+            R.id.transaction_select_all -> transactionAdapter.selectAll()
+        }
+        return true
+    }
+
+    override fun onDestroyActionMode(mode: ActionMode) {
+        tracker?.clearSelection()
+        actionMode = null
+    }
+
+    private fun updateActionModeTitle() {
+        tracker?.selection?.size()?.toString()?.let { num ->
+            actionMode?.title = num
         }
     }
 
diff --git a/cashier/src/main/res/drawable/ic_clear.xml 
b/wallet/src/main/res/drawable/ic_delete.xml
similarity index 60%
copy from cashier/src/main/res/drawable/ic_clear.xml
copy to wallet/src/main/res/drawable/ic_delete.xml
index f50fd99..88caaa1 100644
--- a/cashier/src/main/res/drawable/ic_clear.xml
+++ b/wallet/src/main/res/drawable/ic_delete.xml
@@ -1,9 +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="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 
5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
+        android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 
2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z" />
 </vector>
diff --git a/wallet/src/main/res/drawable/ic_select_all.xml 
b/wallet/src/main/res/drawable/ic_select_all.xml
new file mode 100644
index 0000000..56adb23
--- /dev/null
+++ b/wallet/src/main/res/drawable/ic_select_all.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="M3,5h2L5,3c-1.1,0 -2,0.9 
-2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1
 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 
2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0
 2,-0.9 
2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"
 />
+</vector>
diff --git a/wallet/src/main/res/layout/fragment_transactions.xml 
b/wallet/src/main/res/layout/fragment_balances.xml
similarity index 71%
copy from wallet/src/main/res/layout/fragment_transactions.xml
copy to wallet/src/main/res/layout/fragment_balances.xml
index a2aebcd..84c7bca 100644
--- a/wallet/src/main/res/layout/fragment_transactions.xml
+++ b/wallet/src/main/res/layout/fragment_balances.xml
@@ -13,33 +13,30 @@
   ~ 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/>
   -->
-
 <FrameLayout 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";
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
     <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/list"
+        android:id="@+id/mainList"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:scrollbars="vertical" />
-
-    <TextView
-        android:id="@+id/emptyState"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:text="@string/transactions_empty"
         android:visibility="invisible"
+        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+        tools:listitem="@layout/list_item_balance"
         tools:visibility="visible" />
 
-    <ProgressBar
-        android:id="@+id/progressBar"
-        style="?android:progressBarStyleLarge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
+    <TextView
+        android:id="@+id/mainEmptyState"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:autoLink="web"
+        android:gravity="center"
+        android:padding="16dp"
+        android:text="@string/balances_empty_state"
+        android:textSize="18sp"
         android:visibility="invisible"
         tools:visibility="visible" />
 
diff --git a/wallet/src/main/res/layout/fragment_main.xml 
b/wallet/src/main/res/layout/fragment_main.xml
index 57fe73e..81121b5 100644
--- a/wallet/src/main/res/layout/fragment_main.xml
+++ b/wallet/src/main/res/layout/fragment_main.xml
@@ -15,29 +15,13 @@
   -->
 <androidx.coordinatorlayout.widget.CoordinatorLayout 
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";
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/mainList"
+    <androidx.fragment.app.FragmentContainerView
+        android:id="@+id/mainFragmentContainer"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="gone"
-        tools:listitem="@layout/list_item_balance"
-        tools:visibility="visible" />
-
-    <TextView
-        android:id="@+id/mainEmptyState"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:autoLink="web"
-        android:gravity="center"
-        android:padding="16dp"
-        android:text="@string/balances_empty_state"
-        android:textSize="18sp"
-        android:visibility="gone"
-        tools:visibility="visible" />
+        android:layout_height="match_parent" />
 
     <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/mainFab"
diff --git a/wallet/src/main/res/layout/fragment_transactions.xml 
b/wallet/src/main/res/layout/fragment_transactions.xml
index a2aebcd..aaf638c 100644
--- a/wallet/src/main/res/layout/fragment_transactions.xml
+++ b/wallet/src/main/res/layout/fragment_transactions.xml
@@ -15,6 +15,7 @@
   -->
 
 <FrameLayout 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";
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -23,7 +24,11 @@
         android:id="@+id/list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:scrollbars="vertical" />
+        android:scrollbars="vertical"
+        android:visibility="invisible"
+        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+        tools:listitem="@layout/list_item_transaction"
+        tools:visibility="visible" />
 
     <TextView
         android:id="@+id/emptyState"
diff --git a/wallet/src/main/res/layout/list_item_transaction.xml 
b/wallet/src/main/res/layout/list_item_transaction.xml
index a3ac980..2fabe1d 100644
--- a/wallet/src/main/res/layout/list_item_transaction.xml
+++ b/wallet/src/main/res/layout/list_item_transaction.xml
@@ -19,7 +19,8 @@
     xmlns:tools="http://schemas.android.com/tools";
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="?attr/selectableItemBackground"
+    android:background="@drawable/selectable_background"
+    android:foreground="?attr/selectableItemBackground"
     android:paddingStart="16dp"
     android:paddingTop="8dp"
     android:paddingEnd="16dp"
diff --git a/cashier/src/main/res/menu/balance.xml 
b/wallet/src/main/res/menu/transactions_action_mode.xml
similarity index 73%
copy from cashier/src/main/res/menu/balance.xml
copy to wallet/src/main/res/menu/transactions_action_mode.xml
index eac38d6..b290b9e 100644
--- a/cashier/src/main/res/menu/balance.xml
+++ b/wallet/src/main/res/menu/transactions_action_mode.xml
@@ -14,16 +14,13 @@
   ~ GNU Taler; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
   -->
 
-<menu xmlns:android="http://schemas.android.com/apk/res/android";
-    xmlns:app="http://schemas.android.com/apk/res-auto";>
-
+<menu xmlns:android="http://schemas.android.com/apk/res/android";>
     <item
-        android:id="@+id/action_reconfigure"
-        android:title="@string/action_reconfigure"
-        app:showAsAction="never" />
+        android:id="@+id/transaction_select_all"
+        android:icon="@drawable/ic_select_all"
+        android:title="@string/transactions_select_all" />
     <item
-        android:id="@+id/action_lock"
-        android:title="@string/action_lock"
-        app:showAsAction="never" />
-
+        android:id="@+id/transaction_delete"
+        android:icon="@drawable/ic_delete"
+        android:title="@string/transactions_delete" />
 </menu>
diff --git a/wallet/src/main/res/navigation/nav_graph.xml 
b/wallet/src/main/res/navigation/nav_graph.xml
index ef0f48b..f8d515e 100644
--- a/wallet/src/main/res/navigation/nav_graph.xml
+++ b/wallet/src/main/res/navigation/nav_graph.xml
@@ -18,21 +18,24 @@
     xmlns:app="http://schemas.android.com/apk/res-auto";
     xmlns:tools="http://schemas.android.com/tools";
     android:id="@+id/nav_graph"
-    app:startDestination="@id/showBalance"
-    tools:ignore="UnusedNavigation">
+    app:startDestination="@id/nav_main">
 
     <fragment
-        android:id="@+id/showBalance"
+        android:id="@+id/nav_main"
         android:name="net.taler.wallet.MainFragment"
         android:label="@string/balances_title"
-        tools:layout="@layout/fragment_main">
+        tools:layout="@layout/fragment_balances">
         <action
-            android:id="@+id/action_showBalance_to_promptPayment"
+            android:id="@+id/action_nav_main_to_promptPayment"
             app:destination="@id/promptPayment" />
         <action
-            android:id="@+id/action_showBalance_to_promptWithdraw"
+            android:id="@+id/action_nav_main_to_promptWithdraw"
             app:destination="@id/promptWithdraw" />
+        <action
+            android:id="@+id/action_nav_main_to_nav_transactions"
+            app:destination="@id/nav_transactions" />
     </fragment>
+
     <fragment
         android:id="@+id/promptPayment"
         android:name="net.taler.wallet.payment.PromptPaymentFragment"
@@ -41,31 +44,28 @@
         <action
             android:id="@+id/action_promptPayment_to_paymentSuccessful"
             app:destination="@id/paymentSuccessful"
-            app:popUpTo="@id/showBalance" />
+            app:popUpTo="@id/nav_main" />
         <action
             android:id="@+id/action_promptPayment_to_alreadyPaid"
             app:destination="@id/alreadyPaid"
-            app:popUpTo="@id/showBalance" />
+            app:popUpTo="@id/nav_main" />
     </fragment>
     <fragment
         android:id="@+id/paymentSuccessful"
         android:name="net.taler.wallet.payment.PaymentSuccessfulFragment"
         android:label="Payment Successful"
         tools:layout="@layout/fragment_payment_successful" />
+
     <fragment
-        android:id="@+id/settings"
+        android:id="@+id/nav_settings"
         android:name="net.taler.wallet.SettingsFragment"
-        android:label="Settings" />
+        android:label="@string/menu_settings" />
 
     <fragment
         android:id="@+id/nav_transactions"
         android:name="net.taler.wallet.transactions.TransactionsFragment"
         android:label="@string/transactions_title"
-        tools:layout="@layout/fragment_transactions">
-        <action
-            android:id="@+id/action_nav_transactions_to_nav_transaction_detail"
-            app:destination="@id/nav_transactions_detail" />
-    </fragment>
+        tools:layout="@layout/fragment_transactions" />
 
     <fragment
         android:id="@+id/nav_transactions_detail"
@@ -76,7 +76,7 @@
     <fragment
         android:id="@+id/alreadyPaid"
         android:name="net.taler.wallet.payment.AlreadyPaidFragment"
-        android:label="Already Paid"
+        android:label="@string/payment_already_paid_title"
         tools:layout="@layout/fragment_already_paid" />
 
     <fragment
@@ -90,11 +90,11 @@
         <action
             android:id="@+id/action_promptWithdraw_to_withdrawSuccessful"
             app:destination="@id/withdrawSuccessful"
-            app:popUpTo="@id/showBalance" />
+            app:popUpTo="@id/nav_main" />
         <action
             android:id="@+id/action_promptWithdraw_to_errorFragment"
             app:destination="@id/errorFragment"
-            app:popUpTo="@id/showBalance" />
+            app:popUpTo="@id/nav_main" />
         <action
             android:id="@+id/action_promptWithdraw_to_selectExchangeFragment"
             app:destination="@id/selectExchangeFragment" />
@@ -103,8 +103,9 @@
     <fragment
         android:id="@+id/withdrawSuccessful"
         android:name="net.taler.wallet.withdraw.WithdrawSuccessfulFragment"
-        android:label="Withdrawal Confirmed"
+        android:label="@string/withdraw_accepted"
         tools:layout="@layout/fragment_withdraw_successful" />
+
     <fragment
         android:id="@+id/reviewExchangeTOS"
         android:name="net.taler.wallet.withdraw.ReviewExchangeTosFragment"
@@ -113,7 +114,7 @@
         <action
             android:id="@+id/action_reviewExchangeTOS_to_promptWithdraw"
             app:destination="@id/promptWithdraw"
-            app:popUpTo="@id/showBalance" />
+            app:popUpTo="@id/nav_main" />
     </fragment>
     <fragment
         android:id="@+id/selectExchangeFragment"
@@ -124,8 +125,9 @@
     <fragment
         android:id="@+id/nav_pending_operations"
         android:name="net.taler.wallet.pending.PendingOperationsFragment"
-        android:label="Pending Operations"
+        android:label="@string/pending_operations_title"
         tools:layout="@layout/fragment_pending_operations" />
+
     <fragment
         android:id="@+id/errorFragment"
         android:name="net.taler.wallet.withdraw.ErrorFragment"
@@ -140,4 +142,8 @@
         android:id="@+id/action_global_pending_operations"
         app:destination="@id/nav_pending_operations" />
 
-</navigation>
\ No newline at end of file
+    <action
+        android:id="@+id/action_nav_transaction_detail"
+        app:destination="@id/nav_transactions_detail" />
+
+</navigation>
diff --git a/wallet/src/main/res/values/colors.xml 
b/wallet/src/main/res/values/colors.xml
index a6b1731..6413bb8 100644
--- a/wallet/src/main/res/values/colors.xml
+++ b/wallet/src/main/res/values/colors.xml
@@ -18,7 +18,4 @@
     <color name="colorPrimary">#283593</color>
     <color name="colorPrimaryDark">#1A237E</color>
     <color name="colorAccent">#AE1010</color>
-
-    <color name="red">#C62828</color>
-    <color name="green">#558B2F</color>
 </resources>
diff --git a/wallet/src/main/res/values/strings.xml 
b/wallet/src/main/res/values/strings.xml
index e0b3183..4531785 100644
--- a/wallet/src/main/res/values/strings.xml
+++ b/wallet/src/main/res/values/strings.xml
@@ -49,6 +49,8 @@
     <string name="transactions_detail_title">Transaction</string>
     <string name="transactions_detail_title_balance">Balance: %s</string>
     <string name="transactions_detail_json">Show JSON</string>
+    <string name="transactions_delete">Delete</string>
+    <string name="transactions_select_all">Select All</string>
 
     <!-- Transactions -->
     <string name="transaction_reserve_balance_updated">Reserve Balance 
Updated</string>
@@ -80,6 +82,7 @@
     <string name="payment_hide_details">Hide Details</string>
     <string name="payment_successful">Payment was successful</string>
     <string name="payment_back_button">OK</string>
+    <string name="payment_already_paid_title">Already paid</string>
     <string name="payment_already_paid">You\'ve already paid for this 
order.</string>
 
     <string name="withdraw_accepted">Withdrawal accepted</string>
diff --git a/wallet/src/main/res/values/styles.xml 
b/wallet/src/main/res/values/styles.xml
index c8a2c3b..093f43f 100644
--- a/wallet/src/main/res/values/styles.xml
+++ b/wallet/src/main/res/values/styles.xml
@@ -21,6 +21,8 @@
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorAccent</item>
         <item name="colorOnPrimary">@android:color/white</item>
+
+        <item name="windowActionModeOverlay">true</item>
     </style>
 
     <style name="AppTheme.NoActionBar">

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



reply via email to

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