[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-cashier-terminal-android] 01/06: Add screen for entering amount t
From: |
gnunet |
Subject: |
[taler-cashier-terminal-android] 01/06: Add screen for entering amount to withdraw |
Date: |
Wed, 19 Feb 2020 21:31:55 +0100 |
This is an automated email from the git hooks/post-receive script.
torsten-grote pushed a commit to branch master
in repository cashier-terminal-android.
commit 3d2d9d50caa071d1568d59abdf9348d952104dc8
Author: Torsten Grote <address@hidden>
AuthorDate: Mon Feb 10 10:54:56 2020 -0300
Add screen for entering amount to withdraw
---
.../main/java/net/taler/cashier/BalanceFragment.kt | 6 +-
.../main/java/net/taler/cashier/MainViewModel.kt | 10 ++
.../java/net/taler/cashier/TransactionFragment.kt | 26 +++++
.../java/net/taler/cashier/WithdrawFragment.kt | 68 +++++++++++++
app/src/main/res/drawable/ic_check.xml | 9 ++
app/src/main/res/drawable/ic_clear.xml | 9 ++
app/src/main/res/layout/fragment_transaction.xml | 19 ++++
app/src/main/res/layout/fragment_withdraw.xml | 112 +++++++++++++++++++++
app/src/main/res/navigation/nav_graph.xml | 28 +++++-
app/src/main/res/values/strings.xml | 5 +
app/src/main/res/values/styles.xml | 7 ++
11 files changed, 295 insertions(+), 4 deletions(-)
diff --git a/app/src/main/java/net/taler/cashier/BalanceFragment.kt
b/app/src/main/java/net/taler/cashier/BalanceFragment.kt
index 987553f..90e2e8b 100644
--- a/app/src/main/java/net/taler/cashier/BalanceFragment.kt
+++ b/app/src/main/java/net/taler/cashier/BalanceFragment.kt
@@ -12,8 +12,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
-import com.google.android.material.snackbar.Snackbar
-import com.google.android.material.snackbar.Snackbar.LENGTH_LONG
import kotlinx.android.synthetic.main.fragment_balance.*
class BalanceFragment : Fragment() {
@@ -34,7 +32,9 @@ class BalanceFragment : Fragment() {
progressBar.visibility = INVISIBLE
})
fab.setOnClickListener {
- Snackbar.make(fab, "Withdrawals are not yet implemented!",
LENGTH_LONG).show()
+
BalanceFragmentDirections.actionBalanceFragmentToWithdrawFragment().let {
+ findNavController().navigate(it)
+ }
}
}
diff --git a/app/src/main/java/net/taler/cashier/MainViewModel.kt
b/app/src/main/java/net/taler/cashier/MainViewModel.kt
index e9d4d94..a6accfe 100644
--- a/app/src/main/java/net/taler/cashier/MainViewModel.kt
+++ b/app/src/main/java/net/taler/cashier/MainViewModel.kt
@@ -47,6 +47,8 @@ class MainViewModel(private val app: Application) :
AndroidViewModel(app) {
private val mBalance = MutableLiveData<String>()
val balance: LiveData<String> = mBalance
+ var currentWithdrawAmount: Int = 0
+
fun hasConfig() = config.bankUrl.isNotEmpty()
&& config.username.isNotEmpty()
&& config.password.isNotEmpty()
@@ -120,6 +122,14 @@ class MainViewModel(private val app: Application) :
AndroidViewModel(app) {
saveConfig(config.copy(password=""))
}
+ @UiThread
+ fun hasSufficientBalance(amount: Int): Boolean {
+ val balanceStr = balance.value?.split(' ')?.get(0)
+ if (balanceStr == app.getString(R.string.balance_error)) return false
+ val balanceDouble = balanceStr?.toDouble() ?: 0.0
+ return amount <= balanceDouble
+ }
+
}
data class Config(
diff --git a/app/src/main/java/net/taler/cashier/TransactionFragment.kt
b/app/src/main/java/net/taler/cashier/TransactionFragment.kt
new file mode 100644
index 0000000..1c9c0db
--- /dev/null
+++ b/app/src/main/java/net/taler/cashier/TransactionFragment.kt
@@ -0,0 +1,26 @@
+package net.taler.cashier
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import kotlinx.android.synthetic.main.fragment_transaction.*
+
+class TransactionFragment : Fragment() {
+
+ private val viewModel: MainViewModel by activityViewModels()
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_transaction, container,
false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ test.text = viewModel.currentWithdrawAmount.toString()
+ }
+
+}
diff --git a/app/src/main/java/net/taler/cashier/WithdrawFragment.kt
b/app/src/main/java/net/taler/cashier/WithdrawFragment.kt
new file mode 100644
index 0000000..08db4af
--- /dev/null
+++ b/app/src/main/java/net/taler/cashier/WithdrawFragment.kt
@@ -0,0 +1,68 @@
+package net.taler.cashier
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.EditorInfo.IME_ACTION_GO
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.navigation.fragment.findNavController
+import kotlinx.android.synthetic.main.fragment_withdraw.*
+
+class WithdrawFragment : Fragment() {
+
+ private val viewModel: MainViewModel by activityViewModels()
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_withdraw, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ button5.setOnClickListener { onAmountButtonPressed(5) }
+ button10.setOnClickListener { onAmountButtonPressed(10) }
+ button20.setOnClickListener { onAmountButtonPressed(20) }
+ button50.setOnClickListener { onAmountButtonPressed(50) }
+
+ amountView.editText!!.setOnEditorActionListener { _, actionId, _ ->
+ if (actionId == IME_ACTION_GO) {
+ onAmountConfirmed(getAmountFromView())
+ true
+ } else false
+ }
+ clearButton.setOnClickListener {
+ amountView.editText!!.text = null
+ amountView.error = null
+ }
+ fab.setOnClickListener { onAmountConfirmed(getAmountFromView()) }
+ }
+
+ private fun onAmountButtonPressed(amount: Int) {
+ amountView.editText!!.setText(amount.toString())
+ amountView.error = null
+ }
+
+ private fun getAmountFromView(): Int {
+ val str = amountView.editText!!.text.toString()
+ if (str.isBlank()) return 0
+ return Integer.parseInt(str)
+ }
+
+ private fun onAmountConfirmed(amount: Int) {
+ if (amount <= 0) {
+ amountView.error = getString(R.string.withdraw_error_zero)
+ } else if (!viewModel.hasSufficientBalance(amount)) {
+ amountView.error =
getString(R.string.withdraw_error_insufficient_balance)
+ } else {
+ amountView.error = null
+ viewModel.currentWithdrawAmount = amount
+
WithdrawFragmentDirections.actionWithdrawFragmentToTransactionFragment().let {
+ findNavController().navigate(it)
+ }
+ }
+ }
+
+}
diff --git a/app/src/main/res/drawable/ic_check.xml
b/app/src/main/res/drawable/ic_check.xml
new file mode 100644
index 0000000..3c728c5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_clear.xml
b/app/src/main/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..f50fd99
--- /dev/null
+++ b/app/src/main/res/drawable/ic_clear.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12
5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
+</vector>
diff --git a/app/src/main/res/layout/fragment_transaction.xml
b/app/src/main/res/layout/fragment_transaction.xml
new file mode 100644
index 0000000..533593d
--- /dev/null
+++ b/app/src/main/res/layout/fragment_transaction.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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:id="@+id/frameLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".TransactionFragment">
+
+ <TextView
+ android:id="@+id/test"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/fragment_withdraw.xml
b/app/src/main/res/layout/fragment_withdraw.xml
new file mode 100644
index 0000000..4a98660
--- /dev/null
+++ b/app/src/main/res/layout/fragment_withdraw.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".WithdrawFragment">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/introView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="32dp"
+ android:text="@string/withdraw_into"
+ android:textSize="16sp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.google.android.material.textfield.TextInputLayout
+ android:id="@+id/amountView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="32dp"
+ app:boxBackgroundMode="outline"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button5">
+
+ <com.google.android.material.textfield.TextInputEditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="6"
+ android:imeOptions="actionGo"
+ android:inputType="number"
+ android:maxLength="4" />
+
+ </com.google.android.material.textfield.TextInputLayout>
+
+ <androidx.appcompat.widget.AppCompatImageButton
+ android:id="@+id/clearButton"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/withdraw_clear"
+ android:src="@drawable/ic_clear"
+ app:layout_constraintEnd_toEndOf="@+id/amountView"
+ app:layout_constraintTop_toTopOf="@+id/amountView"
+ app:tint="?attr/colorControlNormal" />
+
+ <Button
+ android:id="@+id/button5"
+ style="@style/AmountButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="5"
+ app:layout_constraintEnd_toStartOf="@+id/button10"
+ app:layout_constraintHorizontal_chainStyle="packed"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/introView"
+ tools:ignore="HardcodedText" />
+
+ <Button
+ android:id="@+id/button10"
+ style="@style/AmountButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="10"
+ app:layout_constraintEnd_toStartOf="@+id/button20"
+ app:layout_constraintStart_toEndOf="@+id/button5"
+ app:layout_constraintTop_toBottomOf="@+id/introView"
+ tools:ignore="HardcodedText" />
+
+ <Button
+ android:id="@+id/button20"
+ style="@style/AmountButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="20"
+ app:layout_constraintEnd_toStartOf="@+id/button50"
+ app:layout_constraintStart_toEndOf="@+id/button10"
+ app:layout_constraintTop_toBottomOf="@+id/introView"
+ tools:ignore="HardcodedText" />
+
+ <Button
+ android:id="@+id/button50"
+ style="@style/AmountButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="50"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/button20"
+ app:layout_constraintTop_toBottomOf="@+id/introView"
+ tools:ignore="HardcodedText" />
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="@dimen/default_margin"
+ android:tint="@color/design_default_color_surface"
+ app:srcCompat="@drawable/ic_check"
+ app:useCompatPadding="true" />
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/navigation/nav_graph.xml
b/app/src/main/res/navigation/nav_graph.xml
index c8870f3..930d13f 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -21,7 +21,33 @@
android:id="@+id/balanceFragment"
android:name="net.taler.cashier.BalanceFragment"
android:label="fragment_balance"
- tools:layout="@layout/fragment_balance" />
+ tools:layout="@layout/fragment_balance">
+ <action
+ android:id="@+id/action_balanceFragment_to_withdrawFragment"
+ app:destination="@id/withdrawFragment"
+ app:enterAnim="@anim/fragment_open_enter"
+ app:exitAnim="@anim/fragment_open_exit"
+ app:launchSingleTop="true" />
+ </fragment>
+
+ <fragment
+ android:id="@+id/withdrawFragment"
+ android:name="net.taler.cashier.WithdrawFragment"
+ android:label="fragment_withdraw"
+ tools:layout="@layout/fragment_withdraw">
+ <action
+ android:id="@+id/action_withdrawFragment_to_transactionFragment"
+ app:destination="@id/transactionFragment"
+ app:enterAnim="@anim/fragment_open_enter"
+ app:exitAnim="@anim/fragment_open_exit"
+ app:launchSingleTop="true" />
+ </fragment>
+
+ <fragment
+ android:id="@+id/transactionFragment"
+ android:name="net.taler.cashier.TransactionFragment"
+ android:label="fragment_transaction"
+ tools:layout="@layout/fragment_transaction" />
<action
android:id="@+id/action_global_configFragment"
diff --git a/app/src/main/res/values/strings.xml
b/app/src/main/res/values/strings.xml
index 2f114de..f122111 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -14,4 +14,9 @@
<string name="action_reconfigure">Reconfigure</string>
<string name="action_lock">Lock</string>
+ <string name="withdraw_clear">clear amount</string>
+ <string name="withdraw_into">How much to cash in?</string>
+ <string name="withdraw_error_zero">Enter positive amount</string>
+ <string name="withdraw_error_insufficient_balance">Insufficient
balance</string>
+
</resources>
diff --git a/app/src/main/res/values/styles.xml
b/app/src/main/res/values/styles.xml
index 35e952e..e3ef098 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -16,4 +16,11 @@
<style name="AppTheme.PopupOverlay"
parent="ThemeOverlay.AppCompat.DayNight" />
+ <style name="AmountButton" parent="Widget.AppCompat.Button.Colored">
+ <item name="android:minWidth">48dp</item>
+ <item name="android:layout_marginStart">@dimen/default_margin</item>
+ <item name="android:layout_marginEnd">@dimen/default_margin</item>
+ <item name="android:layout_marginTop">32dp</item>
+ </style>
+
</resources>
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [taler-cashier-terminal-android] branch master updated (41dc9a4 -> a8307d0), gnunet, 2020/02/19
- [taler-cashier-terminal-android] 03/06: Get and save currency when doing configuration, gnunet, 2020/02/19
- [taler-cashier-terminal-android] 02/06: Use QR code and NFC to make taler:// Uri available, gnunet, 2020/02/19
- [taler-cashier-terminal-android] 01/06: Add screen for entering amount to withdraw,
gnunet <=
- [taler-cashier-terminal-android] 04/06: First complete prototype, gnunet, 2020/02/19
- [taler-cashier-terminal-android] 05/06: Add app logo and optimize UX workflow, gnunet, 2020/02/19
- [taler-cashier-terminal-android] 06/06: Add README, license and copyright headers, gnunet, 2020/02/19