gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant-terminal-android] 02/03: Clean up history code and layou


From: gnunet
Subject: [taler-merchant-terminal-android] 02/03: Clean up history code and layout
Date: Tue, 17 Mar 2020 16:30:46 +0100

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

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

commit bca790d381880b3077df0e37cf29b7a2f9e2266c
Author: Torsten Grote <address@hidden>
AuthorDate: Mon Mar 16 14:48:02 2020 -0300

    Clean up history code and layout
---
 .../java/net/taler/merchantpos/MainViewModel.kt    |   2 +
 .../java/net/taler/merchantpos/MerchantHistory.kt  | 190 ---------------------
 app/src/main/java/net/taler/merchantpos/Utils.kt   |  24 +++
 .../taler/merchantpos/history/HistoryManager.kt    | 104 +++++++++++
 .../merchantpos/history/MerchantHistoryFragment.kt | 146 ++++++++++++++++
 app/src/main/res/layout/history_row.xml            |  91 ----------
 app/src/main/res/layout/list_item_history.xml      |  84 +++++++++
 app/src/main/res/navigation/nav_graph.xml          |   2 +-
 app/src/main/res/values/strings.xml                |   2 +-
 9 files changed, 362 insertions(+), 283 deletions(-)

diff --git a/app/src/main/java/net/taler/merchantpos/MainViewModel.kt 
b/app/src/main/java/net/taler/merchantpos/MainViewModel.kt
index 1bb57b9..560ca59 100644
--- a/app/src/main/java/net/taler/merchantpos/MainViewModel.kt
+++ b/app/src/main/java/net/taler/merchantpos/MainViewModel.kt
@@ -24,6 +24,7 @@ import 
com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PRO
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.kotlin.KotlinModule
 import net.taler.merchantpos.config.ConfigManager
+import net.taler.merchantpos.history.HistoryManager
 import net.taler.merchantpos.order.OrderManager
 import net.taler.merchantpos.payment.PaymentManager
 
@@ -39,6 +40,7 @@ class MainViewModel(app: Application) : AndroidViewModel(app) 
{
         addConfigurationReceiver(orderManager)
     }
     val paymentManager = PaymentManager(configManager, queue, mapper)
