gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant-terminal-android] branch master updated (a29814a -> d1b7


From: gnunet
Subject: [taler-merchant-terminal-android] branch master updated (a29814a -> d1b7474)
Date: Thu, 27 Feb 2020 21:06:24 +0100

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

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

    from a29814a  Do NOT require NFC, we can use QR codes just as well
     new f08ae27  Allow to navigate to next order even if current order is empty
     new d1b7474  Change product definition format to support i18n

The 2 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:
 app/build.gradle                                   |  5 ++
 app/src/main/AndroidManifest.xml                   |  3 +-
 .../java/net/taler/merchantpos/MainActivity.kt     | 55 +++++++++---------
 .../merchantpos/config/ConfigFetcherFragment.kt    |  3 +-
 .../net/taler/merchantpos/config/ConfigManager.kt  | 11 +++-
 .../merchantpos/config/MerchantConfigFragment.kt   | 23 +++++---
 .../taler/merchantpos/order/CategoriesFragment.kt  |  2 +-
 .../net/taler/merchantpos/order/Definitions.kt     | 67 ++++++++++++++++++----
 .../net/taler/merchantpos/order/OrderFragment.kt   | 63 ++++++++++----------
 .../net/taler/merchantpos/order/OrderManager.kt    | 40 +++++++------
 .../taler/merchantpos/order/OrderStateFragment.kt  |  2 +-
 .../taler/merchantpos/order/ProductsFragment.kt    |  2 +-
 app/src/main/res/layout/fragment_order.xml         |  7 +--
 app/src/main/res/navigation/nav_graph.xml          | 12 ++--
 app/src/main/res/values/strings.xml                | 12 ++--
 15 files changed, 192 insertions(+), 115 deletions(-)

diff --git a/app/build.gradle b/app/build.gradle
index c48d7c9..4512af3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -30,6 +30,11 @@ android {
     kotlinOptions {
         jvmTarget = "1.8"
     }
+
+    lintOptions {
+        abortOnError true
+        ignoreWarnings false
+    }
 }
 
 dependencies {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c8a0f78..0c1b834 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,7 +27,8 @@
                 android:name=".MainActivity"
                 android:label="@string/app_name"
                 android:screenOrientation="landscape"
-                android:theme="@style/AppTheme.NoActionBar">
+                android:theme="@style/AppTheme.NoActionBar"
+                tools:ignore="LockedOrientationActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
diff --git a/app/src/main/java/net/taler/merchantpos/MainActivity.kt 
b/app/src/main/java/net/taler/merchantpos/MainActivity.kt
index 36c1211..1fb4653 100644
--- a/app/src/main/java/net/taler/merchantpos/MainActivity.kt
+++ b/app/src/main/java/net/taler/merchantpos/MainActivity.kt
@@ -5,20 +5,21 @@ import android.content.Intent.ACTION_MAIN
 import android.content.Intent.CATEGORY_HOME
 import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
 import android.os.Bundle
+import android.os.Handler
 import android.view.MenuItem
+import android.widget.Toast
+import android.widget.Toast.LENGTH_SHORT
 import androidx.activity.viewModels
 import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.widget.Toolbar
 import androidx.core.view.GravityCompat.START
-import androidx.drawerlayout.widget.DrawerLayout
 import androidx.lifecycle.Observer
 import androidx.navigation.NavController
 import androidx.navigation.fragment.NavHostFragment
 import androidx.navigation.ui.AppBarConfiguration
 import androidx.navigation.ui.setupWithNavController
-import com.google.android.material.navigation.NavigationView
 import 
com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener
-
+import kotlinx.android.synthetic.main.activity_main.*
+import kotlinx.android.synthetic.main.app_bar_main.*
 
 class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
 
@@ -26,7 +27,8 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
     private val nfcManager = NfcManager()
 
     private lateinit var nav: NavController
-    private lateinit var drawerLayout: DrawerLayout
+
+    private var reallyExit = false
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -38,23 +40,20 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
             }
         })
 
-        val toolbar: Toolbar = findViewById(R.id.toolbar)
-        setSupportActionBar(toolbar)
-
-        drawerLayout = findViewById(R.id.drawer_layout)
-        val navView: NavigationView = findViewById(R.id.nav_view)
-        navView.setNavigationItemSelectedListener(this)
-        val appBarConfiguration = AppBarConfiguration(
-            setOf(
-                R.id.order,
-                R.id.merchantSettings,
-                R.id.merchantHistory
-            ), drawerLayout
-        )
-
         val navHostFragment =
             supportFragmentManager.findFragmentById(R.id.navHostFragment) as 
