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 }