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 dfa64be..39b22c8 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 @@ -760,6 +760,11 @@ fun applyNavLabelVisibility() { else -> hideConnectivityBanner() } + val errors = mutableSetOf() + if (noInternet) errors.add("NO_INTERNET") + serverErrors.forEach { errors.add(it.uppercase()) } + viewModel.connectivityErrors.postValue(errors) + for ((_, session) in app.bmlSessions) refreshBmlLimits(session) for ((loginId, session) in app.mibSessions) { val profiles = app.mibProfilesMap[loginId] ?: emptyList() diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/HomeViewModel.kt b/app/src/main/java/sh/sar/basedbank/ui/home/HomeViewModel.kt index c3b0ffc..298eebc 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/HomeViewModel.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/HomeViewModel.kt @@ -29,4 +29,11 @@ class HomeViewModel : ViewModel() { val mibCards = MutableLiveData?>(null) val hideAmounts = MutableLiveData(false) + + /** + * Set of connectivity error keys from the last refresh. + * Contains "NO_INTERNET" for no network, or uppercase bank names ("MIB", "BML", "FAHIPAY") + * for HTTP 5xx server errors from specific banks. + */ + val connectivityErrors = MutableLiveData>(emptySet()) } 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 99413b6..46e1e87 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 @@ -196,6 +196,8 @@ class TransferFragment : Fragment() { qrLauncher.launch(Intent(requireContext(), QrScannerActivity::class.java)) } + viewModel.connectivityErrors.observe(viewLifecycleOwner) { updateTransferButton() } + binding.btnTransfer.isEnabled = false binding.btnTransfer.setOnClickListener { if (bmlOtpState == BmlOtpState.AWAITING_OTP) verifyBmlOtp() @@ -781,12 +783,6 @@ class TransferFragment : Fragment() { val sess = session ?: return Triple(false, getString(R.string.transfer_session_unavailable), null) val app = requireActivity().application as BasedBankApp val loginId = src.loginTag.removePrefix("mib_") - // Switch to the profile that owns the source account - if (src.profileId.isNotBlank()) { - val profiles = app.mibProfilesMap[loginId] ?: emptyList() - val profile = profiles.firstOrNull { it.profileId == src.profileId } - if (profile != null) app.mibFlowFor(loginId).switchProfile(sess, profile) - } val otp = CredentialStore(requireContext()).loadMibCredentials(loginId)?.otpSeed ?.let { Totp.generate(it) } ?: return Triple(false, "OTP unavailable", null) @@ -803,6 +799,12 @@ class TransferFragment : Fragment() { } } return try { + // Switch to the profile that owns the source account + if (src.profileId.isNotBlank()) { + val profiles = app.mibProfilesMap[loginId] ?: emptyList() + val profile = profiles.firstOrNull { it.profileId == src.profileId } + if (profile != null) app.mibFlowFor(loginId).switchProfile(sess, profile) + } val result = MibTransferClient().transfer( session = sess, fromAccount = src.accountNumber, @@ -1215,7 +1217,12 @@ class TransferFragment : Fragment() { private fun updateTransferButton() { if (bmlOtpState != BmlOtpState.NONE) return val amount = binding.etAmount.text?.toString()?.trim()?.toDoubleOrNull() ?: 0.0 - binding.btnTransfer.isEnabled = selectedAccount != null && resolvedAccountNumber.isNotBlank() && amount > 0 + val hasAll = selectedAccount != null && resolvedAccountNumber.isNotBlank() && amount > 0 + if (!hasAll) { binding.btnTransfer.isEnabled = false; return } + val errors = viewModel.connectivityErrors.value ?: emptySet() + val bankOffline = "NO_INTERNET" in errors || + selectedAccount?.bank?.uppercase()?.let { it in errors } == true + binding.btnTransfer.isEnabled = !bankOffline } private fun clearForm() {