X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FMainWebViewActivity.java;h=be28dd88489c516c2d48549f37f7db1b7d07b011;hb=9d621a09cdc72a3ad434084b3aab297f3a7a9d44;hp=becbd5ac8ab5fd55ed65b6305196082fd87518f4;hpb=74655c0cd0ba72c80ac6c48df55bc3d2f5280ad2;p=PrivacyBrowserAndroid.git diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index becbd5ac..be28dd88 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -107,6 +107,8 @@ import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.DialogFragment; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.viewpager.widget.ViewPager; +import androidx.webkit.WebSettingsCompat; +import androidx.webkit.WebViewFeature; import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -3732,10 +3734,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // `reloadWebsite` is used if returning from the Domains activity. Otherwise JavaScript might not function correctly if it is newly enabled. @SuppressLint("SetJavaScriptEnabled") - private boolean applyDomainSettings(NestedScrollWebView nestedScrollWebView, String url, boolean resetTab, boolean reloadWebsite) { - // Store a copy of the current user agent to track changes for the return boolean. - String initialUserAgent = nestedScrollWebView.getSettings().getUserAgentString(); - + private void applyDomainSettings(NestedScrollWebView nestedScrollWebView, String url, boolean resetTab, boolean reloadWebsite) { // Store the current URL. nestedScrollWebView.setCurrentUrl(url); @@ -4050,23 +4049,29 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh); - // Apply swipe to refresh according to the default. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener. - swipeRefreshLayout.setEnabled(defaultSwipeToRefresh); + // Update the swipe refresh layout. + if (defaultSwipeToRefresh) { // Swipe to refresh is enabled. + // Only enable the swipe refresh layout if the WebView is scrolled to the top. It is updated every time the scroll changes. + swipeRefreshLayout.setEnabled(currentWebView.getY() == 0); + } else { // Swipe to refresh is disabled. + // Disable the swipe refresh layout. + swipeRefreshLayout.setEnabled(false); + } break; case DomainsDatabaseHelper.ENABLED: // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(true); - // Enable swipe to refresh. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener. - swipeRefreshLayout.setEnabled(true); + // Only enable the swipe refresh layout if the WebView is scrolled to the top. It is updated every time the scroll changes. + swipeRefreshLayout.setEnabled(currentWebView.getY() == 0); break; case DomainsDatabaseHelper.DISABLED: // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(false); - // Disable swipe to refresh. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener. + // Disable swipe to refresh. swipeRefreshLayout.setEnabled(false); } @@ -4154,8 +4159,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh); - // Apply swipe to refresh according to the default. - swipeRefreshLayout.setEnabled(defaultSwipeToRefresh); + // Update the swipe refresh layout. + if (defaultSwipeToRefresh) { // Swipe to refresh is enabled. + // Only enable the swipe refresh layout if the WebView is scrolled to the top. It is updated every time the scroll changes. + swipeRefreshLayout.setEnabled(currentWebView.getY() == 0); + } else { // Swipe to refresh is disabled. + // Disable the swipe refresh layout. + swipeRefreshLayout.setEnabled(false); + } // Reset the pinned variables. nestedScrollWebView.setDomainSettingsDatabaseId(-1); @@ -4211,9 +4222,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook if (reloadWebsite) { nestedScrollWebView.reload(); } - - // Return the user agent changed status. - return !nestedScrollWebView.getSettings().getUserAgentString().equals(initialUserAgent); } private void applyProxy(boolean reloadWebViews) { @@ -5176,26 +5184,60 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook }); // Update the status of swipe to refresh based on the scroll position of the nested scroll WebView. Also reinforce full screen browsing mode. - // Once the minimum API >= 23 this can be replaced with `nestedScrollWebView.setOnScrollChangeListener()`. - nestedScrollWebView.getViewTreeObserver().addOnScrollChangedListener(() -> { - if (nestedScrollWebView.getSwipeToRefresh()) { - // Only enable swipe to refresh if the WebView is scrolled to the top. - swipeRefreshLayout.setEnabled(nestedScrollWebView.getScrollY() == 0); - } + // On API < 23, `getViewTreeObserver().addOnScrollChangedListener()` must be used, but it is a little bit buggy and appears to get garbage collected from time to time. + if (Build.VERSION.SDK_INT >= 23) { + nestedScrollWebView.setOnScrollChangeListener((view, i, i1, i2, i3) -> { + if (nestedScrollWebView.getSwipeToRefresh()) { + // Only enable swipe to refresh if the WebView is scrolled to the top. + swipeRefreshLayout.setEnabled(nestedScrollWebView.getScrollY() == 0); + } else { + // Disable swipe to refresh. + swipeRefreshLayout.setEnabled(false); + } + + // Reinforce the system UI visibility flags if in full screen browsing mode. + // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. + if (inFullScreenBrowsingMode) { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } + }); + } else { + nestedScrollWebView.getViewTreeObserver().addOnScrollChangedListener(() -> { + if (nestedScrollWebView.getSwipeToRefresh()) { + // Only enable swipe to refresh if the WebView is scrolled to the top. + swipeRefreshLayout.setEnabled(nestedScrollWebView.getScrollY() == 0); + } else { + // Disable swipe to refresh. + swipeRefreshLayout.setEnabled(false); + } - // Reinforce the system UI visibility flags if in full screen browsing mode. - // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. - if (inFullScreenBrowsingMode) { - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ - rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } - }); + + // Reinforce the system UI visibility flags if in full screen browsing mode. + // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. + if (inFullScreenBrowsingMode) { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } + }); + } + + // TODO. + if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) { + WebSettingsCompat.setForceDark(nestedScrollWebView.getSettings(), WebSettingsCompat.FORCE_DARK_AUTO); + } // Set the web chrome client. nestedScrollWebView.setWebChromeClient(new WebChromeClient() { @@ -5450,28 +5492,24 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook }); nestedScrollWebView.setWebViewClient(new WebViewClient() { - // `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps. + // `shouldOverrideUrlLoading` makes this WebView the default handler for URLs inside the app, so that links are not kicked out to other apps. // The deprecated `shouldOverrideUrlLoading` must be used until API >= 24. @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // Sanitize the url. url = sanitizeUrl(url); + // Handle the URL according to the type. if (url.startsWith("http")) { // Load the URL in Privacy Browser. // Apply the domain settings for the new URL. This doesn't do anything if the domain has not changed. - boolean userAgentChanged = applyDomainSettings(nestedScrollWebView, url, true, false); + applyDomainSettings(nestedScrollWebView, url, true, false); - // Check if the user agent has changed. - if (userAgentChanged) { - // Manually load the URL. The changing of the user agent will cause WebView to reload the previous URL. - nestedScrollWebView.loadUrl(url, customHeaders); + // Manually load the URL. The changing of the user agent will cause WebView to reload the previous URL. + nestedScrollWebView.loadUrl(url, customHeaders); - // Returning true indicates that Privacy Browser is manually handling the loading of the URL. - return true; - } else { - // Returning false causes the current WebView to handle the URL and prevents it from adding redirects to the history list. - return false; - } + // Returning true indicates that Privacy Browser is manually handling the loading of the URL. + // Custom headers cannot be added if false is returned and the WebView handles the loading of the URL. + return true; } else if (url.startsWith("mailto:")) { // Load the email address in an external email program. // Use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched. Intent emailIntent = new Intent(Intent.ACTION_SENDTO);