From a4796ec47d89a851b260b6fc195494547208a025 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 18 Mar 2020 14:24:41 -0300 Subject: Merge all three apps into one repository --- .../main/java/net/taler/cashier/BalanceFragment.kt | 182 +++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 cashier/src/main/java/net/taler/cashier/BalanceFragment.kt (limited to 'cashier/src/main/java/net/taler/cashier/BalanceFragment.kt') diff --git a/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt b/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt new file mode 100644 index 0000000..b3a0221 --- /dev/null +++ b/cashier/src/main/java/net/taler/cashier/BalanceFragment.kt @@ -0,0 +1,182 @@ +/* + * 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 + */ + +package net.taler.cashier + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.View.VISIBLE +import android.view.ViewGroup +import android.view.inputmethod.EditorInfo +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.withdraw.LastTransaction +import net.taler.cashier.withdraw.WithdrawStatus + +sealed class BalanceResult { + object Error : BalanceResult() + object Offline : BalanceResult() + class Success(val amount: Amount) : BalanceResult() +} + +class BalanceFragment : Fragment() { + + private val viewModel: MainViewModel by activityViewModels() + private val withdrawManager by lazy { viewModel.withdrawManager } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + setHasOptionsMenu(true) + return inflater.inflate(R.layout.fragment_balance, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + withdrawManager.lastTransaction.observe(viewLifecycleOwner, Observer { lastTransaction -> + onLastTransaction(lastTransaction) + }) + viewModel.balance.observe(viewLifecycleOwner, Observer { result -> + when (result) { + is BalanceResult.Success -> onBalanceUpdated(result.amount) + else -> onBalanceUpdated(null, result is BalanceResult.Offline) + } + }) + button5.setOnClickListener { onAmountButtonPressed(5) } + button10.setOnClickListener { onAmountButtonPressed(10) } + button20.setOnClickListener { onAmountButtonPressed(20) } + button50.setOnClickListener { onAmountButtonPressed(50) } + + if (savedInstanceState != null) { + amountView.editText!!.setText(savedInstanceState.getCharSequence("amountView")) + } + amountView.editText!!.setOnEditorActionListener { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_GO) { + onAmountConfirmed(getAmountFromView()) + true + } else false + } + viewModel.currency.observe(viewLifecycleOwner, Observer { currency -> + currencyView.text = currency + }) + confirmWithdrawalButton.setOnClickListener { onAmountConfirmed(getAmountFromView()) } + } + + override fun onStart() { + super.onStart() + // update balance if there's a config + if (viewModel.hasConfig()) { + viewModel.getBalance() + } + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + // for some reason automatic restore isn't working at the moment!? + amountView?.editText?.text.let { + outState.putCharSequence("amountView", it) + } + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.balance, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { + R.id.action_reconfigure -> { + findNavController().navigate(viewModel.configDestination) + true + } + R.id.action_lock -> { + viewModel.lock() + findNavController().navigate(viewModel.configDestination) + true + } + else -> super.onOptionsItemSelected(item) + } + + private fun onBalanceUpdated(amount: Amount?, isOffline: Boolean = false) { + val uiList = listOf( + introView, + button5, button10, button20, button50, + amountView, currencyView, confirmWithdrawalButton + ) + if (amount == null) { + balanceView.text = + getString(if (isOffline) R.string.balance_offline else R.string.balance_error) + uiList.forEach { it.fadeOut() } + } else { + @SuppressLint("SetTextI18n") + balanceView.text = "${amount.amount} ${amount.currency}" + uiList.forEach { it.fadeIn() } + } + progressBar.fadeOut() + } + + 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 (!withdrawManager.hasSufficientBalance(amount)) { + amountView.error = getString(R.string.withdraw_error_insufficient_balance) + } else { + amountView.error = null + withdrawManager.withdraw(amount) + actionBalanceFragmentToTransactionFragment().let { + findNavController().navigate(it) + } + } + } + + private fun onLastTransaction(lastTransaction: LastTransaction?) { + val status = lastTransaction?.withdrawStatus + val text = when (status) { + is WithdrawStatus.Success -> getString( + R.string.transaction_last_success, lastTransaction.withdrawAmount + ) + is WithdrawStatus.Aborted -> getString(R.string.transaction_last_aborted) + else -> getString(R.string.transaction_last_error) + } + 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 + } + +} -- cgit v1.2.3