+    val historyManager = HistoryManager(configManager, queue, mapper)
 
     override fun onCleared() {
         queue.cancelAll { !it.isCanceled }
diff --git a/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt 
b/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt
deleted file mode 100644
index 997a1e6..0000000
--- a/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.merchantpos
-
-import android.annotation.SuppressLint
-import android.os.Bundle
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.activityViewModels
-import androidx.lifecycle.MutableLiveData
-import androidx.navigation.fragment.findNavController
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView.Adapter
-import androidx.recyclerview.widget.RecyclerView.ViewHolder
-import com.android.volley.Request.Method.GET
-import com.android.volley.RequestQueue
-import com.android.volley.Response.ErrorListener
-import com.android.volley.Response.Listener
-import com.android.volley.toolbox.Volley
-import com.google.android.material.snackbar.Snackbar
-import com.google.android.material.snackbar.Snackbar.LENGTH_SHORT
-import kotlinx.android.synthetic.main.fragment_merchant_history.*
-import net.taler.merchantpos.HistoryItemAdapter.HistoryItemViewHolder
-import 
net.taler.merchantpos.MerchantHistoryDirections.Companion.actionGlobalMerchantSettings
-import net.taler.merchantpos.config.MerchantRequest
-import org.json.JSONObject
-import java.time.Instant
-import java.time.ZoneId
-import java.time.format.DateTimeFormatter
-import java.time.format.FormatStyle.SHORT
-import java.util.*
-
-/**
- * Fragment to display the merchant's payment history,
- * received from the backend.
- */
-class MerchantHistory : Fragment() {
-
-    companion object {
-        const val TAG = "taler-merchant"
-    }
-
-    private lateinit var queue: RequestQueue
-    private val model: MainViewModel by activityViewModels()
-    private val historyListAdapter = HistoryItemAdapter(listOf())
-
-    private val isLoading = MutableLiveData<Boolean>().apply { value = false }
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-
-        queue = Volley.newRequestQueue(context)
-    }
-
-    override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View? {
-        return inflater.inflate(R.layout.fragment_merchant_history, container, 
false)
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        list_history.apply {
-            layoutManager = LinearLayoutManager(requireContext())
-            addItemDecoration(DividerItemDecoration(context, VERTICAL))
-            adapter = historyListAdapter
-        }
-
-        swipeRefresh.isRefreshing = false
-        swipeRefresh.setOnRefreshListener {
-            Log.v(TAG, "refreshing!")
-            fetchHistory()
-        }
-
-        this.isLoading.observe(viewLifecycleOwner, androidx.lifecycle.Observer 
{ loading ->
-            Log.v(TAG, "setting refreshing to $loading")
-            swipeRefresh.isRefreshing = loading
-        })
-    }
-
-    override fun onStart() {
-        super.onStart()
-        if (model.configManager.merchantConfig?.instance == null) {
-            actionGlobalMerchantSettings().navigate(findNavController())
-        } else {
-            fetchHistory()
-        }
-    }
-
-    private fun fetchHistory() {
-        isLoading.value = true
-        val merchantConfig = model.configManager.merchantConfig!!
-        val params = mapOf("instance" to merchantConfig.instance)
-        val req = MerchantRequest(GET, merchantConfig, "history", params, null,
-            Listener { onHistoryResponse(it) },
-            ErrorListener { onNetworkError() })
-        queue.add(req)
-    }
-
-    private fun onHistoryResponse(body: JSONObject) {
-        this.isLoading.value = false
-        Log.v(TAG, "got history response $body")
-        // TODO use jackson instead of manual parsing
-        val data = arrayListOf<HistoryItem>()
-        val historyJson = body.getJSONArray("history")
-        for (i in 0 until historyJson.length()) {
-            val item = historyJson.getJSONObject(i)
-            val orderId = item.getString("order_id")
-            val summary = item.getString("summary")
-            val timestampObj = item.getJSONObject("timestamp")
-            val timestamp = Instant.ofEpochSecond(timestampObj.getLong("t_ms"))
-            val amount = Amount.fromString(item.getString("amount"))
-            data.add(HistoryItem(orderId, amount, summary, timestamp))
-        }
-        historyListAdapter.setData(data)
-    }
-
-    private fun onNetworkError() {
-        this.isLoading.value = false
-        Snackbar.make(view!!, R.string.error_network, LENGTH_SHORT).show()
-    }
-
-}
-
-data class HistoryItem(
-    val orderId: String,
-    val amount: Amount,
-    val summary: String,
-    val timestamp: Instant
-)
-
-class HistoryItemAdapter(private var items: List<HistoryItem>) : 
Adapter<HistoryItemViewHolder>() {
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
HistoryItemViewHolder {
-        val v = 
LayoutInflater.from(parent.context).inflate(R.layout.history_row, parent, false)
-        return HistoryItemViewHolder(v)
-    }
-
-    override fun getItemCount() = items.size
-
-    override fun onBindViewHolder(holder: HistoryItemViewHolder, position: 
Int) {
-        holder.bind(items[position])
-    }
-
-    fun setData(items: List<HistoryItem>) {
-        this.items = items
-        this.notifyDataSetChanged()
-    }
-
-    class HistoryItemViewHolder(v: View) : ViewHolder(v) {
-
-        private val summaryTextView: TextView = 
v.findViewById(R.id.text_history_summary)
-        private val amountTextView: TextView = 
v.findViewById(R.id.text_history_amount)
-        private val timestampTextView: TextView = 
v.findViewById(R.id.text_history_time)
-        private val orderIdTextView: TextView = 
v.findViewById(R.id.text_history_order_id)
-        private val formatter: DateTimeFormatter = 
DateTimeFormatter.ofLocalizedDateTime(SHORT)
-            .withLocale(Locale.getDefault())
-            .withZone(ZoneId.systemDefault())
-
-        fun bind(item: HistoryItem) {
-            summaryTextView.text = item.summary
-            val amount = item.amount
-            @SuppressLint("SetTextI18n")
-            amountTextView.text = "${amount.amount} ${amount.currency}"
-            timestampTextView.text = formatter.format(item.timestamp)
-            orderIdTextView.text = item.orderId
-        }
-    }
-
-}
diff --git a/app/src/main/java/net/taler/merchantpos/Utils.kt 
b/app/src/main/java/net/taler/merchantpos/Utils.kt
index 2f6d4f8..507d142 100644
--- a/app/src/main/java/net/taler/merchantpos/Utils.kt
+++ b/app/src/main/java/net/taler/merchantpos/Utils.kt
@@ -16,6 +16,16 @@
 
 package net.taler.merchantpos
 
