aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cashier/build.gradle5
-rw-r--r--cashier/proguard-rules.pro2
-rw-r--r--cashier/src/main/java/net/taler/cashier/BalanceFragment.kt57
-rw-r--r--cashier/src/main/java/net/taler/cashier/MainActivity.kt9
-rw-r--r--cashier/src/main/java/net/taler/cashier/config/Config.kt1
-rw-r--r--cashier/src/main/java/net/taler/cashier/config/ConfigFragment.kt65
-rw-r--r--cashier/src/main/java/net/taler/cashier/withdraw/ErrorFragment.kt13
-rw-r--r--cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt58
8 files changed, 114 insertions, 96 deletions
diff --git a/cashier/build.gradle b/cashier/build.gradle
index f5c56a9..a749353 100644
--- a/cashier/build.gradle
+++ b/cashier/build.gradle
@@ -17,7 +17,6 @@
plugins {
id "com.android.application"
id "kotlin-android"
- id "kotlin-android-extensions"
id "kotlinx-serialization"
id "androidx.navigation.safeargs.kotlin"
}
@@ -51,6 +50,10 @@ android {
jvmTarget = "1.8"
}
+ buildFeatures {
+ viewBinding = true
+ }
+
packagingOptions {
exclude("META-INF/*.kotlin_module")
}
diff --git a/cashier/proguard-rules.pro b/cashier/proguard-rules.pro
index f612b29..a1cc1f6 100644
--- a/cashier/proguard-rules.pro
+++ b/cashier/proguard-rules.pro
@@ -20,6 +20,8 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+-keep class net.taler.cashier.** {*;}
+
# androidx.security:security-crypto
# https://github.com/google/tink/issues/361
-keep class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite { *; }
diff --git a/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt b/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt
index cdfa142..1114080 100644
--- a/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt
+++ b/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt
@@ -29,8 +29,8 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
-import kotlinx.android.synthetic.main.fragment_balance.*
import net.taler.cashier.BalanceFragmentDirections.Companion.actionBalanceFragmentToTransactionFragment
+import net.taler.cashier.databinding.FragmentBalanceBinding
import net.taler.cashier.withdraw.LastTransaction
import net.taler.cashier.withdraw.WithdrawStatus
import net.taler.common.exhaustive
@@ -50,12 +50,15 @@ class BalanceFragment : Fragment() {
private val configManager by lazy { viewModel.configManager}
private val withdrawManager by lazy { viewModel.withdrawManager }
+ private lateinit var ui: FragmentBalanceBinding
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
setHasOptionsMenu(true)
- return inflater.inflate(R.layout.fragment_balance, container, false)
+ ui = FragmentBalanceBinding.inflate(layoutInflater, container, false)
+ return ui.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -65,24 +68,24 @@ class BalanceFragment : Fragment() {
viewModel.balance.observe(viewLifecycleOwner, Observer { result ->
onBalanceUpdated(result)
})
- button5.setOnClickListener { onAmountButtonPressed(5) }
- button10.setOnClickListener { onAmountButtonPressed(10) }
- button20.setOnClickListener { onAmountButtonPressed(20) }
- button50.setOnClickListener { onAmountButtonPressed(50) }
+ ui.button5.setOnClickListener { onAmountButtonPressed(5) }
+ ui.button10.setOnClickListener { onAmountButtonPressed(10) }
+ ui.button20.setOnClickListener { onAmountButtonPressed(20) }
+ ui.button50.setOnClickListener { onAmountButtonPressed(50) }
if (savedInstanceState != null) {
- amountView.editText!!.setText(savedInstanceState.getCharSequence("amountView"))
+ ui.amountView.editText!!.setText(savedInstanceState.getCharSequence("amountView"))
}
- amountView.editText!!.setOnEditorActionListener { _, actionId, _ ->
+ ui.amountView.editText!!.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_GO) {
onAmountConfirmed(getAmountFromView())
true
} else false
}
configManager.currency.observe(viewLifecycleOwner, Observer { currency ->
- currencyView.text = currency
+ ui.currencyView.text = currency
})
- confirmWithdrawalButton.setOnClickListener { onAmountConfirmed(getAmountFromView()) }
+ ui.confirmWithdrawalButton.setOnClickListener { onAmountConfirmed(getAmountFromView()) }
}
override fun onStart() {
@@ -96,7 +99,7 @@ class BalanceFragment : Fragment() {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// for some reason automatic restore isn't working at the moment!?
- amountView?.editText?.text.let {
+ ui.amountView.editText?.text.let {
outState.putCharSequence("amountView", it)
}
}
@@ -121,34 +124,34 @@ class BalanceFragment : Fragment() {
private fun onBalanceUpdated(result: BalanceResult) {
val uiList = listOf(
- introView,
- button5, button10, button20, button50,
- amountView, currencyView, confirmWithdrawalButton
+ ui.introView,
+ ui.button5, ui.button10, ui.button20, ui.button50,
+ ui.amountView, ui.currencyView, ui.confirmWithdrawalButton
)
when (result) {
is BalanceResult.Success -> {
- balanceView.text = result.amount.toString()
+ ui.balanceView.text = result.amount.toString()
uiList.forEach { it.fadeIn() }
}
is BalanceResult.Error -> {
- balanceView.text = getString(R.string.balance_error, result.msg)
+ ui.balanceView.text = getString(R.string.balance_error, result.msg)
uiList.forEach { it.fadeOut() }
}
BalanceResult.Offline -> {
- balanceView.text = getString(R.string.balance_offline)
+ ui.balanceView.text = getString(R.string.balance_offline)
uiList.forEach { it.fadeOut() }
}
}.exhaustive
- progressBar.fadeOut()
+ ui.progressBar.fadeOut()
}
private fun onAmountButtonPressed(amount: Int) {
- amountView.editText!!.setText(amount.toString())
- amountView.error = null
+ ui.amountView.editText!!.setText(amount.toString())
+ ui.amountView.error = null
}
private fun getAmountFromView(): Amount {
- val str = amountView.editText!!.text.toString()
+ val str = ui.amountView.editText!!.text.toString()
val currency = configManager.currency.value!!
if (str.isBlank()) return Amount.zero(currency)
return Amount.fromString(currency, str)
@@ -156,11 +159,11 @@ class BalanceFragment : Fragment() {
private fun onAmountConfirmed(amount: Amount) {
if (amount.isZero()) {
- amountView.error = getString(R.string.withdraw_error_zero)
+ ui.amountView.error = getString(R.string.withdraw_error_zero)
} else if (!withdrawManager.hasSufficientBalance(amount)) {
- amountView.error = getString(R.string.withdraw_error_insufficient_balance)
+ ui.amountView.error = getString(R.string.withdraw_error_insufficient_balance)
} else {
- amountView.error = null
+ ui.amountView.error = null
withdrawManager.withdraw(amount)
actionBalanceFragmentToTransactionFragment().let {
findNavController().navigate(it)
@@ -177,13 +180,13 @@ class BalanceFragment : Fragment() {
is WithdrawStatus.Aborted -> getString(R.string.transaction_last_aborted)
else -> getString(R.string.transaction_last_error)
}
- lastTransactionView.text = text
+ ui.lastTransactionView.text = text
val drawable = if (status == WithdrawStatus.Success)
R.drawable.ic_check_circle
else
R.drawable.ic_error
- lastTransactionView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, 0, 0, 0)
- lastTransactionView.visibility = VISIBLE
+ ui.lastTransactionView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, 0, 0, 0)
+ ui.lastTransactionView.visibility = VISIBLE
}
}
diff --git a/cashier/src/main/java/net/taler/cashier/MainActivity.kt b/cashier/src/main/java/net/taler/cashier/MainActivity.kt
index ae31be5..2f4c4ec 100644
--- a/cashier/src/main/java/net/taler/cashier/MainActivity.kt
+++ b/cashier/src/main/java/net/taler/cashier/MainActivity.kt
@@ -25,18 +25,21 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
-import kotlinx.android.synthetic.main.activity_main.*
+import net.taler.cashier.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
private val configManager by lazy { viewModel.configManager}
+
+ private lateinit var ui: ActivityMainBinding
private lateinit var nav: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- setSupportActionBar(toolbar)
+ ui = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(ui.root)
+ setSupportActionBar(ui.toolbar)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
nav = navHostFragment.navController
diff --git a/cashier/src/main/java/net/taler/cashier/config/Config.kt b/cashier/src/main/java/net/taler/cashier/config/Config.kt
index b50cf92..c898f95 100644
--- a/cashier/src/main/java/net/taler/cashier/config/Config.kt
+++ b/cashier/src/main/java/net/taler/cashier/config/Config.kt
@@ -17,7 +17,6 @@
package net.taler.cashier.config
import kotlinx.serialization.Serializable
-import net.taler.lib.common.Version
import okhttp3.Credentials
data class Config(
diff --git a/cashier/src/main/java/net/taler/cashier/config/ConfigFragment.kt b/cashier/src/main/java/net/taler/cashier/config/ConfigFragment.kt
index a7aaf2f..6498590 100644
--- a/cashier/src/main/java/net/taler/cashier/config/ConfigFragment.kt
+++ b/cashier/src/main/java/net/taler/cashier/config/ConfigFragment.kt
@@ -33,9 +33,9 @@ import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import com.google.android.material.snackbar.BaseTransientBottomBar.LENGTH_LONG
import com.google.android.material.snackbar.Snackbar
-import kotlinx.android.synthetic.main.fragment_config.*
import net.taler.cashier.MainViewModel
import net.taler.cashier.R
+import net.taler.cashier.databinding.FragmentConfigBinding
import net.taler.common.exhaustive
private const val URL_BANK_TEST = "https://bank.test.taler.net"
@@ -46,38 +46,41 @@ class ConfigFragment : Fragment() {
private val viewModel: MainViewModel by activityViewModels()
private val configManager by lazy { viewModel.configManager}
+ private lateinit var ui: FragmentConfigBinding
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- return inflater.inflate(R.layout.fragment_config, container, false)
+ ui = FragmentConfigBinding.inflate(inflater, container, false)
+ return ui.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (savedInstanceState == null) {
if (configManager.config.bankUrl.isBlank()) {
- urlView.editText!!.setText(URL_BANK_TEST)
+ ui.urlView.editText!!.setText(URL_BANK_TEST)
} else {
- urlView.editText!!.setText(configManager.config.bankUrl)
+ ui.urlView.editText!!.setText(configManager.config.bankUrl)
}
- usernameView.editText!!.setText(configManager.config.username)
- passwordView.editText!!.setText(configManager.config.password)
+ ui.usernameView.editText!!.setText(configManager.config.username)
+ ui.passwordView.editText!!.setText(configManager.config.password)
} else {
- urlView.editText!!.setText(savedInstanceState.getCharSequence("urlView"))
- usernameView.editText!!.setText(savedInstanceState.getCharSequence("usernameView"))
- passwordView.editText!!.setText(savedInstanceState.getCharSequence("passwordView"))
+ ui.urlView.editText!!.setText(savedInstanceState.getCharSequence("urlView"))
+ ui.usernameView.editText!!.setText(savedInstanceState.getCharSequence("usernameView"))
+ ui.passwordView.editText!!.setText(savedInstanceState.getCharSequence("passwordView"))
}
- saveButton.setOnClickListener {
+ ui.saveButton.setOnClickListener {
val config = Config(
- bankUrl = urlView.editText!!.text.toString(),
- username = usernameView.editText!!.text.toString(),
- password = passwordView.editText!!.text.toString()
+ bankUrl = ui.urlView.editText!!.text.toString(),
+ username = ui.usernameView.editText!!.text.toString(),
+ password = ui.passwordView.editText!!.text.toString()
)
if (checkConfig(config)) {
// show progress
- saveButton.visibility = INVISIBLE
- progressBar.visibility = VISIBLE
+ ui.saveButton.visibility = INVISIBLE
+ ui.progressBar.visibility = VISIBLE
// kick off check and observe result
configManager.checkAndSaveConfig(config)
configManager.configResult.observe(viewLifecycleOwner, onConfigResult)
@@ -87,43 +90,43 @@ class ConfigFragment : Fragment() {
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
}
- demoView.text = HtmlCompat.fromHtml(
+ ui.demoView.text = HtmlCompat.fromHtml(
getString(R.string.config_demo_hint, URL_BANK_TEST_REGISTER), FROM_HTML_MODE_LEGACY
)
- demoView.movementMethod = LinkMovementMethod.getInstance()
+ ui.demoView.movementMethod = LinkMovementMethod.getInstance()
}
override fun onStart() {
super.onStart()
// focus on password if it is the only missing value (like after locking)
- if (urlView.editText!!.text.isNotBlank()
- && usernameView.editText!!.text.isNotBlank()
- && passwordView.editText!!.text.isBlank()
+ if (ui.urlView.editText!!.text.isNotBlank()
+ && ui.usernameView.editText!!.text.isNotBlank()
+ && ui.passwordView.editText!!.text.isBlank()
) {
- passwordView.editText!!.requestFocus()
+ ui.passwordView.editText!!.requestFocus()
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// for some reason automatic restore isn't working at the moment!?
- outState.putCharSequence("urlView", urlView.editText?.text)
- outState.putCharSequence("usernameView", usernameView.editText?.text)
- outState.putCharSequence("passwordView", passwordView.editText?.text)
+ outState.putCharSequence("urlView", ui.urlView.editText?.text)
+ outState.putCharSequence("usernameView", ui.usernameView.editText?.text)
+ outState.putCharSequence("passwordView", ui.passwordView.editText?.text)
}
private fun checkConfig(config: Config): Boolean {
if (!config.bankUrl.startsWith("https://")) {
- urlView.error = getString(R.string.config_bank_url_error)
- urlView.requestFocus()
+ ui.urlView.error = getString(R.string.config_bank_url_error)
+ ui.urlView.requestFocus()
return false
}
if (config.username.isBlank()) {
- usernameView.error = getString(R.string.config_username_error)
- usernameView.requestFocus()
+ ui.usernameView.error = getString(R.string.config_username_error)
+ ui.usernameView.requestFocus()
return false
}
- urlView.isErrorEnabled = false
+ ui.urlView.isErrorEnabled = false
return true
}
@@ -146,8 +149,8 @@ class ConfigFragment : Fragment() {
}
}
}.exhaustive
- saveButton.visibility = VISIBLE
- progressBar.visibility = INVISIBLE
+ ui.saveButton.visibility = VISIBLE
+ ui.progressBar.visibility = INVISIBLE
configManager.configResult.removeObservers(viewLifecycleOwner)
}
diff --git a/cashier/src/main/java/net/taler/cashier/withdraw/ErrorFragment.kt b/cashier/src/main/java/net/taler/cashier/withdraw/ErrorFragment.kt
index ea33b0d..4f98847 100644
--- a/cashier/src/main/java/net/taler/cashier/withdraw/ErrorFragment.kt
+++ b/cashier/src/main/java/net/taler/cashier/withdraw/ErrorFragment.kt
@@ -24,33 +24,36 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
-import kotlinx.android.synthetic.main.fragment_error.*
import net.taler.cashier.MainViewModel
import net.taler.cashier.R
+import net.taler.cashier.databinding.FragmentErrorBinding
class ErrorFragment : Fragment() {
private val viewModel: MainViewModel by activityViewModels()
private val withdrawManager by lazy { viewModel.withdrawManager }
+ private lateinit var ui: FragmentErrorBinding
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- return inflater.inflate(R.layout.fragment_error, container, false)
+ ui = FragmentErrorBinding.inflate(inflater, container, false)
+ return ui.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
withdrawManager.withdrawStatus.observe(viewLifecycleOwner, Observer { status ->
if (status == null) return@Observer
if (status is WithdrawStatus.Aborted) {
- textView.setText(R.string.transaction_aborted)
+ ui.textView.setText(R.string.transaction_aborted)
} else if (status is WithdrawStatus.Error) {
- textView.text = status.msg
+ ui.textView.text = status.msg
}
withdrawManager.completeTransaction()
})
- backButton.setOnClickListener {
+ ui.backButton.setOnClickListener {
findNavController().popBackStack()
}
}
diff --git a/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt b/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt
index 0726a77..ffb1539 100644
--- a/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt
+++ b/cashier/src/main/java/net/taler/cashier/withdraw/TransactionFragment.kt
@@ -25,11 +25,10 @@ import android.view.ViewGroup
import androidx.core.content.ContextCompat.getColor
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
-import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
-import kotlinx.android.synthetic.main.fragment_transaction.*
import net.taler.cashier.MainViewModel
import net.taler.cashier.R
+import net.taler.cashier.databinding.FragmentTransactionBinding
import net.taler.cashier.withdraw.TransactionFragmentDirections.Companion.actionTransactionFragmentToBalanceFragment
import net.taler.cashier.withdraw.TransactionFragmentDirections.Companion.actionTransactionFragmentToErrorFragment
import net.taler.cashier.withdraw.WithdrawResult.Error
@@ -46,30 +45,33 @@ class TransactionFragment : Fragment() {
private val withdrawManager by lazy { viewModel.withdrawManager }
private val nfcManager = NfcManager()
+ private lateinit var ui: FragmentTransactionBinding
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- return inflater.inflate(R.layout.fragment_transaction, container, false)
+ ui = FragmentTransactionBinding.inflate(inflater, container, false)
+ return ui.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- withdrawManager.withdrawAmount.observe(viewLifecycleOwner, Observer { amount ->
- amountView.text = amount?.toString()
+ withdrawManager.withdrawAmount.observe(viewLifecycleOwner, { amount ->
+ ui.amountView.text = amount?.toString()
})
- withdrawManager.withdrawResult.observe(viewLifecycleOwner, Observer { result ->
+ withdrawManager.withdrawResult.observe(viewLifecycleOwner, { result ->
onWithdrawResultReceived(result)
})
- withdrawManager.withdrawStatus.observe(viewLifecycleOwner, Observer { status ->
+ withdrawManager.withdrawStatus.observe(viewLifecycleOwner, { status ->
onWithdrawStatusChanged(status)
})
// change intro text depending on whether NFC is available or not
val hasNfc = NfcManager.hasNfc(requireContext())
val intro = if (hasNfc) R.string.transaction_intro_nfc else R.string.transaction_intro
- introView.setText(intro)
+ ui.introView.setText(intro)
- cancelButton.setOnClickListener {
+ ui.cancelButton.setOnClickListener {
findNavController().popBackStack()
}
}
@@ -95,9 +97,9 @@ class TransactionFragment : Fragment() {
private fun onWithdrawResultReceived(result: WithdrawResult?) {
if (result != null) {
- progressBar.animate()
+ ui.progressBar.animate()
.alpha(0f)
- .withEndAction { progressBar?.visibility = INVISIBLE }
+ .withEndAction { ui.progressBar.visibility = INVISIBLE }
.setDuration(750)
.start()
}
@@ -113,12 +115,12 @@ class TransactionFragment : Fragment() {
nfcManager
)
// show QR code
- qrCodeView.alpha = 0f
- qrCodeView.animate()
+ ui.qrCodeView.alpha = 0f
+ ui.qrCodeView.animate()
.alpha(1f)
.withStartAction {
- qrCodeView.visibility = VISIBLE
- qrCodeView.setImageBitmap(result.qrCode)
+ ui.qrCodeView.visibility = VISIBLE
+ ui.qrCodeView.setImageBitmap(result.qrCode)
}
.setDuration(750)
.start()
@@ -129,30 +131,30 @@ class TransactionFragment : Fragment() {
private fun setErrorMsg(str: String) {
val c = getColor(requireContext(), R.color.design_default_color_error)
- introView.setTextColor(c)
- introView.text = str
+ ui.introView.setTextColor(c)
+ ui.introView.text = str
}
private fun onWithdrawStatusChanged(status: WithdrawStatus?): Any = when (status) {
is WithdrawStatus.SelectionDone -> {
- qrCodeView.fadeOut {
- qrCodeView?.setImageResource(R.drawable.ic_arrow)
- qrCodeView?.fadeIn()
+ ui.qrCodeView.fadeOut {
+ ui.qrCodeView.setImageResource(R.drawable.ic_arrow)
+ ui.qrCodeView.fadeIn()
}
- introView.fadeOut {
- introView?.text = getString(R.string.transaction_intro_scanned)
- introView?.fadeIn {
- confirmButton?.isEnabled = true
- confirmButton?.setOnClickListener {
+ ui.introView.fadeOut {
+ ui.introView.text = getString(R.string.transaction_intro_scanned)
+ ui.introView.fadeIn {
+ ui.confirmButton.isEnabled = true
+ ui.confirmButton.setOnClickListener {
withdrawManager.confirm(status.withdrawalId)
}
}
}
}
is WithdrawStatus.Confirming -> {
- confirmButton.isEnabled = false
- qrCodeView.fadeOut()
- progressBar.fadeIn()
+ ui.confirmButton.isEnabled = false
+ ui.qrCodeView.fadeOut()
+ ui.progressBar.fadeIn()
}
is WithdrawStatus.Success -> {
withdrawManager.completeTransaction()