taler-android

Android apps for GNU Taler (wallet, PoS, cashier)
Log | Files | Refs | README | LICENSE

TransactionFragment.kt (6219B)


      1 /*
      2  * This file is part of GNU Taler
      3  * (C) 2020 Taler Systems S.A.
      4  *
      5  * GNU Taler is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3, or (at your option) any later version.
      8  *
      9  * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
     10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11  * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License along with
     14  * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15  */
     16 
     17 package net.taler.cashier.withdraw
     18 
     19 import android.os.Bundle
     20 import android.view.LayoutInflater
     21 import android.view.View
     22 import android.view.View.INVISIBLE
     23 import android.view.View.VISIBLE
     24 import android.view.ViewGroup
     25 import androidx.core.content.ContextCompat.getColor
     26 import androidx.fragment.app.Fragment
     27 import androidx.fragment.app.activityViewModels
     28 import androidx.navigation.fragment.findNavController
     29 import net.taler.cashier.MainViewModel
     30 import net.taler.cashier.R
     31 import net.taler.cashier.databinding.FragmentTransactionBinding
     32 import net.taler.cashier.withdraw.TransactionFragmentDirections.Companion.actionTransactionFragmentToBalanceFragment
     33 import net.taler.cashier.withdraw.TransactionFragmentDirections.Companion.actionTransactionFragmentToErrorFragment
     34 import net.taler.cashier.withdraw.WithdrawResult.Error
     35 import net.taler.cashier.withdraw.WithdrawResult.InsufficientBalance
     36 import net.taler.cashier.withdraw.WithdrawResult.Success
     37 import net.taler.lib.android.exhaustive
     38 import net.taler.lib.android.fadeIn
     39 import net.taler.lib.android.fadeOut
     40 import net.taler.lib.android.TalerNfcService
     41 
     42 class TransactionFragment : Fragment() {
     43 
     44     private val viewModel: MainViewModel by activityViewModels()
     45     private val withdrawManager by lazy { viewModel.withdrawManager }
     46 
     47     private lateinit var ui: FragmentTransactionBinding
     48 
     49     override fun onCreateView(
     50         inflater: LayoutInflater, container: ViewGroup?,
     51         savedInstanceState: Bundle?
     52     ): View {
     53         ui = FragmentTransactionBinding.inflate(inflater, container, false)
     54         return ui.root
     55     }
     56 
     57     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
     58         withdrawManager.withdrawAmount.observe(viewLifecycleOwner) { amount ->
     59             ui.amountView.text = amount?.toString()
     60         }
     61         withdrawManager.withdrawResult.observe(viewLifecycleOwner) { result ->
     62             onWithdrawResultReceived(result)
     63         }
     64         withdrawManager.withdrawStatus.observe(viewLifecycleOwner) { status ->
     65             onWithdrawStatusChanged(status)
     66         }
     67 
     68         // change intro text depending on whether NFC is available or not
     69         val hasNfc = TalerNfcService.hasNfc(requireContext())
     70         val intro = if (hasNfc) R.string.transaction_intro_nfc else R.string.transaction_intro
     71         ui.introView.setText(intro)
     72 
     73         ui.cancelButton.setOnClickListener {
     74             findNavController().popBackStack()
     75         }
     76     }
     77 
     78     override fun onDestroy() {
     79         super.onDestroy()
     80         TalerNfcService.clearNdefPayload(requireActivity())
     81         if (!requireActivity().isChangingConfigurations) {
     82             withdrawManager.abort()
     83         }
     84     }
     85 
     86     private fun onWithdrawResultReceived(result: WithdrawResult?) {
     87         TalerNfcService.clearNdefPayload(requireActivity())
     88 
     89         if (result != null) {
     90             ui.progressBar.animate()
     91                 .alpha(0f)
     92                 .withEndAction { ui.progressBar.visibility = INVISIBLE }
     93                 .setDuration(750)
     94                 .start()
     95         }
     96         when (result) {
     97             is InsufficientBalance -> setErrorMsg(getString(R.string.withdraw_error_insufficient_balance))
     98             is WithdrawResult.Offline -> setErrorMsg(getString(R.string.withdraw_error_offline))
     99             is Error -> setErrorMsg(result.msg)
    100             is Success -> {
    101                 // start NFC
    102                 TalerNfcService.setUri(requireActivity(), result.talerUri)
    103                 // show QR code
    104                 ui.qrCodeView.alpha = 0f
    105                 ui.qrCodeView.animate()
    106                     .alpha(1f)
    107                     .withStartAction {
    108                         ui.qrCodeView.visibility = VISIBLE
    109                         ui.qrCodeView.setImageBitmap(result.qrCode)
    110                     }
    111                     .setDuration(750)
    112                     .start()
    113             }
    114             null -> return
    115         }.exhaustive
    116     }
    117 
    118     private fun setErrorMsg(str: String) {
    119         val c = getColor(requireContext(), R.color.design_default_color_error)
    120         ui.introView.setTextColor(c)
    121         ui.introView.text = str
    122     }
    123 
    124     private fun onWithdrawStatusChanged(status: WithdrawStatus?): Any = when (status) {
    125         is WithdrawStatus.SelectionDone -> {
    126             ui.qrCodeView.fadeOut {
    127                 ui.qrCodeView.setImageResource(R.drawable.ic_arrow)
    128                 ui.qrCodeView.fadeIn()
    129             }
    130             ui.introView.fadeOut {
    131                 ui.introView.text = getString(R.string.transaction_intro_scanned)
    132                 ui.introView.fadeIn {
    133                     ui.confirmButton.isEnabled = true
    134                     ui.confirmButton.setOnClickListener {
    135                         withdrawManager.confirm(status.withdrawalId)
    136                     }
    137                 }
    138             }
    139         }
    140         is WithdrawStatus.Confirming -> {
    141             ui.confirmButton.isEnabled = false
    142             ui.qrCodeView.fadeOut()
    143             // ui.progressBar.fadeIn()
    144         }
    145         is WithdrawStatus.Success -> {
    146             withdrawManager.completeTransaction()
    147             actionTransactionFragmentToBalanceFragment().let {
    148                 findNavController().navigate(it)
    149             }
    150         }
    151         is WithdrawStatus.Aborted -> onError()
    152         is WithdrawStatus.Error -> onError()
    153         null -> {
    154             // no-op
    155         }
    156     }
    157 
    158     private fun onError() {
    159         actionTransactionFragmentToErrorFragment().let {
    160             findNavController().navigate(it)
    161         }
    162     }
    163 
    164 }