From 0642dab358ac7c84d56314277d4664043598dcc5 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Wed, 2 Sep 2026 23:14:33 +0000 Subject: Restore WebView state across Activity recreation in the dashboard widget The web dashboard is a single HTMX page -- tab switches are client-side swaps + history.pushState (?tab=shopping), never a real navigation. The WebView never saved/restored that state, so any Activity recreation (Android reclaiming a backgrounded Activity, a rotation, anything that reruns the AndroidView factory with a fresh WebView) fell back to loadUrl() on the bare server URL in the update block, landing on whatever tab is default. Reported as "shopping randomly jumps back to timeline" -- the prior swipe-detection fix (a17a159) addressed a real but separate false-positive source and didn't touch this path, which isn't tied to touch input at all. WebView.saveState/restoreState is the standard mechanism for exactly this; wired into onSaveInstanceState and the AndroidView factory. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B --- .../org/terst/doot/widget/ui/DashboardActivity.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'android/app') diff --git a/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt b/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt index c7cdfaa..597d06b 100644 --- a/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt +++ b/android/app/src/main/java/org/terst/doot/widget/ui/DashboardActivity.kt @@ -119,6 +119,20 @@ class DashboardActivity : ComponentActivity() { canGoBack = view.canGoBack() } } + // The dashboard's tab switch never does a real navigation -- + // it's HTMX swapping #tab-content client-side and recording + // the tab via history.pushState (?tab=shopping etc). Without + // restoring that here, an Activity recreation (Android + // reclaiming a backgrounded Activity, a rotation, anything + // that reruns this factory with a fresh WebView) had nothing + // to fall back on except the bare server URL in `update` + // below, which always lands on the default tab -- reported as + // "shopping randomly jumps back to timeline," but not actually + // tied to being on shopping specifically, just to whichever + // tab you weren't on by default. No-ops harmlessly if + // savedInstanceState has no WebView state to restore (e.g. the + // very first launch). + savedInstanceState?.let { restoreState(it) } } }, update = { webView -> @@ -144,6 +158,11 @@ class DashboardActivity : ComponentActivity() { } } + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + webViewRef?.saveState(outState) + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_BACK && webViewRef?.canGoBack() == true) { webViewRef?.goBack() -- cgit v1.2.3