+import android.content.Context
+import android.text.format.DateUtils.DAY_IN_MILLIS
+import android.text.format.DateUtils.FORMAT_ABBREV_MONTH
+import android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE
+import android.text.format.DateUtils.FORMAT_NO_YEAR
+import android.text.format.DateUtils.FORMAT_SHOW_DATE
+import android.text.format.DateUtils.FORMAT_SHOW_TIME
+import android.text.format.DateUtils.MINUTE_IN_MILLIS
+import android.text.format.DateUtils.formatDateTime
+import android.text.format.DateUtils.getRelativeTimeSpanString
 import android.view.View
 import android.view.View.INVISIBLE
 import android.view.View.VISIBLE
@@ -97,6 +107,14 @@ fun topSnackbar(view: View, @StringRes resId: Int, 
@Duration duration: Int) {
 
 fun NavDirections.navigate(nav: NavController) = nav.navigate(this)
 
+fun Long.toRelativeTime(context: Context): CharSequence {
+    val now = System.currentTimeMillis()
+    return if (now - this > DAY_IN_MILLIS * 2) {
+        val flags = FORMAT_SHOW_TIME or FORMAT_SHOW_DATE or 
FORMAT_ABBREV_MONTH or FORMAT_NO_YEAR
+        formatDateTime(context, this, flags)
+    } else getRelativeTimeSpanString(this, now, MINUTE_IN_MILLIS, 
FORMAT_ABBREV_RELATIVE)
+}
+
 class CombinedLiveData<T, K, S>(
     source1: LiveData<T>,
     source2: LiveData<K>,
@@ -125,3 +143,9 @@ class CombinedLiveData<T, K, S>(
         throw UnsupportedOperationException()
     }
 }
+
+/**
+ * Use this with 'when' expressions when you need it to handle all 
possibilities/branches.
+ */
+val <T> T.exhaustive: T
+    get() = this
diff --git a/app/src/main/java/net/taler/merchantpos/history/HistoryManager.kt 
b/app/src/main/java/net/taler/merchantpos/history/HistoryManager.kt
new file mode 100644
index 0000000..1459876
--- /dev/null
+++ b/app/src/main/java/net/taler/merchantpos/history/HistoryManager.kt
@@ -0,0 +1,104 @@
+/*
+ * 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.merchantpos.history
+
+import androidx.annotation.UiThread
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.android.volley.Request.Method.GET
+import com.android.volley.RequestQueue
+import com.android.volley.Response.ErrorListener
+import com.android.volley.Response.Listener
+import com.fasterxml.jackson.annotation.JsonIgnore
+import com.fasterxml.jackson.annotation.JsonInclude
+import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY
+import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.kotlin.readValue
+import net.taler.merchantpos.Amount
+import net.taler.merchantpos.config.ConfigManager
+import net.taler.merchantpos.config.MerchantRequest
+import org.json.JSONObject
+
+@JsonInclude(NON_EMPTY)
+class Timestamp(
+    @JsonProperty("t_ms")
+    val ms: Long
+)
+
+data class HistoryItem(
+    @JsonProperty("order_id")
+    val orderId: String,
+    @JsonProperty("amount")
+    val amountStr: String,
+    val summary: String,
+    val timestamp: Timestamp
+) {
+    @get:JsonIgnore
+    val amount: Amount by lazy { Amount.fromString(amountStr) }
+
+    @get:JsonIgnore
+    val time = timestamp.ms
+}
+
+sealed class HistoryResult {
+    object Error : HistoryResult()
+    class Success(val items: List<HistoryItem>) : HistoryResult()
+}
+
+class HistoryManager(
+    private val configManager: ConfigManager,
+    private val queue: RequestQueue,
+    private val mapper: ObjectMapper
+) {
+
+    private val mIsLoading = MutableLiveData(false)
+    val isLoading: LiveData<Boolean> = mIsLoading
+
+    private val mItems = MutableLiveData<HistoryResult>()
+    val items: LiveData<HistoryResult> = mItems
+
+    @UiThread
+    internal fun fetchHistory() {
+        mIsLoading.value = true
+        val merchantConfig = configManager.merchantConfig!!
+        val params = mapOf("instance" to merchantConfig.instance)
+        val req = MerchantRequest(GET, merchantConfig, "history", params, null,
+            Listener { onHistoryResponse(it) },
+            ErrorListener { onNetworkError() })
+        queue.add(req)
+    }
+
+    @UiThread
+    private fun onHistoryResponse(body: JSONObject) {
+        mIsLoading.value = false
+        val items = arrayListOf<HistoryItem>()
+        val historyJson = body.getJSONArray("history")
+        for (i in 0 until historyJson.length()) {
+            val historyItem: HistoryItem = 
mapper.readValue(historyJson.getString(i))
+            items.add(historyItem)
+        }
+        mItems.value = HistoryResult.Success(items)
+    }
+
+    @UiThread
+    private fun onNetworkError() {
+        mIsLoading.value = false
+        mItems.value = HistoryResult.Error
+    }
+
+}
diff --git 
a/app/src/main/java/net/taler/merchantpos/history/MerchantHistoryFragment.kt 
b/app/src/main/java/net/taler/merchantpos/history/MerchantHistoryFragment.kt
new file mode 100644
index 0000000..5299f28
--- /dev/null
+++ b/app/src/main/java/net/taler/merchantpos/history/MerchantHistoryFragment.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.merchantpos.history
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+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.DividerItemDecoration.VERTICAL
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView.Adapter
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.google.android.material.snackbar.Snackbar
+import com.google.android.material.snackbar.Snackbar.LENGTH_SHORT
+import kotlinx.android.synthetic.main.fragment_merchant_history.*
+import net.taler.merchantpos.MainViewModel
+import net.taler.merchantpos.R
+import net.taler.merchantpos.exhaustive
+import net.taler.merchantpos.history.HistoryItemAdapter.HistoryItemViewHolder
+import 
net.taler.merchantpos.history.MerchantHistoryFragmentDirections.Companion.actionGlobalMerchantSettings
+import net.taler.merchantpos.navigate
+import net.taler.merchantpos.toRelativeTime
+import java.util.*
+
+/**
+ * Fragment to display the merchant's payment history, received from the 
backend.
+ */
+class MerchantHistoryFragment : Fragment() {
+
+    companion object {
+        const val TAG = "taler-merchant"
+    }
+
+    private val model: MainViewModel by activityViewModels()
+    private val historyManager by lazy { model.historyManager }
+
+    private val historyListAdapter = HistoryItemAdapter()
+
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(R.layout.fragment_merchant_history, container, 
false)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        list_history.apply {
+            layoutManager = LinearLayoutManager(requireContext())
+            addItemDecoration(DividerItemDecoration(context, VERTICAL))
+            adapter = historyListAdapter
+        }
+
+        swipeRefresh.setOnRefreshListener {
+            Log.v(TAG, "refreshing!")
+            historyManager.fetchHistory()
+        }
+        historyManager.isLoading.observe(viewLifecycleOwner, Observer { 
loading ->
+            Log.v(TAG, "setting refreshing to $loading")
+            swipeRefresh.isRefreshing = loading
+        })
+        historyManager.items.observe(viewLifecycleOwner, Observer { result ->
+            when (result) {
+                is HistoryResult.Error -> onError()
+                is HistoryResult.Success -> 
historyListAdapter.setData(result.items)
+            }.exhaustive
+        })
+    }
+
+    override fun onStart() {
+        super.onStart()
+        if (model.configManager.merchantConfig?.instance == null) {
+            actionGlobalMerchantSettings().navigate(findNavController())
+        } else {
+            historyManager.fetchHistory()
+        }
+    }
+
+    private fun onError() {
+        Snackbar.make(view!!, R.string.error_network, LENGTH_SHORT).show()
+    }
+
+}
+
+internal class HistoryItemAdapter : Adapter<HistoryItemViewHolder>() {
+
+    private val items = ArrayList<HistoryItem>()
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
HistoryItemViewHolder {
+        val v =
+            
LayoutInflater.from(parent.context).inflate(R.layout.list_item_history, parent, 
false)
+        return HistoryItemViewHolder(v)
+    }
+
+    override fun getItemCount() = items.size
+
+    override fun onBindViewHolder(holder: HistoryItemViewHolder, position: 
Int) {
+        holder.bind(items[position])
+    }
+
+    fun setData(items: List<HistoryItem>) {
+        this.items.clear()
+        this.items.addAll(items)
+        this.notifyDataSetChanged()
+    }
+
+    internal class HistoryItemViewHolder(private val v: View) : ViewHolder(v) {
+
+        private val orderSummaryView: TextView = 
v.findViewById(R.id.orderSummaryView)
+        private val orderAmountView: TextView = 
v.findViewById(R.id.orderAmountView)
+        private val orderTimeView: TextView = 
v.findViewById(R.id.orderTimeView)
+        private val orderIdView: TextView = v.findViewById(R.id.orderIdView)
+
+        fun bind(item: HistoryItem) {
+            orderSummaryView.text = item.summary
+            val amount = item.amount
+            @SuppressLint("SetTextI18n")
+            orderAmountView.text = "${amount.amount} ${amount.currency}"
+            orderIdView.text = v.context.getString(R.string.history_ref_no, 
item.orderId)
+            orderTimeView.text = item.time.toRelativeTime(v.context)
+        }
+
+    }
+
+}
diff --git a/app/src/main/res/layout/history_row.xml 
b/app/src/main/res/layout/history_row.xml
deleted file mode 100644
index e68e5a0..0000000
--- a/app/src/main/res/layout/history_row.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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/>
-  -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android";
-        xmlns:tools="http://schemas.android.com/tools";
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="16dp"
-        android:layout_marginBottom="8dp"
-        android:orientation="vertical">
-
-    <TextView
-            android:id="@+id/text_history_summary"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textSize="24sp"
-            android:textStyle="bold"
-            tools:text="One Cappuccino" />
-
-    <TextView
-            android:id="@+id/text_history_amount"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textSize="20sp"
-            android:textStyle="bold"
-            tools:text="1 Euro" />
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-        <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/history_received_at"
-                android:textAllCaps="false"
-                android:textSize="20sp"
-                android:textStyle="italic" />
-
-
-        <TextView
-                android:id="@+id/text_history_time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textSize="20sp"
-                tools:text="2019-08-31 14:25" />
-
-    </LinearLayout>
-
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-        <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/history_ref_no"
-                android:textAllCaps="false"
-                android:textSize="20sp"
-                android:textStyle="italic" />
-
-        <TextView
-                android:id="@+id/text_history_order_id"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textAllCaps="false"
-                android:textSize="20sp"
-                android:textStyle="italic"
-                tools:text="2019.242-014B6QPF1M1HC5TY" />
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/list_item_history.xml 
b/app/src/main/res/layout/list_item_history.xml
new file mode 100644
index 0000000..06ffff2
--- /dev/null
+++ b/app/src/main/res/layout/list_item_history.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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/>
+  -->
+
+<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";
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="16dp">
+
+    <TextView
+            android:id="@+id/orderSummaryView"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="20sp"
+            android:textStyle="bold"
+            app:layout_constraintEnd_toStartOf="@+id/orderAmountView"
+            app:layout_constraintHorizontal_bias="1.0"
+            app:layout_constraintHorizontal_chainStyle="spread_inside"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            tools:text="One Cappuccino or another name that can be so long 
that it spans more than one line" />
+
+    <TextView
+            android:id="@+id/orderAmountView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="20sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toBottomOf="@+id/orderSummaryView"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.0"
+            app:layout_constraintStart_toEndOf="@+id/orderSummaryView"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_bias="0.0"
+            tools:text="23.42 TESTKUDOS" />
+
+    <TextView
+            android:id="@+id/orderIdView"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:text="@string/history_ref_no"
+            android:textAllCaps="false"
+            android:textSize="20sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@+id/orderTimeView"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintHorizontal_chainStyle="spread_inside"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/orderSummaryView" />
+
+    <TextView
+            android:id="@+id/orderTimeView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_marginTop="8dp"
+            android:textSize="20sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintHorizontal_bias="0.5"
+            app:layout_constraintStart_toEndOf="@+id/orderIdView"
+            app:layout_constraintTop_toBottomOf="@+id/orderAmountView"
+            app:layout_constraintVertical_bias="1.0"
+            tools:text="3 hrs. ago" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/navigation/nav_graph.xml 
b/app/src/main/res/navigation/nav_graph.xml
index f00d21c..0d7d870 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -55,7 +55,7 @@
 
     <fragment
             android:id="@+id/nav_history"
-            android:name="net.taler.merchantpos.MerchantHistory"
+            
android:name="net.taler.merchantpos.history.MerchantHistoryFragment"
             android:label="@string/history_label"
             tools:layout="@layout/fragment_merchant_history" />
 
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index 740a080..ac84c5d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -47,7 +47,7 @@
 
     <string name="history_label">Payment History</string>
     <string name="history_received_at">Received at</string>
-    <string name="history_ref_no">Ref. No:</string>
+    <string name="history_ref_no">Ref. No: %s</string>
 
     <string name="error_network">Network Error</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]