From 296d23a0088ee99b58af6c3cd3e8019da1b3589e Mon Sep 17 00:00:00 2001 From: 4aiman Date: Thu, 27 Aug 2026 23:12:34 +0300 Subject: [PATCH] Android: fix OS back gesture for SPA modals/screens (drive JS history.back) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WryActivity's generated back handler calls WebView.goBack(), which does NOT dispatch popstate for same-document history.pushState() entries — so the OS back gesture never reached the app's popstate handler and couldn't dismiss modals (new product, add-to-eaten, ЧЗ scanner) or navigate screens; only the on-screen back arrow worked. WryActivity.kt is auto-regenerated each build, so override in the app-owned MainActivity instead: set handleBackNavigation=false and register our own OnBackPressedCallback that runs window.history.back() via evaluateJavascript, which fires popstate. Verified on-device: swipe-back now closes modals and the ЧЗ scanner. (adb `input keyevent BACK` does NOT go through OnBackPressedDispatcher on Android 13+, so it can't be used to test this — only the real gesture does.) --- .../main/java/dev/baldav/app/MainActivity.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src-tauri/gen/android/app/src/main/java/dev/baldav/app/MainActivity.kt b/src-tauri/gen/android/app/src/main/java/dev/baldav/app/MainActivity.kt index dd117dd..fb0a005 100644 --- a/src-tauri/gen/android/app/src/main/java/dev/baldav/app/MainActivity.kt +++ b/src-tauri/gen/android/app/src/main/java/dev/baldav/app/MainActivity.kt @@ -11,6 +11,8 @@ import android.provider.Settings import android.os.Bundle import android.os.FileObserver import android.util.Log +import android.webkit.WebView +import androidx.activity.OnBackPressedCallback import androidx.activity.enableEdgeToEdge import androidx.activity.result.contract.ActivityResultContracts import androidx.core.view.ViewCompat @@ -22,6 +24,33 @@ import javax.net.ssl.HttpsURLConnection class MainActivity : TauriActivity() { private var commandObserver: FileObserver? = null private var pendingSaveContent: String? = null + private var backWebView: WebView? = null + + // Disable WryActivity's generated back handler: its mWebView.goBack() does NOT + // dispatch a popstate for same-document history.pushState() entries (our SPA + // nav/modals), so the OS back gesture never reached the JS handler — modals + // and screens couldn't be dismissed with a swipe. We register our own callback + // (below) that drives window.history.back() via JS, which fires popstate. + override val handleBackNavigation: Boolean = false + + override fun onWebViewCreate(webView: WebView) { + super.onWebViewCreate(webView) + backWebView = webView + onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + val wv = backWebView + if (wv != null) { + // Drive JS history.back() — it fires popstate (closes modals / navigates + // screens). WebView.goBack() would not, for same-document pushState entries. + wv.evaluateJavascript("window.history.back()", null) + } else { + isEnabled = false + onBackPressed() + isEnabled = true + } + } + }) + } private val saveFileLauncher = registerForActivityResult( ActivityResultContracts.CreateDocument("application/gpx+xml")