gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-merchant-terminal-android] branch master updated: im


From: gnunet
Subject: [GNUnet-SVN] [taler-merchant-terminal-android] branch master updated: implement backend settings
Date: Mon, 02 Sep 2019 10:50:48 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 2622830  implement backend settings
2622830 is described below

commit 26228306686bb37c18a48b25eba59c354379150c
Author: Florian Dold <address@hidden>
AuthorDate: Mon Sep 2 10:50:45 2019 +0200

    implement backend settings
---
 app/build.gradle                                   |   2 +
 app/src/main/java/net/taler/merchantpos/Amount.kt  |  29 +++++
 .../java/net/taler/merchantpos/CreatePayment.kt    |   9 +-
 .../java/net/taler/merchantpos/MainActivity.kt     |  10 +-
 .../java/net/taler/merchantpos/MerchantConfig.kt   |   7 +-
 .../java/net/taler/merchantpos/MerchantHistory.kt  | 138 ++++++++++++++++++---
 .../java/net/taler/merchantpos/MerchantSettings.kt | 111 ++++++++++++++++-
 .../main/res/layout/fragment_create_payment.xml    |   2 +-
 .../main/res/layout/fragment_merchant_history.xml  |  33 ++---
 .../main/res/layout/fragment_merchant_settings.xml |  93 ++++++++++++++
 app/src/main/res/layout/history_row.xml            |  79 +++++++++++-
 11 files changed, 457 insertions(+), 56 deletions(-)

diff --git a/app/build.gradle b/app/build.gradle
index 0f36545..c1fc89b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -64,6 +64,8 @@ dependencies {
     implementation 
"androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
     kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
 
+    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
+
     // JSON literals and parsing
     implementation 'com.beust:klaxon:5.0.11'
 }
