From 68967fa0ce446e587db8dc6f23bb6a6c3b0cda95 Mon Sep 17 00:00:00 2001 From: lukstbit <52494258+lukstbit@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:40:44 +0200 Subject: [PATCH 1/3] Implement predictive back navigation for Info The added back callback is enabled/disabled based on webview status( can go back or not) to let the system know if it should handle the back navigation request. The callback is disabled at start, the WebView it's expected to not have any history yet. See: https://codelabs.developers.google.com/handling-gesture-back-navigation#5 where this exact scenario is handled. --- .../src/main/java/com/ichi2/anki/Info.kt | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Info.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Info.kt index 5e707e6e4ac1..6b663be37109 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Info.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Info.kt @@ -27,6 +27,7 @@ import android.webkit.WebChromeClient import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient +import androidx.activity.OnBackPressedCallback import androidx.appcompat.widget.ThemeUtils import com.google.android.material.button.MaterialButton import com.ichi2.anim.ActivityTransitionAnimation @@ -46,7 +47,7 @@ private const val CHANGE_LOG_URL = "https://docs.ankidroid.org/changelog.html" * Shows an about box, which is a small HTML page. */ class Info : AnkiActivity() { - private var mWebView: WebView? = null + private lateinit var mWebView: WebView @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { @@ -67,7 +68,7 @@ class Info : AnkiActivity() { findViewById(R.id.info_donate).setOnClickListener { openUrl(Uri.parse(getString(R.string.link_opencollective_donate))) } title = "$appName v$pkgVersionName" mWebView = findViewById(R.id.info) - mWebView!!.webChromeClient = object : WebChromeClient() { + mWebView.webChromeClient = object : WebChromeClient() { override fun onProgressChanged(view: WebView, progress: Int) { // Hide the progress indicator when the page has finished loaded if (progress == 100) { @@ -88,7 +89,11 @@ class Info : AnkiActivity() { visibility = View.GONE } } - + val onBackPressedCallback = object : OnBackPressedCallback(false) { + override fun handleOnBackPressed() { + if (mWebView.canGoBack()) mWebView.goBack() + } + } // Apply Theme colors val typedArray = theme.obtainStyledAttributes(intArrayOf(android.R.attr.colorBackground, android.R.attr.textColor)) val backgroundColor = typedArray.getColor(0, -1) @@ -97,9 +102,9 @@ class Info : AnkiActivity() { val anchorTextThemeColor = ThemeUtils.getThemeAttrColor(this, android.R.attr.colorAccent) val anchorTextColor = anchorTextThemeColor.toRGBHex() - mWebView!!.setBackgroundColor(backgroundColor) - mWebView!!.settings.allowFileAccess = true - mWebView!!.settings.allowContentAccess = true + mWebView.setBackgroundColor(backgroundColor) + mWebView.settings.allowFileAccess = true + mWebView.settings.allowContentAccess = true setRenderWorkaround(this) when (type) { TYPE_NEW_VERSION -> { @@ -108,14 +113,14 @@ class Info : AnkiActivity() { setOnClickListener { close() } } val background = backgroundColor.toRGBHex() - mWebView!!.loadUrl("/android_asset/changelog.html") - mWebView!!.settings.javaScriptEnabled = true - mWebView!!.webViewClient = object : WebViewClient() { + mWebView.loadUrl("/android_asset/changelog.html") + mWebView.settings.javaScriptEnabled = true + mWebView.webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView, url: String) { /* The order of below javascript code must not change (this order works both in debug and release mode) * or else it will break in any one mode. */ - mWebView!!.loadUrl( + mWebView.loadUrl( "javascript:document.body.style.setProperty(\"color\", \"" + textColor + "\");" + "x=document.getElementsByTagName(\"a\"); for(i=0;i finish() } + onBackPressedDispatcher.addCallback(this, onBackPressedCallback) } private fun close() { @@ -170,15 +185,6 @@ class Info : AnkiActivity() { finishWithAnimation(ActivityTransitionAnimation.Direction.START) } - @Suppress("deprecation") // onBackPressed - override fun onBackPressed() { - if (mWebView!!.canGoBack()) { - mWebView!!.goBack() - } else { - super.onBackPressed() - } - } - companion object { const val TYPE_EXTRA = "infoType" const val TYPE_NEW_VERSION = 2 From 0f488d574ca15221f3e8061547143636859d7af0 Mon Sep 17 00:00:00 2001 From: lukstbit <52494258+lukstbit@users.noreply.github.com> Date: Fri, 3 Nov 2023 19:26:25 +0200 Subject: [PATCH 2/3] Implement predictive back navigation for Previewer The previous code was setting the result on back pressed passing the values of two class properties, the modified code sets an initial result + updates the returned Intent every time one of the observed properties is changed. --- .../src/main/java/com/ichi2/anki/Previewer.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/Previewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/Previewer.kt index d90c6124dbed..e41db66afa36 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/Previewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/Previewer.kt @@ -75,6 +75,7 @@ class Previewer : AbstractFlashcardViewer() { disableDrawerSwipe() startLoadingCollection() initPreviewProgress() + setOkResult() } private fun initPreviewProgress() { @@ -161,13 +162,8 @@ class Previewer : AbstractFlashcardViewer() { return super.onOptionsItemSelected(item) } - override fun onBackPressed() { - setResult(RESULT_OK, resultIntent) - super.onBackPressed() - } - override fun onNavigationPressed() { - setResult(RESULT_OK, resultIntent) + setOkResult() super.onNavigationPressed() } @@ -214,6 +210,7 @@ class Previewer : AbstractFlashcardViewer() { override fun performReload() { mReloadRequired = true + setOkResult() val newCardList = getColUnsafe.filterToValidCards(mCardList) if (newCardList.isEmpty()) { finish() @@ -228,6 +225,7 @@ class Previewer : AbstractFlashcardViewer() { override fun onEditedNoteChanged() { super.onEditedNoteChanged() mNoteChanged = true + setOkResult() } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @@ -267,13 +265,15 @@ class Previewer : AbstractFlashcardViewer() { mProgressText.text = progress } - private val resultIntent: Intent - get() { - val intent = Intent() - intent.putExtra("reloadRequired", mReloadRequired) - intent.putExtra("noteChanged", mNoteChanged) - return intent - } + private fun setOkResult() { + setResult( + RESULT_OK, + Intent().apply { + putExtra("reloadRequired", mReloadRequired) + putExtra("noteChanged", mNoteChanged) + } + ) + } companion object { @CheckResult From ff873ea6b92d06ab036f921f8d2c80eeb1ed06c3 Mon Sep 17 00:00:00 2001 From: lukstbit <52494258+lukstbit@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:52:08 +0200 Subject: [PATCH 3/3] Implement predictive back navigation in ModelFieldEditor Simply deleted the onBackPressed() callback as all it did was to close the activity. Without a back callbak set, the system will handle the back navigation itself. The toolbar home button was already handled in the superclass AnkiActivity. --- .../src/main/java/com/ichi2/anki/ModelFieldEditor.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt index ed14f24ed746..792291bfe0c4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt @@ -454,10 +454,6 @@ class ModelFieldEditor : AnkiActivity(), LocaleSelectionDialogHandler { } override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { - android.R.id.home -> { - onBackPressed() - true - } R.id.action_add_new_model -> { addFieldDialog() true @@ -469,12 +465,6 @@ class ModelFieldEditor : AnkiActivity(), LocaleSelectionDialogHandler { finishWithAnimation(ActivityTransitionAnimation.Direction.END) } - @Suppress("DEPRECATION", "Deprecated in API34+dependencies for predictive back feature") - override fun onBackPressed() { - super.onBackPressed() - closeActivity() - } - fun handleAction(contextMenuAction: ModelEditorContextMenuAction) { when (contextMenuAction) { ModelEditorContextMenuAction.Sort -> sortByField()