NavHostFragment
         nav = navHostFragment.navController
+
+        nav_view.setupWithNavController(nav)
+        nav_view.setNavigationItemSelectedListener(this)
+        if (savedInstanceState == null) {
+            nav_view.menu.getItem(0).isChecked = true
+        }
+
+        setSupportActionBar(toolbar)
+        val appBarConfiguration = AppBarConfiguration(
+            setOf(R.id.order, R.id.merchantSettings, R.id.merchantHistory), 
drawer_layout
+        )
         toolbar.setupWithNavController(nav, appBarConfiguration)
     }
 
@@ -85,14 +84,13 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
             R.id.nav_history -> 
nav.navigate(R.id.action_global_merchantHistory)
             R.id.nav_settings -> 
nav.navigate(R.id.action_global_merchantSettings)
         }
-        val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
-        drawerLayout.closeDrawer(START)
+        drawer_layout.closeDrawer(START)
         return true
     }
 
     override fun onBackPressed() {
-        if (drawerLayout.isDrawerOpen(START)) {
-            drawerLayout.closeDrawer(START)
+        if (drawer_layout.isDrawerOpen(START)) {
+            drawer_layout.closeDrawer(START)
         } else if (nav.currentDestination?.id == R.id.merchantSettings && 
model.configManager.needsConfig()) {
             // we are in the configuration screen and need a config to continue
             val intent = Intent(ACTION_MAIN).apply {
@@ -100,9 +98,14 @@ class MainActivity : AppCompatActivity(), 
OnNavigationItemSelectedListener {
                 flags = FLAG_ACTIVITY_NEW_TASK
             }
             startActivity(intent)
-        } else {
-            super.onBackPressed()
-        }
+        } else if (nav.currentDestination?.id == R.id.order) {
+            if (reallyExit) super.onBackPressed()
+            else {
+                reallyExit = true
+                Toast.makeText(this, R.string.toast_back_to_exit, 
LENGTH_SHORT).show()
+                Handler().postDelayed({ reallyExit = false }, 3000)
+            }
+        } else super.onBackPressed()
     }
 
 }
diff --git 
a/app/src/main/java/net/taler/merchantpos/config/ConfigFetcherFragment.kt 
b/app/src/main/java/net/taler/merchantpos/config/ConfigFetcherFragment.kt
index 4520f8f..e233c13 100644
--- a/app/src/main/java/net/taler/merchantpos/config/ConfigFetcherFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/config/ConfigFetcherFragment.kt
@@ -12,6 +12,7 @@ import com.google.android.material.snackbar.Snackbar
 import com.google.android.material.snackbar.Snackbar.LENGTH_SHORT
 import net.taler.merchantpos.MainViewModel
 import net.taler.merchantpos.R
+import 
net.taler.merchantpos.config.ConfigFetcherFragmentDirections.Companion.actionConfigFetcherToOrder
 
 class ConfigFetcherFragment : Fragment() {
 
@@ -32,7 +33,7 @@ class ConfigFetcherFragment : Fragment() {
             when {
                 result == null -> return@Observer
                 result.error -> onNetworkError(result.authError)
-                else -> 
findNavController().navigate(R.id.action_configFetcher_to_order)
+                else -> actionConfigFetcherToOrder().let { 
findNavController().navigate(it) }
             }
         })
     }
diff --git a/app/src/main/java/net/taler/merchantpos/config/ConfigManager.kt 
b/app/src/main/java/net/taler/merchantpos/config/ConfigManager.kt
index 753f5b9..1016465 100644
--- a/app/src/main/java/net/taler/merchantpos/config/ConfigManager.kt
+++ b/app/src/main/java/net/taler/merchantpos/config/ConfigManager.kt
@@ -27,6 +27,10 @@ private const val SETTINGS_CONFIG_URL = "configUrl"
 private const val SETTINGS_USERNAME = "username"
 private const val SETTINGS_PASSWORD = "password"
 
