From 60e583d7aa5272bc0293797af77e6167f18887b3 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Wed, 6 Mar 2024 11:25:34 -0700 Subject: [PATCH] Unify the code path for navigating history. https://redmine.stoutner.com/issues/1165 --- .../activities/MainWebViewActivity.kt | 182 ++++++------------ .../dialogs/UrlHistoryDialog.kt | 19 +- .../views/NestedScrollWebView.kt | 17 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 5 files changed, 75 insertions(+), 149 deletions(-) diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt index 204023e3..b6086b46 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt @@ -250,6 +250,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Declare the public static variables. lateinit var appBarLayout: AppBarLayout + lateinit var defaultFavoriteIconBitmap : Bitmap } // Declare the class variables. @@ -656,6 +657,15 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Update the bookmarks drawer pinned image view. updateBookmarksDrawerPinnedImageView() + // Get the default favorite icon drawable. + val favoriteIconDrawable = AppCompatResources.getDrawable(this, R.drawable.world) + + // Cast the favorite icon drawable to a bitmap drawable. + val favoriteIconBitmapDrawable = (favoriteIconDrawable as BitmapDrawable?)!! + + // Store the default favorite icon bitmap. + defaultFavoriteIconBitmap = favoriteIconBitmapDrawable.bitmap + // Initialize the app. initializeApp() @@ -677,34 +687,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook exitFullScreenVideo() // It shouldn't be possible for the currentWebView to be null, but crash logs indicate it sometimes happens. } else if (currentWebView != null && currentWebView!!.canGoBack()) { // There is at least one item in the current WebView history. - // Get the current web back forward list. - val webBackForwardList = currentWebView!!.copyBackForwardList() - - // Get the previous entry data. - val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url - val previousFavoriteIcon = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).favicon - - // Apply the domain settings. - applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false) - - // Get the current tab. - val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!! - - // Get the custom view from the tab. - val tabView = tab.customView!! - - // Get the favorite icon image view from the tab. - val tabFavoriteIconImageView = tabView.findViewById(R.id.favorite_icon_imageview) - - // Set the previous favorite icon if it isn't null. - if (previousFavoriteIcon != null) - tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(previousFavoriteIcon, 64, 64, true)) - - // Go back. - currentWebView!!.goBack() - - // Update the URL edit text after a delay. - updateUrlEditTextAfterDelay() + // Navigate back one page. + navigateHistory(-1) } else { // Close the current tab. // A view is required because the method is also called by an XML `onClick`. closeTab(null) @@ -2237,66 +2221,16 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook R.id.back -> { // Back. // Check if the WebView can go back. if (currentWebView!!.canGoBack()) { - // Get the current web back forward list. - val webBackForwardList = currentWebView!!.copyBackForwardList() - - // Get the previous entry data. - val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url - val previousFavoriteIcon = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).favicon!! - - // Apply the domain settings. - applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false) - - // Get the current tab. - val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!! - - // Get the custom view from the tab. - val tabView = tab.customView!! - - // Get the favorite icon image view from the tab. - val tabFavoriteIconImageView = tabView.findViewById(R.id.favorite_icon_imageview) - - // Set the previous favorite icon. - tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(previousFavoriteIcon, 64, 64, true)) - - // Load the previous website in the history. - currentWebView!!.goBack() - - // Update the URL edit text after a delay. - updateUrlEditTextAfterDelay() + // Navigate back one page. + navigateHistory(-1) } } R.id.forward -> { // Forward. // Check if the WebView can go forward. if (currentWebView!!.canGoForward()) { - // Get the current web back forward list. - val webBackForwardList = currentWebView!!.copyBackForwardList() - - // Get the next entry data. - val nextUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex + 1).url - val nextFavoriteIcon = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex + 1).favicon!! - - // Apply the domain settings. - applyDomainSettings(currentWebView!!, nextUrl, resetTab = false, reloadWebsite = false, loadUrl = false) - - // Get the current tab. - val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!! - - // Get the custom view from the tab. - val tabView = tab.customView!! - - // Get the favorite icon image view from the tab. - val tabFavoriteIconImageView = tabView.findViewById(R.id.favorite_icon_imageview) - - // Set the next favorite icon. - tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nextFavoriteIcon, 64, 64, true)) - - // Load the next website in the history. - currentWebView!!.goForward() - - // Update the URL edit text after a delay. - updateUrlEditTextAfterDelay() + // Navigate forward one page. + navigateHistory(+1) } } @@ -3171,10 +3105,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook nestedScrollWebView.clearPinnedSslCertificate() nestedScrollWebView.pinnedIpAddresses = "" - // Reset the favorite icon if specified. + // Reset the tab if specified. if (resetTab) { // Initialize the favorite icon. - nestedScrollWebView.initializeFavoriteIcon() + nestedScrollWebView.resetFavoriteIcon() // Get the current page position. val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId) @@ -5942,15 +5876,53 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook loadUrl(currentWebView!!, urlString) } - override fun navigateHistory(url: String, steps: Int) { + override fun navigateHistory(steps: Int) { + // Get the current web back forward list. + val webBackForwardList = currentWebView!!.copyBackForwardList() + + // Calculate the target index. + val targetIndex = webBackForwardList.currentIndex + steps + + // Get the previous entry data. + val previousUrl = webBackForwardList.getItemAtIndex(targetIndex).url + val previousFavoriteIcon = webBackForwardList.getItemAtIndex(targetIndex).favicon + // Apply the domain settings. - applyDomainSettings(currentWebView!!, url, resetTab = false, reloadWebsite = false, loadUrl = false) + applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false) + + // Get the current tab. + val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!! + + // Get the custom view from the tab. + val tabView = tab.customView!! + + // Get the favorite icon image view from the tab. + val tabFavoriteIconImageView = tabView.findViewById(R.id.favorite_icon_imageview) + + // Set the previous favorite icon. + if (previousFavoriteIcon == null) + tabFavoriteIconImageView.setImageBitmap(defaultFavoriteIconBitmap) + else + tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(previousFavoriteIcon, 64, 64, true)) // Load the history entry. currentWebView!!.goBackOrForward(steps) - // Update the URL edit text after a delay. - updateUrlEditTextAfterDelay() + // Create a handler to update the URL edit box. + val urlEditTextUpdateHandler = Handler(Looper.getMainLooper()) + + // Create a runnable to update the URL edit box. + val urlEditTextUpdateRunnable = Runnable { + // Update the URL edit text. + urlEditText.setText(currentWebView!!.url) + + // Disable the wide viewport if the source is being viewed. + if (currentWebView!!.url!!.startsWith("view-source:")) + currentWebView!!.settings.useWideViewPort = false + } + + // Update the URL edit text after 50 milliseconds, so that the WebView has enough time to navigate to the new URL. + urlEditTextUpdateHandler.postDelayed(urlEditTextUpdateRunnable, 50) } override fun openFile(dialogFragment: DialogFragment) { @@ -6055,20 +6027,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } override fun pinnedErrorGoBack() { - // Get the current web back forward list. - val webBackForwardList = currentWebView!!.copyBackForwardList() - - // Get the previous entry URL. - val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url - - // Apply the domain settings. - applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false) - - // Go back. - currentWebView!!.goBack() - - // Update the URL edit text after a delay. - updateUrlEditTextAfterDelay() + // Navigate back one page. + navigateHistory(-1) } private fun sanitizeUrl(urlString: String): String { @@ -6356,22 +6316,4 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook invalidateOptionsMenu() } } - - fun updateUrlEditTextAfterDelay() { - // Create a handler to update the URL edit box. - val urlEditTextUpdateHandler = Handler(Looper.getMainLooper()) - - // Create a runnable to update the URL edit box. - val urlEditTextUpdateRunnable = Runnable { - // Update the URL edit text. - urlEditText.setText(currentWebView!!.url) - - // Disable the wide viewport if the source is being viewed. - if (currentWebView!!.url!!.startsWith("view-source:")) - currentWebView!!.settings.useWideViewPort = false - } - - // Update the URL edit text after 50 milliseconds, so that the WebView has enough time to navigate to the new URL. - urlEditTextUpdateHandler.postDelayed(urlEditTextUpdateRunnable, 50) - } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/UrlHistoryDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/UrlHistoryDialog.kt index 008abef7..eedd6447 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/UrlHistoryDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/UrlHistoryDialog.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Soren Stoutner . + * Copyright 2016-2024 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -29,7 +29,6 @@ import android.view.WindowManager import android.widget.AdapterView import android.widget.AdapterView.OnItemClickListener import android.widget.ListView -import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat @@ -43,7 +42,7 @@ import com.stoutner.privacybrowser.dataclasses.HistoryDataClass import com.stoutner.privacybrowser.views.NestedScrollWebView // Define the class constants. -private const val WEBVIEW_FRAGMENT_ID = "webview_fragment_id" +private const val WEBVIEW_FRAGMENT_ID = "A" class UrlHistoryDialog : DialogFragment() { companion object { @@ -70,7 +69,7 @@ class UrlHistoryDialog : DialogFragment() { // The public interface is used to send information back to the parent activity. interface NavigateHistoryListener { - fun navigateHistory(url: String, steps: Int) + fun navigateHistory(steps: Int) } override fun onAttach(context: Context) { @@ -181,20 +180,14 @@ class UrlHistoryDialog : DialogFragment() { listView.adapter = historyArrayAdapter // Listen for clicks on entries in the list view. - listView.onItemClickListener = OnItemClickListener { _: AdapterView<*>?, view: View, _: Int, id: Long -> + listView.onItemClickListener = OnItemClickListener { _: AdapterView<*>?, _: View, _: Int, id: Long -> // Convert the long ID to an int. val itemId = id.toInt() // Only consume the click if it is not on the current page ID. if (itemId != currentPageId) { - // Get a handle for the URL text view. - val urlTextView = view.findViewById(R.id.history_url_textview) - - // Get the URL. - val url = urlTextView.text.toString() - - // Invoke the navigate history listener in the calling activity. These commands cannot be run here because they need access to `applyDomainSettings()`. - navigateHistoryListener.navigateHistory(url, currentPageId - itemId) + // Invoke the navigate history listener in the calling activity. Those commands cannot be run here because they need access to `applyDomainSettings()`. + navigateHistoryListener.navigateHistory(currentPageId - itemId) // Dismiss the alert dialog. alertDialog.dismiss() diff --git a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt index fa32cf0c..45133be5 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 Soren Stoutner . + * Copyright 2019-2024 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -23,7 +23,6 @@ import android.animation.ObjectAnimator import android.annotation.SuppressLint import android.content.Context import android.graphics.Bitmap -import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.os.Bundle import android.util.AttributeSet @@ -32,12 +31,10 @@ import android.webkit.HttpAuthHandler import android.webkit.SslErrorHandler import android.webkit.WebView -import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.core.view.NestedScrollingChild2 import androidx.core.view.NestedScrollingChildHelper import androidx.core.view.ViewCompat -import com.stoutner.privacybrowser.R import com.stoutner.privacybrowser.activities.MainWebViewActivity import java.util.Collections @@ -143,19 +140,13 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS nestedScrollingChildHelper.isNestedScrollingEnabled = true // Initialize the favorite icon. - initializeFavoriteIcon() + resetFavoriteIcon() } // Favorite or default icon. - fun initializeFavoriteIcon() { - // Get the default favorite icon drawable. - val favoriteIconDrawable = getDrawable(context, R.drawable.world) - - // Cast the favorite icon drawable to a bitmap drawable. - val favoriteIconBitmapDrawable = (favoriteIconDrawable as BitmapDrawable?)!! - + fun resetFavoriteIcon() { // Store the default icon bitmap. - favoriteIcon = favoriteIconBitmapDrawable.bitmap + favoriteIcon = MainWebViewActivity.defaultFavoriteIconBitmap // Set the favorite icon height to be 0. This way any favorite icons presented by the website will overwrite it. favoriteIconHeight = 0 diff --git a/build.gradle b/build.gradle index c65a4ca3..9ab25062 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.2.2' + classpath 'com.android.tools.build:gradle:8.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fe335734..b49cb335 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -# Copyright 2019-2023 Soren Stoutner . +# Copyright 2019-2024 Soren Stoutner . # # This file is part of Privacy Browser Android . # @@ -20,4 +20,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip -- 2.45.2