diff --git a/app/src/main/java/net/taler/merchantpos/Amount.kt 
b/app/src/main/java/net/taler/merchantpos/Amount.kt
new file mode 100644
index 0000000..15cadf4
--- /dev/null
+++ b/app/src/main/java/net/taler/merchantpos/Amount.kt
@@ -0,0 +1,29 @@
+package net.taler.merchantpos
+
+import org.json.JSONObject
+
+data class Amount(val currency: String, val amount: String) {
+    fun isZero(): Boolean {
+        return amount.toDouble() == 0.0
+    }
+
+    companion object {
+        const val FRACTIONAL_BASE = 1e8;
+        fun fromJson(jsonAmount: JSONObject): Amount {
+            val amountCurrency = jsonAmount.getString("currency")
+            val amountValue = jsonAmount.getString("value")
+            val amountFraction = jsonAmount.getString("fraction")
+            val amountIntValue = Integer.parseInt(amountValue)
+            val amountIntFraction = Integer.parseInt(amountFraction)
+            return Amount(
+                amountCurrency,
+                (amountIntValue + amountIntFraction / 
FRACTIONAL_BASE).toString()
+            )
+        }
+
+        fun fromString(strAmount: String): Amount {
+            val components = strAmount.split(":")
+            return Amount(components[0], components[1])
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/taler/merchantpos/CreatePayment.kt 
b/app/src/main/java/net/taler/merchantpos/CreatePayment.kt
index c6a8066..83dbed8 100644
--- a/app/src/main/java/net/taler/merchantpos/CreatePayment.kt
+++ b/app/src/main/java/net/taler/merchantpos/CreatePayment.kt
@@ -1,11 +1,13 @@
 package net.taler.merchantpos
 
+import android.annotation.SuppressLint
 import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.Button
 import android.widget.EditText
+import android.widget.TextView
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.ViewModelProviders
 import androidx.navigation.fragment.findNavController
@@ -36,6 +38,10 @@ class CreatePayment : Fragment() {
     override fun onResume() {
         super.onResume()
         this.paused = false
+
+        val textView = 
view!!.findViewById<TextView>(R.id.text_create_payment_amount_label)
+        @SuppressLint("SetTextI18n")
+        textView.text = "Amount (${model.merchantConfig!!.currency})"
     }
 
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -50,7 +56,7 @@ class CreatePayment : Fragment() {
 
     private fun onRequestPayment() {
         val amountValStr = 
activity!!.findViewById<EditText>(R.id.edit_payment_amount).text
-        val amount = "TESTKUDOS:${amountValStr}"
+        val amount = "${model.merchantConfig!!.currency}:${amountValStr}"
         model.activeAmount = amount
         model.activeSubject = 
activity!!.findViewById<EditText>(R.id.edit_payment_subject).text
 
@@ -117,6 +123,7 @@ class CreatePayment : Fragment() {
         requestPaymentButton.setOnClickListener {
             onRequestPayment()
         }
+
         return view
     }
 
diff --git a/app/src/main/java/net/taler/merchantpos/MainActivity.kt 
b/app/src/main/java/net/taler/merchantpos/MainActivity.kt
index e8e9a2a..7c8330a 100644
--- a/app/src/main/java/net/taler/merchantpos/MainActivity.kt
+++ b/app/src/main/java/net/taler/merchantpos/MainActivity.kt
@@ -1,5 +1,6 @@
 package net.taler.merchantpos
 
+import android.content.Context
 import android.nfc.NfcAdapter
 import android.nfc.Tag
 import android.nfc.tech.IsoDep
@@ -276,9 +277,16 @@ class MainActivity : AppCompatActivity(), 
NavigationView.OnNavigationItemSelecte
         findViewById<Toolbar>(R.id.toolbar)
             .setupWithNavController(navController, appBarConfiguration)
 
+        val prefs = getSharedPreferences("taler-merchant-terminal", 
Context.MODE_PRIVATE)
+
+        val baseUrl = prefs.getString("merchantBackendUrl", 
"https://backend.test.taler.net";)
+        val instance = prefs.getString("merchantBackendInstance", "default")
+        val apiKey = prefs.getString("merchantBackendApiKey", "sandbox")
+        val currency = prefs.getString("merchantBackendCurrency", "TESTKUDOS")
+
         model = ViewModelProviders.of(this)[PosTerminalViewModel::class.java]
         model.merchantConfig =
-            MerchantConfig("https://backend.test.taler.net";, "default", 
"sandbox")
+            MerchantConfig(baseUrl!!, instance!!, apiKey!!, currency!!)
 
     }
 
diff --git a/app/src/main/java/net/taler/merchantpos/MerchantConfig.kt 
b/app/src/main/java/net/taler/merchantpos/MerchantConfig.kt
index 3e043a0..626d60b 100644
--- a/app/src/main/java/net/taler/merchantpos/MerchantConfig.kt
+++ b/app/src/main/java/net/taler/merchantpos/MerchantConfig.kt
@@ -2,7 +2,12 @@ package net.taler.merchantpos
 
 import android.net.Uri
 
-data class MerchantConfig(val baseUrl: String, val instance: String, val 
apiKey: String) {
+data class MerchantConfig(
+    val baseUrl: String,
+    val instance: String,
+    val apiKey: String,
+    val currency: String
+) {
     fun urlFor(endpoint: String, params: Map<String, String>?): String {
         val uriBuilder = Uri.parse(baseUrl).buildUpon()
         uriBuilder.appendPath(endpoint)
diff --git a/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt 
b/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt
index c3bab06..b79f836 100644
--- a/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt
+++ b/app/src/main/java/net/taler/merchantpos/MerchantHistory.kt
@@ -1,23 +1,48 @@
 package net.taler.merchantpos
 
 
+import android.annotation.SuppressLint
 import android.os.Bundle
+import android.util.Log
 import androidx.fragment.app.Fragment
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.TextView
+import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModelProviders
 import androidx.recyclerview.widget.DividerItemDecoration
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+import com.android.volley.Request
 import com.android.volley.RequestQueue
+import com.android.volley.Response
+import com.android.volley.VolleyError
 import com.android.volley.toolbox.Volley
+import com.google.android.material.snackbar.Snackbar
+import org.json.JSONObject
+import java.time.Instant
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
+import java.util.*
 
-class MyAdapter(private val myDataset: Array<String>) : 
RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
+
+
+data class HistoryItem(
+    val orderId: String,
+    val amount: Amount,
+    val summary: String,
+    val timestamp: Instant
+)
+
+class MyAdapter(private var myDataset: List<HistoryItem>) :
+    RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): 
MyViewHolder {
-        val textView = 
LayoutInflater.from(parent.context).inflate(R.layout.history_row, parent, false)
-        return MyViewHolder(textView as TextView)
+        val view =
+            LayoutInflater.from(parent.context).inflate(R.layout.history_row, 
parent, false)
+        return MyViewHolder(view)
     }
 
     override fun getItemCount(): Int {
@@ -25,24 +50,47 @@ class MyAdapter(private val myDataset: Array<String>) : 
RecyclerView.Adapter<MyA
     }
 
     override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
-        holder.textView.text = myDataset[position]
+        val item = myDataset[position]
+        val summaryTextView = 
holder.rowView.findViewById<TextView>(R.id.text_history_summary)
+        summaryTextView.text = myDataset[position].summary
+
+        val amount = myDataset[position].amount
+        val amountTextView = 
holder.rowView.findViewById<TextView>(R.id.text_history_amount)
+        @SuppressLint("SetTextI18n")
+        amountTextView.text = "${amount.amount} ${amount.currency}"
+
+        val formatter = 
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
+            .withLocale(Locale.UK)
+            .withZone(ZoneId.systemDefault())
+        val timestampTextView = 
holder.rowView.findViewById<TextView>(R.id.text_history_time)
+        timestampTextView.text = formatter.format(item.timestamp)
+
+        val orderIdTextView =  
holder.rowView.findViewById<TextView>(R.id.text_history_order_id)
+        orderIdTextView.text = item.orderId
+    }
+
+    fun setData(dataset: List<HistoryItem>) {
+        this.myDataset = dataset
+        this.notifyDataSetChanged()
     }
 
-    class MyViewHolder(val textView: TextView) : 
RecyclerView.ViewHolder(textView)
+    class MyViewHolder(val rowView: View) : RecyclerView.ViewHolder(rowView)
+}
+
+fun parseTalerTimestamp(s: String): Instant {
+    return 
Instant.ofEpochSecond(s.substringAfterLast('(').substringBeforeLast(')').toLong())
 }
 
 /**
- * A simple [Fragment] subclass.
- * Activities that contain this fragment must implement the
- * [MerchantHistory.OnFragmentInteractionListener] interface
- * to handle interaction events.
- * Use the [MerchantHistory.newInstance] factory method to
- * create an instance of this fragment.
- *
+ * Fragment to display the merchant's payment history,
+ * received from the backend.
  */
 class MerchantHistory : Fragment() {
     private lateinit var queue: RequestQueue
     private lateinit var model: PosTerminalViewModel
+    private val historyListAdapter = MyAdapter(listOf())
+
+    private val isLoading = MutableLiveData<Boolean>().apply { value = false }
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -54,6 +102,48 @@ class MerchantHistory : Fragment() {
         queue = Volley.newRequestQueue(context)
     }
 
+    private fun onNetworkError(volleyError: VolleyError?) {
+        this.isLoading.value = false
+        val mySnackbar = Snackbar.make(view!!, "Network Error", 
Snackbar.LENGTH_SHORT)
+        mySnackbar.show()
+    }
+
+    private fun onHistoryResponse(body: JSONObject) {
+        this.isLoading.value = false
+        Log.v(TAG, "got history response ${body}")
+        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 timestampStr = item.getString("timestamp")
+            val timestamp = parseTalerTimestamp(timestampStr)
+            val amount = Amount.fromString(item.getString("amount"))
+            data.add(HistoryItem(orderId, amount, summary, timestamp))
+        }
+        historyListAdapter.setData(data)
+    }
+
+    private fun fetchHistory() {
+        isLoading.value = true
+        val instance = model.merchantConfig!!.instance
+        val req = MerchantInternalRequest(
+            Request.Method.GET,
+            model.merchantConfig!!,
+            "history",
+            mapOf("instance" to instance),
+            null,
+            Response.Listener { onHistoryResponse(it) },
+            Response.ErrorListener { onNetworkError(it) })
+        queue.add(req)
+    }
+
+    override fun onResume() {
+        super.onResume()
+        fetchHistory()
+    }
+
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?,
         savedInstanceState: Bundle?
@@ -62,16 +152,28 @@ class MerchantHistory : Fragment() {
         val myItemDecoration = DividerItemDecoration(context, 
myLayoutManager.orientation)
         // Inflate the layout for this fragment
         val view = inflater.inflate(R.layout.fragment_merchant_history, 
container, false)
-        val myList = ArrayList<String>()
-        for (i in 0..100) {
-            myList.add("Element $i")
-        }
-        val myArray: Array<String> = myList.toTypedArray()
         view.findViewById<RecyclerView>(R.id.list_history).apply {
             layoutManager = myLayoutManager
-            adapter = MyAdapter(myArray)
+            adapter = historyListAdapter
             addItemDecoration(myItemDecoration)
         }
+
+        val refreshLayout = 
view.findViewById<SwipeRefreshLayout>(R.id.swiperefresh)
+        refreshLayout.isRefreshing = false
+        refreshLayout.setOnRefreshListener {
+            Log.v(TAG, "refreshing!")
+            fetchHistory()
+        }
+
+        this.isLoading.observe(this, androidx.lifecycle.Observer { loading ->
+            Log.v(TAG, "setting refreshing to ${loading}")
+            refreshLayout.isRefreshing = loading
+        })
+
         return view
     }
+
+    companion object {
+        val TAG = "taler-merchant"
+    }
 }
diff --git a/app/src/main/java/net/taler/merchantpos/MerchantSettings.kt 
b/app/src/main/java/net/taler/merchantpos/MerchantSettings.kt
index 1903bce..7797dcb 100644
--- a/app/src/main/java/net/taler/merchantpos/MerchantSettings.kt
+++ b/app/src/main/java/net/taler/merchantpos/MerchantSettings.kt
@@ -1,21 +1,128 @@
 package net.taler.merchantpos
 
+import android.content.Context
 import android.os.Bundle
 import androidx.fragment.app.Fragment
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.Button
+import android.widget.EditText
+import android.widget.TextView
+import androidx.lifecycle.ViewModelProviders
+import com.android.volley.Request
+import com.android.volley.RequestQueue
+import com.android.volley.Response
+import com.android.volley.VolleyError
+import com.android.volley.toolbox.Volley
+import com.google.android.material.snackbar.Snackbar
+import org.json.JSONObject
 
 
 /**
  * Fragment that displays merchant settings.
  */
 class MerchantSettings : Fragment() {
+
+    private lateinit var queue: RequestQueue
+    private lateinit var model: PosTerminalViewModel
+
+    private var newConfig: MerchantConfig? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        model = activity?.run {
+            ViewModelProviders.of(this)[PosTerminalViewModel::class.java]
+        } ?: throw Exception("Invalid Activity")
+
+        queue = Volley.newRequestQueue(context)
+    }
+
+    private fun reset(view: View) {
+        val backendUrlEdit = 
view.findViewById<EditText>(R.id.edit_settings_backend_url)
+        backendUrlEdit.setText(model.merchantConfig!!.baseUrl, 
TextView.BufferType.EDITABLE)
+
+        val backendInstanceEdit = 
view.findViewById<EditText>(R.id.edit_settings_instance)
+        backendInstanceEdit.setText(model.merchantConfig!!.instance, 
TextView.BufferType.EDITABLE)
+
+        val backendApiKeyEdit = 
view.findViewById<EditText>(R.id.edit_settings_apikey)
+        backendApiKeyEdit.setText(model.merchantConfig!!.apiKey, 
TextView.BufferType.EDITABLE)
+
+        val currencyView = 
view.findViewById<TextView>(R.id.text_settings_currency)
+        currencyView.text = model.merchantConfig!!.currency
+    }
+
+
     override fun onCreateView(
         inflater: LayoutInflater, container: ViewGroup?,
         savedInstanceState: Bundle?
     ): View? {
-        // Inflate the layout for this fragment
-        return inflater.inflate(R.layout.fragment_merchant_settings, 
container, false)
+        val view = inflater.inflate(R.layout.fragment_merchant_settings, 
container, false)
+
+        reset(view)
+
+        val buttonApply = view.findViewById<Button>(R.id.button_settings_apply)
+        buttonApply.setOnClickListener {
+
+            val backendUrlEdit = 
view.findViewById<EditText>(R.id.edit_settings_backend_url)
+            val backendInstanceEdit = 
view.findViewById<EditText>(R.id.edit_settings_instance)
+            val backendApiKeyEdit = 
view.findViewById<EditText>(R.id.edit_settings_apikey)
+
+            val config = MerchantConfig(
+                backendUrlEdit.text.toString(),
+                backendInstanceEdit.text.toString(),
+                backendApiKeyEdit.text.toString(),
+                "UNKNOWN"
+            )
+
+            newConfig = config
+
+            val req = MerchantInternalRequest(
+                Request.Method.GET,
+                config,
+                "config",
+                mapOf("instance" to config.instance),
+                null,
+                Response.Listener { onConfigReceived(it) },
+                Response.ErrorListener { onNetworkError(it) })
+
+            queue.add(req)
+
+        }
+
+        val buttonReset = view.findViewById<Button>(R.id.button_settings_reset)
+        buttonReset.setOnClickListener {
+            reset(view)
+        }
+
+        return view
+    }
+
+    private fun onConfigReceived(it: JSONObject) {
+        val currency = it.getString("currency")
+        val mySnackbar =
+            Snackbar.make(view!!, "Changed to new ${currency} merchant", 
Snackbar.LENGTH_SHORT)
+
+        val config = this.newConfig!!.copy(currency = currency)
+        this.newConfig = null
+        model.merchantConfig = config
+
+        val currencyView = 
view!!.findViewById<TextView>(R.id.text_settings_currency)
+        currencyView.text = currency
+
+        mySnackbar.show()
+
+        val prefs = activity!!.getSharedPreferences("taler-merchant-terminal", 
Context.MODE_PRIVATE)
+        prefs.edit().putString("merchantBackendUrl", config.baseUrl)
+            .putString("merchantBackendInstance", config.instance)
+            .putString("merchantBackendApiKey", config.apiKey)
+            .putString("merchantBackendCurrency", config.currency)
+    }
+
+    private fun onNetworkError(it: VolleyError) {
+        val mySnackbar =
+            Snackbar.make(view!!, "Error: Invalid Configuration", 
Snackbar.LENGTH_SHORT)
+        mySnackbar.show()
     }
 }
diff --git a/app/src/main/res/layout/fragment_create_payment.xml 
b/app/src/main/res/layout/fragment_create_payment.xml
index f72f263..c3f2e5f 100644
--- a/app/src/main/res/layout/fragment_create_payment.xml
+++ b/app/src/main/res/layout/fragment_create_payment.xml
@@ -36,7 +36,7 @@
                 android:text="Amount (TESTKUDOS)"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:id="@+id/textView6"/>
+                android:id="@+id/text_create_payment_amount_label"/>
         <EditText
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/fragment_merchant_history.xml 
b/app/src/main/res/layout/fragment_merchant_history.xml
index 92abdf7..abb757c 100644
--- a/app/src/main/res/layout/fragment_merchant_history.xml
+++ b/app/src/main/res/layout/fragment_merchant_history.xml
@@ -1,32 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.core.widget.NestedScrollView
-        xmlns:android="http://schemas.android.com/apk/res/android";
-        xmlns:tools="http://schemas.android.com/tools";
+<androidx.swiperefreshlayout.widget.SwipeRefreshLayout 
xmlns:android="http://schemas.android.com/apk/res/android";
+        android:id="@+id/swiperefresh"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_margin="15dp">
+        android:layout_height="match_parent">
 
-    <LinearLayout
+    <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/list_history"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:orientation="vertical">
+            android:scrollbars="vertical" />
 
-        <View
-                android:id="@+id/header"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
-
-        <androidx.recyclerview.widget.RecyclerView
-                android:id="@+id/list_history"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:scrollbars="vertical"
-                android:layout_marginTop="47dp" android:layout_marginEnd="75dp"
-                android:layout_marginBottom="17dp"/>
-
-        <Button
-                android:text="Button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" 
android:id="@+id/button2"/>
-    </LinearLayout>
-</androidx.core.widget.NestedScrollView>
+</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
diff --git a/app/src/main/res/layout/fragment_merchant_settings.xml 
b/app/src/main/res/layout/fragment_merchant_settings.xml
index 8fcf233..b6e3707 100644
--- a/app/src/main/res/layout/fragment_merchant_settings.xml
+++ b/app/src/main/res/layout/fragment_merchant_settings.xml
@@ -11,5 +11,98 @@
             android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent">
+
+        <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Merchant Backend Base URL" />
+
+        <EditText
+                android:id="@+id/edit_settings_backend_url"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="text"
+                android:text="Name" />
+
+        <Space
+                android:layout_width="match_parent"
+                android:layout_height="40dp" />
+
+        <TextView
+                android:id="@+id/textView4"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Merchant Instance" />
+
+        <EditText
+                android:id="@+id/edit_settings_instance"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="text"
+                android:text="Name" />
+
+        <Space
+                android:layout_width="match_parent"
+                android:layout_height="40dp" />
+
+        <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="API Key" />
+
+        <EditText
+                android:id="@+id/edit_settings_apikey"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:ems="10"
+                android:inputType="textPassword" />
+
+        <Space
+                android:layout_width="match_parent"
+                android:layout_height="40dp" />
+
+        <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Currency" />
+
+        <TextView
+                android:id="@+id/text_settings_currency"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="TextView"
+                
android:textAppearance="@style/TextAppearance.AppCompat.Display1" />
+
+        <Space
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1"/>
+
+        <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+            <Button
+                    android:id="@+id/button_settings_reset"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="bottom|right"
+                    android:text="Reset" />
+
+            <Space
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp"
+                    android:layout_weight="1"/>
+
+            <Button
+                    android:id="@+id/button_settings_apply"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="bottom|right"
+                    android:text="Apply" />
+        </LinearLayout>
     </LinearLayout>
+
 </FrameLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/history_row.xml 
b/app/src/main/res/layout/history_row.xml
index a67cf37..12b93d5 100644
--- a/app/src/main/res/layout/history_row.xml
+++ b/app/src/main/res/layout/history_row.xml
@@ -1,7 +1,74 @@
 <?xml version="1.0" encoding="utf-8"?>
-<TextView xmlns:android="http://schemas.android.com/apk/res/android";
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content"
-              android:id="@+id/historyText"
-              android:textSize="20sp">
-</TextView>
\ No newline at end of file
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android";
+        xmlns:tools="http://schemas.android.com/tools";
+        android:orientation="vertical"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_marginHorizontal="15dp"
+        android:layout_marginVertical="5dp">
+
+    <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:text="1 Euro"
+            android:textSize="20sp"
+            android:textStyle="bold" />
+
+    <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="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:text="2019-08-31 14:25"
+                android:textSize="20sp" />
+
+    </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="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:text="2019.242-014B6QPFMHCTY"
+                android:textAllCaps="false"
+                android:textSize="20sp"
+                android:textStyle="italic" />
+    </LinearLayout>
+
+</LinearLayout>

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



reply via email to

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