From 395e2308a0785a524b4de04dfdeec74148456941 Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Sun, 31 May 2026 01:25:50 +0500 Subject: [PATCH] keep transfer form in cache (no reset on page change --- .../sh/sar/basedbank/ui/home/HomeActivity.kt | 5 +- .../sar/basedbank/ui/home/TransferFragment.kt | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt index 0085964..a70509a 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/HomeActivity.kt @@ -76,6 +76,7 @@ class HomeActivity : AppCompatActivity() { private val viewModel: HomeViewModel by viewModels() private lateinit var toggle: ActionBarDrawerToggle private var suppressBottomNavCallback = false + private var cachedTransferFragment: TransferFragment? = null private var backPressedOnce = false private val backPressHandler = Handler(Looper.getMainLooper()) @@ -156,7 +157,7 @@ class HomeActivity : AppCompatActivity() { R.id.nav_dashboard -> DashboardFragment() R.id.nav_accounts -> AccountsFragment() R.id.nav_contacts -> ContactsFragment() - R.id.nav_transfer -> TransferFragment() + R.id.nav_transfer -> cachedTransferFragment ?: TransferFragment().also { cachedTransferFragment = it } R.id.nav_pay_mv_qr -> PayMvQrFragment() R.id.nav_more -> MoreFragment() R.id.nav_activities -> ActivitiesFragment() @@ -390,7 +391,7 @@ fun applyNavLabelVisibility() { R.id.nav_dashboard -> DashboardFragment() R.id.nav_accounts -> AccountsFragment() R.id.nav_contacts -> ContactsFragment() - R.id.nav_transfer -> TransferFragment() + R.id.nav_transfer -> cachedTransferFragment ?: TransferFragment().also { cachedTransferFragment = it } R.id.nav_pay_mv_qr -> PayMvQrFragment() R.id.nav_activities -> ActivitiesFragment() R.id.nav_transfer_history -> TransferHistoryFragment() diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt index d90ac56..513e052 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/TransferFragment.kt @@ -92,6 +92,14 @@ class TransferFragment : Fragment() { // Values: "FAHIPAY_TRANSFER", "RAASTAS", "OOREDOO_BILL" private var selectedFahipayService: String? = null + // Form state preserved across view destroy/create when the fragment instance is cached + private var savedAmount = "" + private var savedRemarks = "" + private var savedToText = "" + private var savedToSubtitle = "" + private var savedToColorHex = "#607D8B" + private var savedToImageHash: String? = null + // BML QR merchant payment mode (set when navigated from a card QR scan) private var bmlQrInfo: BmlQrPayInfo? = null private var bmlGatewayQr = false // true for pay.bml.com.mv QRs (requires pre-initiate step) @@ -306,6 +314,33 @@ class TransferFragment : Fragment() { if (arguments?.getBoolean(ARG_AUTO_SCAN, false) == true) { qrLauncher.launch(Intent(requireContext(), QrScannerActivity::class.java)) } + + // Restore form state when view is recreated on the cached no-args instance + if (arguments == null) { + if (resolvedAccountNumber.isNotEmpty()) { + val ownAccount = viewModel.accounts.value?.firstOrNull { it.accountNumber == resolvedAccountNumber } + if (ownAccount != null) { + showToCard(ownAccount) + } else { + binding.tvToAccountName.text = resolvedRecipientName + binding.tvToBankBic.text = savedToSubtitle + binding.tvToAccountDetails.visibility = View.GONE + binding.tvToBalance.visibility = View.GONE + binding.ivToPhoto.scaleType = android.widget.ImageView.ScaleType.CENTER_CROP + binding.ivToPhoto.setImageBitmap(makeInitialsBitmap(resolvedRecipientName, savedToColorHex)) + } + binding.tilTo.visibility = View.GONE + binding.btnPickContact.visibility = View.GONE + binding.btnScanQr.visibility = View.GONE + binding.cardToInfo.visibility = View.VISIBLE + if (savedToImageHash != null) loadToPhoto(savedToImageHash!!, isProfile = resolvedToOwnAccount != null) + } else if (savedToText.isNotEmpty()) { + binding.etTo.setText(savedToText) + } + if (savedAmount.isNotEmpty()) binding.etAmount.setText(savedAmount) + if (savedRemarks.isNotEmpty()) binding.etRemarks.setText(savedRemarks) + updateTransferButton() + } } private fun lookupBmlQrMerchant(qrUrl: String) { @@ -472,6 +507,13 @@ class TransferFragment : Fragment() { val app = requireActivity().application as BasedBankApp if (app.anyBmlSession() != null) lookupBmlQrMerchant(pendingBmlQrUrl) } + + // Re-render the from card when the view is recreated on a cached instance + if (selectedAccount != null && binding.cardFromInfo.visibility != View.VISIBLE) { + updateAmountPrefix(selectedAccount!!) + showFromCard(selectedAccount!!) + updateTransferButton() + } } } @@ -757,6 +799,13 @@ class TransferFragment : Fragment() { resolvedAccountNumber = info.accountNumber resolvedRecipientName = info.accountName resolvedBankName = info.bankId + savedToSubtitle = "${info.accountNumber} · ${info.bankId}" + savedToColorHex = colorHex + savedToImageHash = when { + matchedAcc?.profileImageHash != null -> matchedAcc.profileImageHash + matchedCont?.customerImgHash != null -> matchedCont.customerImgHash + else -> null + } if (matchedAcc != null) { showToCard(matchedAcc) @@ -889,6 +938,9 @@ class TransferFragment : Fragment() { ) { resolvedAccountNumber = accountNumber resolvedRecipientName = displayName + savedToSubtitle = subtitle + savedToColorHex = colorHex + savedToImageHash = imageHash val contacts = viewModel.contacts.value ?: emptyList() resolvedBankName = contacts.firstOrNull { it.benefAccount == accountNumber }?.benefBankName ?: "" @@ -2079,6 +2131,14 @@ class TransferFragment : Fragment() { override fun onDestroyView() { super.onDestroyView() + // Persist form state so it can be restored when the view is recreated + savedAmount = binding.etAmount.text?.toString() ?: "" + savedRemarks = binding.etRemarks.text?.toString() ?: "" + savedToText = if (resolvedAccountNumber.isEmpty()) binding.etTo.text?.toString() ?: "" else "" + // Reset in-progress OTP flow — it cannot sensibly resume after the view is gone + bmlOtpState = BmlOtpState.NONE + pendingBmlTransfer = null + bmlOtpChannel = null _binding = null }