From 3e8ea907014dd87bf159fdcaa77c09ae43d14f07 Mon Sep 17 00:00:00 2001 From: Shihaam Abdul Rahman Date: Wed, 27 May 2026 22:14:31 +0500 Subject: [PATCH] handle server timeouts instead of crashing --- .../sar/basedbank/api/bml/BmlHistoryClient.kt | 3 +++ .../api/fahipay/FahipayHistoryClient.kt | 3 +++ .../sar/basedbank/api/mib/MibHistoryClient.kt | 2 ++ .../ui/home/AccountHistoryFragment.kt | 19 ++++++++++++++++++- .../sh/sar/basedbank/ui/home/HomeActivity.kt | 2 +- 5 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/sh/sar/basedbank/api/bml/BmlHistoryClient.kt b/app/src/main/java/sh/sar/basedbank/api/bml/BmlHistoryClient.kt index c5a465d..b33e747 100644 --- a/app/src/main/java/sh/sar/basedbank/api/bml/BmlHistoryClient.kt +++ b/app/src/main/java/sh/sar/basedbank/api/bml/BmlHistoryClient.kt @@ -4,6 +4,7 @@ import okhttp3.MediaType.Companion.toMediaType import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import org.json.JSONObject +import sh.sar.basedbank.api.models.BankServerException import sh.sar.basedbank.api.models.BankTransaction import java.text.SimpleDateFormat import java.util.Locale @@ -30,6 +31,7 @@ class BmlHistoryClient { val json = resp.body?.string() ?: return Pair(emptyList(), 0) resp.close() if (code == 401 || code == 419) throw AuthExpiredException() + if (code in 500..599) throw BankServerException("BML") return try { val root = JSONObject(json) if (!root.optBoolean("success")) return Pair(emptyList(), 0) @@ -82,6 +84,7 @@ class BmlHistoryClient { val json = resp.body?.string() ?: return emptyList() resp.close() if (code == 401 || code == 419) throw AuthExpiredException() + if (code in 500..599) throw BankServerException("BML") return try { val root = JSONObject(json) if (!root.optBoolean("success")) return emptyList() diff --git a/app/src/main/java/sh/sar/basedbank/api/fahipay/FahipayHistoryClient.kt b/app/src/main/java/sh/sar/basedbank/api/fahipay/FahipayHistoryClient.kt index 63c1b74..636009b 100644 --- a/app/src/main/java/sh/sar/basedbank/api/fahipay/FahipayHistoryClient.kt +++ b/app/src/main/java/sh/sar/basedbank/api/fahipay/FahipayHistoryClient.kt @@ -3,6 +3,7 @@ package sh.sar.basedbank.api.fahipay import okhttp3.OkHttpClient import okhttp3.Request import org.json.JSONObject +import sh.sar.basedbank.api.models.BankServerException import sh.sar.basedbank.api.models.BankTransaction import java.util.concurrent.TimeUnit @@ -32,8 +33,10 @@ class FahipayHistoryClient { .header("User-Agent", UA) .build() ).execute() + val code = resp.code val json = resp.body?.string() ?: return Pair(emptyList(), 0) resp.close() + if (code in 500..599) throw BankServerException("Fahipay") return try { val obj = JSONObject(json) val total = obj.optInt("total", 0) diff --git a/app/src/main/java/sh/sar/basedbank/api/mib/MibHistoryClient.kt b/app/src/main/java/sh/sar/basedbank/api/mib/MibHistoryClient.kt index 62bec83..12843e2 100644 --- a/app/src/main/java/sh/sar/basedbank/api/mib/MibHistoryClient.kt +++ b/app/src/main/java/sh/sar/basedbank/api/mib/MibHistoryClient.kt @@ -5,6 +5,7 @@ import okhttp3.FormBody import okhttp3.OkHttpClient import okhttp3.Request import org.json.JSONObject +import sh.sar.basedbank.api.models.BankServerException import java.util.concurrent.TimeUnit class MibHistoryClient { @@ -60,6 +61,7 @@ class MibHistoryClient { .build() return client.newCall(request).execute().use { response -> + if (response.code in 500..599) throw BankServerException("MIB") val bodyStr = response.body?.string() ?: return Pair(emptyList(), 0) val json = try { JSONObject(bodyStr) } catch (_: Exception) { return Pair(emptyList(), 0) } if (!json.optBoolean("success")) return Pair(emptyList(), 0) diff --git a/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt b/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt index 2f48560..3b841bc 100644 --- a/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt +++ b/app/src/main/java/sh/sar/basedbank/ui/home/AccountHistoryFragment.kt @@ -23,6 +23,7 @@ import kotlinx.coroutines.withContext import sh.sar.basedbank.BasedBankApp import sh.sar.basedbank.R import sh.sar.basedbank.api.models.BankAccount +import sh.sar.basedbank.api.models.BankServerException import sh.sar.basedbank.api.mib.MibContactsClient import sh.sar.basedbank.api.models.BankTransaction import sh.sar.basedbank.api.mib.TransactionCache @@ -165,7 +166,17 @@ class AccountHistoryFragment : Fragment() { val app = requireActivity().application as BasedBankApp lifecycleScope.launch { - val transactions = fetcher.fetchNextPage(app, pageSize) + val transactions = try { + fetcher.fetchNextPage(app, pageSize) + } catch (e: java.io.IOException) { + (activity as? HomeActivity)?.showConnectivityBanner(getString(R.string.connectivity_no_internet)) + null + } catch (e: BankServerException) { + (activity as? HomeActivity)?.showConnectivityBanner(getString(R.string.connectivity_server_error, e.bankName)) + null + } catch (_: Exception) { + null + } isLoading = false @@ -175,6 +186,12 @@ class AccountHistoryFragment : Fragment() { binding.swipeRefresh.isRefreshing = false } + if (transactions == null) { + adapter.showLoadingFooter = false + if (allTransactions.isEmpty()) binding.emptyView.visibility = View.VISIBLE + return@launch + } + if (transactions.isNotEmpty()) { val existingIds = allTransactions.map { it.id }.toHashSet() val newOnes = transactions.filter { it.id !in existingIds } 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 39b22c8..538c590 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 @@ -549,7 +549,7 @@ fun applyNavLabelVisibility() { autoRefresh(store) } - private fun showConnectivityBanner(message: String) { + fun showConnectivityBanner(message: String) { binding.connectivityBanner.text = message binding.connectivityBanner.visibility = View.VISIBLE }