v1.8: fix black screen on resume and crash on sync

- onResume() no longer triggers a refresh every time — only fetches when
  data is >5 min stale, so returning to app shows cached data instantly
  without a loading spinner
- Fix CancellationException being swallowed by catch(Exception) in
  refreshUsage(), which caused updates to run on a destroyed activity
- EncryptedSharedPreferences key invalidation (caused by enabling/changing
  biometrics or screen lock) now deletes the stale encrypted file and
  recreates it cleanly, rather than silently using empty fallback prefs
- Wrap all securePrefs read/write ops in try-catch so a mid-session
  Keystore failure degrades gracefully instead of crashing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-22 20:59:10 +00:00
parent 3dc0448942
commit 695c54f03c
3 changed files with 45 additions and 18 deletions
@@ -68,7 +68,10 @@ class MainActivity : AppCompatActivity() {
val cached = prefs.getUsageData()
updateUI(cached)
if (prefs.isLoggedIn()) {
refreshUsage()
val staleMs = 5 * 60 * 1000L
if ((cached?.lastUpdated ?: 0L) < System.currentTimeMillis() - staleMs) {
refreshUsage()
}
}
}
@@ -79,6 +82,7 @@ class MainActivity : AppCompatActivity() {
val data = try {
repo.fetchUsage()
} catch (e: Exception) {
if (e is kotlinx.coroutines.CancellationException) throw e
prefs.getUsageData()?.copy(errorMessage = "Network error")
?: UsageData(errorMessage = "Network error")
}