+internal const val CONFIG_URL_DEMO = "https://grobox.de/taler/pos.json";
+internal const val CONFIG_USERNAME_DEMO = "torsten"
+internal const val CONFIG_PASSWORD_DEMO = "test"
+
 private val TAG = ConfigManager::class.java.simpleName
 
 interface ConfigurationReceiver {
@@ -117,7 +121,12 @@ class ConfigManager(
 
         var configValid = true
         configurationReceivers.forEach {
-            val result = it.onConfigurationReceived(configJson, currency)
+            val result = try {
+                it.onConfigurationReceived(configJson, currency)
+            } catch (e: Exception) {
+                Log.e(TAG, "Error handling configuration by 
${it::class.java.simpleName}", e)
+                false
+            }
             configValid = result && configValid
         }
         if (configValid) {
diff --git 
a/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt 
b/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt
index c6e60d3..f89962f 100644
--- a/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt
@@ -60,7 +60,7 @@ class MerchantConfigFragment : Fragment() {
             passwordView.editText!!.text = null
             forgetPasswordButton.visibility = GONE
         }
-        updateView()
+        updateView(savedInstanceState == null)
     }
 
     override fun onStart() {
@@ -74,12 +74,21 @@ class MerchantConfigFragment : Fragment() {
         }
     }
 
-    private fun updateView() {
-        configUrlView.editText!!.setText(configManager.config.configUrl)
-        usernameView.editText!!.setText(configManager.config.username)
-        passwordView.editText!!.setText(configManager.config.password)
-
-        forgetPasswordButton.visibility = if 
(configManager.config.hasPassword()) VISIBLE else GONE
+    private fun updateView(isInitialization: Boolean = false) {
+        val config = configManager.config
+        configUrlView.editText!!.setText(
+            if (isInitialization && config.configUrl.isBlank()) CONFIG_URL_DEMO
+            else config.configUrl
+        )
+        usernameView.editText!!.setText(
+            if (isInitialization && config.username.isBlank()) 
CONFIG_USERNAME_DEMO
+            else config.username
+        )
+        passwordView.editText!!.setText(
+            if (isInitialization && config.password.isBlank()) 
CONFIG_PASSWORD_DEMO
+            else config.password
+        )
+        forgetPasswordButton.visibility = if (config.hasPassword()) VISIBLE 
else GONE
     }
 
     private fun checkInput(): Boolean {
diff --git 
a/app/src/main/java/net/taler/merchantpos/order/CategoriesFragment.kt 
b/app/src/main/java/net/taler/merchantpos/order/CategoriesFragment.kt
index 148699c..549eb78 100644
--- a/app/src/main/java/net/taler/merchantpos/order/CategoriesFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/CategoriesFragment.kt
@@ -81,7 +81,7 @@ private class CategoryAdapter(
         private val button: Button = v.findViewById(R.id.button)
 
         fun bind(category: Category) {
-            button.text = category.name
+            button.text = category.localizedName
             button.isPressed = category.selected
             button.setOnClickListener { listener.onCategorySelected(category) }
         }
diff --git a/app/src/main/java/net/taler/merchantpos/order/Definitions.kt 
b/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
index 3aeeed4..065f2d2 100644
--- a/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
@@ -1,34 +1,47 @@
 package net.taler.merchantpos.order
 
+import androidx.core.os.LocaleListCompat
 import com.fasterxml.jackson.annotation.JsonIgnore
 import com.fasterxml.jackson.annotation.JsonProperty
 import net.taler.merchantpos.Amount
+import java.util.*
+import java.util.Locale.LanguageRange
+import kotlin.collections.ArrayList
+import kotlin.collections.HashMap
 
 data class Category(
     val id: Int,
-    val name: String
+    val name: Map<String, String>
 ) {
+    val defaultName: String? get() = name["_"]
     var selected: Boolean = false
+    val localizedName: String get() = getLocalizedString(name, defaultName!!)
 }
 
-interface Product {
-    val id: String
-    val description: String
-    val price: String
-    val location: String?
+abstract class Product {
+    abstract val id: String
+    abstract val description: Map<String, String>
+    abstract val price: String
+    abstract val location: String?
+    @get:JsonIgnore
+    val defaultDescription: String?
+        get() = description["_"]
+    @get:JsonIgnore
+    val localizedDescription: String
+        get() = getLocalizedString(description, defaultDescription!!)
 }
 
 data class ConfigProduct(
     @JsonProperty("product_id")
     override val id: String,
-    override val description: String,
+    override val description: Map<String, String>,
     override val price: String,
     @JsonProperty("delivery_location")
     override val location: String?,
     val categories: List<Int>,
     @JsonIgnore
     val quantity: Int = 0
-) : Product {
+) : Product() {
     val priceAsDouble by lazy { Amount.fromString(price).amount.toDouble() }
 
     override fun equals(other: Any?): Boolean {
@@ -48,12 +61,13 @@ data class ConfigProduct(
 data class ContractProduct(
     @JsonProperty("product_id")
     override val id: String,
-    override val description: String,
+    @get:JsonIgnore
+    override val description: Map<String, String>,
     override val price: String,
     @JsonProperty("delivery_location")
     override val location: String?,
     val quantity: Int
-) : Product {
+) : Product() {
     constructor(product: ConfigProduct) : this(
         product.id,
         product.description,
@@ -61,12 +75,41 @@ data class ContractProduct(
         product.location,
         product.quantity
     )
+
+    // TODO remove once backend supports i18n
+    @get:JsonProperty("description")
+    val tmpDescription: String
+        get() = localizedDescription
+}
+
+private fun getLocalizedString(map: Map<String, String>, default: String): 
String {
+    // just return the default, if it is the only element
+    if (map.size == 1) return default
+    // create a priority list of language ranges from system locales
+    val locales = LocaleListCompat.getDefault()
+    val priorityList = ArrayList<LanguageRange>(locales.size())
+    for (i in 0 until locales.size()) {
+        priorityList.add(LanguageRange(locales[i].toLanguageTag()))
+    }
+    // create a list of locales available in the given map
+    val availableLocales = map.keys.mapNotNull {
+        if (it == "_") return@mapNotNull null
+        val list = it.split("_")
+        when (list.size) {
+            1 -> Locale(list[0])
+            2 -> Locale(list[0], list[1])
+            3 -> Locale(list[0], list[1], list[2])
+            else -> null
+        }
+    }
+    val match = Locale.lookup(priorityList, availableLocales)
+    return match?.toString()?.let { map[it] } ?: default
 }
 
 data class Order(val id: Int, val availableCategories: Map<Int, Category>) {
     val products = ArrayList<ConfigProduct>()
     val title: String = id.toString()
-    val summary: String
+    val summary: String  // TODO also support i18n map here?
         get() {
             val categories = HashMap<Category, Int>()
             products.forEach { product ->
@@ -76,7 +119,7 @@ data class Order(val id: Int, val availableCategories: 
Map<Int, Category>) {
                 categories[category] = oldQuantity + product.quantity
             }
             return categories.map { (category, quantity) ->
-                "$quantity x ${category.name}"
+                "$quantity x ${category.localizedName}"
             }.joinToString()
         }
     val total: Double
diff --git a/app/src/main/java/net/taler/merchantpos/order/OrderFragment.kt 
b/app/src/main/java/net/taler/merchantpos/order/OrderFragment.kt
index 8ababad..42d060d 100644
--- a/app/src/main/java/net/taler/merchantpos/order/OrderFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/OrderFragment.kt
@@ -8,12 +8,10 @@ import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
 import androidx.navigation.fragment.findNavController
-import androidx.navigation.fragment.navArgs
 import androidx.transition.TransitionManager.beginDelayedTransition
 import kotlinx.android.synthetic.main.fragment_order.*
 import net.taler.merchantpos.MainViewModel
 import net.taler.merchantpos.R
-import 
net.taler.merchantpos.order.OrderFragmentDirections.Companion.actionGlobalOrder
 import net.taler.merchantpos.order.RestartState.ENABLED
 import net.taler.merchantpos.order.RestartState.UNDO
 
@@ -22,8 +20,6 @@ class OrderFragment : Fragment() {
     private val viewModel: MainViewModel by activityViewModels()
     private val orderManager by lazy { viewModel.orderManager }
     private val paymentManager by lazy { viewModel.paymentManager }
-    private val args: OrderFragmentArgs by navArgs()
-    private val liveOrder by lazy { orderManager.getOrder(args.orderId) }
 
     override fun onCreateView(
         inflater: LayoutInflater,
@@ -33,7 +29,32 @@ class OrderFragment : Fragment() {
         return inflater.inflate(R.layout.fragment_order, container, false)
     }
 
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+    override fun onActivityCreated(savedInstanceState: Bundle?) {
+        super.onActivityCreated(savedInstanceState)
+        orderManager.currentOrderId.observe(viewLifecycleOwner, Observer { 
orderId ->
+            val liveOrder = orderManager.getOrder(orderId)
+            onOrderSwitched(orderId, liveOrder)
+            // add a new OrderStateFragment for each order
+            // as switching its internals (like we do here) would be too messy
+            childFragmentManager.beginTransaction()
+                .replace(R.id.fragment1, OrderStateFragment())
+                .commit()
+        })
+    }
+
+    override fun onStart() {
+        super.onStart()
+        if (viewModel.configManager.needsConfig() || 
viewModel.configManager.merchantConfig?.currency == null) {
+            findNavController().navigate(R.id.action_global_merchantSettings)
+        }
+    }
+
+    private fun onOrderSwitched(orderId: Int, liveOrder: LiveOrder) {
+        // order title
+        liveOrder.order.observe(viewLifecycleOwner, Observer { order ->
+            activity?.title = getString(R.string.order_label_title, 
order.title)
+        })
+        // restart button
         restartButton.setOnClickListener { liveOrder.restartOrUndo() }
         liveOrder.restartState.observe(viewLifecycleOwner, Observer { state ->
             beginDelayedTransition(view as ViewGroup)
@@ -46,43 +67,27 @@ class OrderFragment : Fragment() {
                 restartButton.isEnabled = state == ENABLED
                 completeButton.isEnabled = state == ENABLED
             }
-            nextButton.isEnabled = state == ENABLED
         })
-        minusButton.setOnClickListener { liveOrder.decreaseSelectedOrderLine() 
}
-        plusButton.setOnClickListener { liveOrder.increaseSelectedOrderLine() }
+        // -1 and +1 buttons
         liveOrder.modifyOrderAllowed.observe(viewLifecycleOwner, Observer { 
allowed ->
             minusButton.isEnabled = allowed
             plusButton.isEnabled = allowed
         })
-        orderManager.hasPreviousOrder.observe(viewLifecycleOwner, Observer { 
hasPreviousOrder ->
-            prevButton.isEnabled = hasPreviousOrder
-        })
-    }
-
-    override fun onActivityCreated(savedInstanceState: Bundle?) {
-        super.onActivityCreated(savedInstanceState)
-        liveOrder.order.observe(viewLifecycleOwner, Observer { order ->
-            activity?.title = getString(R.string.order_label_title, 
order.title)
+        minusButton.setOnClickListener { liveOrder.decreaseSelectedOrderLine() 
}
+        plusButton.setOnClickListener { liveOrder.increaseSelectedOrderLine() }
+        // previous and next button
+        prevButton.isEnabled = orderManager.hasPreviousOrder(orderId)
+        orderManager.hasNextOrder(orderId).observe(viewLifecycleOwner, 
Observer { hasNextOrder ->
+            nextButton.isEnabled = hasNextOrder
         })
         prevButton.setOnClickListener { orderManager.previousOrder() }
         nextButton.setOnClickListener { orderManager.nextOrder() }
+        // complete button
         completeButton.setOnClickListener {
             val order = liveOrder.order.value ?: return@setOnClickListener
             paymentManager.createPayment(order)
             findNavController().navigate(R.id.action_order_to_processPayment)
         }
-        orderManager.currentOrderId.observe(viewLifecycleOwner, Observer { 
orderId ->
-            if (args.orderId != orderId) {
-                findNavController().navigate(actionGlobalOrder(orderId))
-            }
-        })
-    }
-
-    override fun onStart() {
-        super.onStart()
-        if (viewModel.configManager.needsConfig() || 
viewModel.configManager.merchantConfig?.currency == null) {
-            findNavController().navigate(R.id.action_global_merchantSettings)
-        }
     }
 
 }
diff --git a/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt 
b/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
index 53c824b..7fdefbb 100644
--- a/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
@@ -4,10 +4,12 @@ import android.util.Log
 import androidx.annotation.UiThread
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.Transformations.map
 import com.fasterxml.jackson.core.type.TypeReference
 import com.fasterxml.jackson.databind.ObjectMapper
 import net.taler.merchantpos.Amount.Companion.fromString
 import net.taler.merchantpos.config.ConfigurationReceiver
+import net.taler.merchantpos.order.RestartState.ENABLED
 import org.json.JSONObject
 
 class OrderManager(private val mapper: ObjectMapper) : ConfigurationReceiver {
@@ -24,9 +26,6 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
 
     private val orders = LinkedHashMap<Int, MutableLiveOrder>()
 
-    private val mHasPreviousOrder = MutableLiveData<Boolean>(false)
-    internal val hasPreviousOrder: LiveData<Boolean> = mHasPreviousOrder
-
     private val mProducts = MutableLiveData<List<ConfigProduct>>()
     internal val products: LiveData<List<ConfigProduct>> = mProducts
 
@@ -55,6 +54,10 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
         productsByCategory.clear()
         val seenIds = ArrayList<String>()
         products.forEach { product ->
+            if (product.defaultDescription == null) {
+                Log.e(TAG, "Product $product has no default description \"_\"")
+                return false
+            }
             val productCurrency = fromString(product.price).currency
             if (productCurrency != currency) {
                 Log.e(TAG, "Product $product has currency $productCurrency, 
$currency expected")
@@ -74,6 +77,10 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
                 if (productsByCategory.containsKey(category)) {
                     productsByCategory[category]?.add(product)
                 } else {
+                    if (category.defaultName == null) {
+                        Log.e(TAG, "Category $category has no default 
description \"_\"")
+                        return false
+                    }
                     productsByCategory[category] = 
ArrayList<ConfigProduct>().apply { add(product) }
                 }
             }
@@ -113,16 +120,9 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
             orders[nextId] = MutableLiveOrder(nextId, productsByCategory)
         }
         val currentOrder = order(currentId)
-        val stillHasPrevious = if (currentOrder.isEmpty()) {
-            val wasFirst = orders.keys.first() == currentId
-            orders.remove(currentId)
-            !wasFirst  // we still have a previous order if the removed one 
wasn't the first
-        } else {
-            currentOrder.lastAddedProduct = null  // not needed anymore and 
would select it
-            true  // we did not remove anything, so our next order still has a 
previous
-        }
+        if (currentOrder.isEmpty()) orders.remove(currentId)
+        else currentOrder.lastAddedProduct = null  // not needed anymore and 
it would get selected
         mCurrentOrderId.value = nextId
-        mHasPreviousOrder.value = stillHasPrevious
     }
 
     @UiThread
@@ -146,7 +146,14 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
         if (currentOrder.isEmpty()) orders.remove(currentId)
         else currentOrder.lastAddedProduct = null
         mCurrentOrderId.value = previousId
-        mHasPreviousOrder.value = previousId != orders.keys.first()
+    }
+
+    fun hasPreviousOrder(currentOrderId: Int): Boolean {
+        return currentOrderId != orders.keys.first()
+    }
+
+    fun hasNextOrder(currentOrderId: Int) = 
map(order(currentOrderId).restartState) { state ->
+        state == ENABLED || currentOrderId != orders.keys.last()
     }
 
     internal fun setCurrentCategory(category: Category) {
@@ -166,11 +173,8 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
     @UiThread
     internal fun onOrderPaid(orderId: Int) {
         if (currentOrderId.value == orderId) {
-            if (hasPreviousOrder.value!!) previousOrder()
-            else {
-                nextOrder()
-                mHasPreviousOrder.value = false
-            }
+            if (hasPreviousOrder(orderId)) previousOrder()
+            else nextOrder()
         }
         orders.remove(orderId)
     }
diff --git 
a/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt 
b/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt
index 090208b..9a40577 100644
--- a/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/OrderStateFragment.kt
@@ -166,7 +166,7 @@ private class OrderAdapter : Adapter<OrderViewHolder>() {
         fun bind(product: ConfigProduct, selected: Boolean) {
             v.isActivated = selected
             quantity.text = product.quantity.toString()
-            name.text = product.description
+            name.text = product.localizedDescription
             price.text = String.format("%.2f", product.priceAsDouble * 
product.quantity)
         }
     }
diff --git a/app/src/main/java/net/taler/merchantpos/order/ProductsFragment.kt 
b/app/src/main/java/net/taler/merchantpos/order/ProductsFragment.kt
index 54bd763..a545694 100644
--- a/app/src/main/java/net/taler/merchantpos/order/ProductsFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/ProductsFragment.kt
@@ -86,7 +86,7 @@ private class ProductAdapter(
         private val price: TextView = v.findViewById(R.id.price)
 
         fun bind(product: ConfigProduct) {
-            name.text = product.description
+            name.text = product.localizedDescription
             price.text = product.priceAsDouble.toString()
             v.setOnClickListener { listener.onProductSelected(product) }
         }
diff --git a/app/src/main/res/layout/fragment_order.xml 
b/app/src/main/res/layout/fragment_order.xml
index 19fb629..d65c0ce 100644
--- a/app/src/main/res/layout/fragment_order.xml
+++ b/app/src/main/res/layout/fragment_order.xml
@@ -7,7 +7,6 @@
 
     <androidx.fragment.app.FragmentContainerView
             android:id="@+id/fragment1"
-            android:name="net.taler.merchantpos.order.OrderStateFragment"
             android:layout_width="0dp"
             android:layout_height="0dp"
             android:layout_marginBottom="8dp"
@@ -93,7 +92,7 @@
             android:layout_height="wrap_content"
             android:layout_marginStart="32dp"
             android:backgroundTint="@color/button_bottom"
-            android:text="@string/button_previous"
+            android:text="@string/order_previous"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toEndOf="@+id/plusButton" />
 
@@ -103,7 +102,7 @@
             android:layout_height="wrap_content"
             android:layout_marginStart="16dp"
             android:backgroundTint="@color/button_bottom"
-            android:text="@string/button_next"
+            android:text="@string/order_next"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toEndOf="@+id/prevButton" />
 
@@ -114,7 +113,7 @@
             android:layout_marginStart="32dp"
             android:layout_marginEnd="8dp"
             android:backgroundTint="@color/button_bottom"
-            android:text="@string/button_complete"
+            android:text="@string/order_complete"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintHorizontal_bias="1.0"
diff --git a/app/src/main/res/navigation/nav_graph.xml 
b/app/src/main/res/navigation/nav_graph.xml
index 4a37ae3..59a3f29 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -3,7 +3,7 @@
         xmlns:app="http://schemas.android.com/apk/res-auto";
         xmlns:tools="http://schemas.android.com/tools";
         android:id="@+id/nav_graph"
-        app:startDestination="@id/configFetcher"
+        app:startDestination="@id/order"
         tools:ignore="UnusedNavigation">
 
     <fragment
@@ -11,10 +11,6 @@
             android:name="net.taler.merchantpos.order.OrderFragment"
             android:label=""
             tools:layout="@layout/fragment_order">
-        <argument
-                android:name="orderId"
-                android:defaultValue="0"
-                app:argType="integer" />
         <action
                 android:id="@+id/action_order_to_processPayment"
                 app:destination="@id/processPayment" />
@@ -24,6 +20,9 @@
         <action
                 android:id="@+id/action_order_to_merchantSettings"
                 app:destination="@id/merchantSettings" />
+        <action
+                android:id="@+id/action_order_self"
+                app:destination="@id/order" />
     </fragment>
 
     <fragment
@@ -62,7 +61,8 @@
                 android:id="@+id/action_configFetcher_to_order"
                 app:destination="@id/order"
                 app:launchSingleTop="true"
-                app:popUpTo="@+id/order" />
+                app:popUpTo="@+id/nav_graph"
+                app:popUpToInclusive="true" />
     </fragment>
 
     <fragment
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index fe85bce..149df6e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -12,16 +12,14 @@
     <string name="order_total">Total: %1$.2f %2$s</string>
     <string name="order_restart">Restart</string>
     <string name="order_undo">Undo</string>
-    <string name="button_reconfigure">Reconfigure</string>
-    <string name="button_history">History</string>
-    <string name="button_logout">Logout</string>
-    <string name="button_complete">Complete</string>
+    <string name="order_previous">Prev</string>
+    <string name="order_next">Next</string>
+    <string name="order_complete">Complete</string>
 
     <string name="config_label">Merchant Settings</string>
     <string name="config_url">Configuration URL</string>
     <string name="config_username">Username</string>
     <string name="config_password">Password</string>
-    <string name="config_currency">Currency: %s</string>
     <string name="config_ok">Fetch Configuration</string>
     <string name="config_malformed_url">Invalid URL</string>
     <string name="config_auth_error">Invalid username or password</string>
@@ -46,7 +44,7 @@
     <string name="history_ref_no">Ref. No:</string>
 
     <string name="error_network">Network Error</string>
-    <string name="button_previous">Prev</string>
-    <string name="button_next">Next</string>
+
+    <string name="toast_back_to_exit">Click BACK again to exit</string>
 
 </resources>

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



reply via email to

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