]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java
Add `Copy URL` to the URL context menus.
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebView.java
index c7e987c116337b57012646976f690e2f43266160..8e06fc8bab2cd24787a7209ccf912c916e7da5e8 100644 (file)
@@ -22,6 +22,8 @@ package com.stoutner.privacybrowser.activities;
 import android.annotation.SuppressLint;
 import android.app.DialogFragment;
 import android.app.DownloadManager;
+import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -128,6 +130,12 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     // 'mainWebView' is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`, `findNextOnPage()`, `closeFindOnPage()`, and `loadUrlFromTextBox()`.
     private WebView mainWebView;
 
+    // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
+    private EditText findOnPageEditText;
+
+    // `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`.
+    private FrameLayout fullScreenVideoFrameLayout;
+
     // `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu`, and `onRestart()`.
     private SwipeRefreshLayout swipeRefreshLayout;
 
@@ -186,9 +194,6 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     // `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
     private SslErrorHandler sslErrorHandler;
 
-    // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
-    private EditText findOnPageEditText;
-
     // `inputMethodManager` is used in `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `closeFindOnPage()`.
     private InputMethodManager inputMethodManager;
 
@@ -241,7 +246,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout);
         mainWebView = (WebView) findViewById(R.id.mainWebView);
         findOnPageEditText = (EditText) findViewById(R.id.find_on_page_edittext);
-        final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout);
+        fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout);
 
         // Create a double-tap listener to toggle full-screen mode.
         final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@@ -277,7 +282,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                         // Set `rootCoordinatorLayout` to fit under the status and navigation bars.
                         rootCoordinatorLayout.setFitsSystemWindows(false);
 
-                        if (translucentNavigationBarOnFullscreen) {  // There is an Android Support Library bug that causes an ugly scrim to print on the `Drawer Layout` when the navigation bar is displayed on the right of the screen.
+                        if (translucentNavigationBarOnFullscreen) {  // There is an Android Support Library bug that causes a scrim to print on the right side of the `Drawer Layout` when the navigation bar is displayed on the right of the screen.
                             // Set the navigation bar to be translucent.
                             getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                         }
@@ -428,7 +433,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         });
 
         // drawerToggle creates the hamburger icon at the start of the AppBar.
-        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation, R.string.close_navigation);
+        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation_drawer, R.string.close_navigation_drawer);
 
         mainWebView.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.
@@ -436,7 +441,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             @SuppressWarnings("deprecation")
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
-                // Use an external email program if the link begins with "mailto:".
+                // Use an external email program if the link begins with `mailto:`.
                 if (url.startsWith("mailto:")) {
                     // We use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
                     Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
@@ -522,42 +527,51 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             // Enter full screen video
             @Override
             public void onShowCustomView(View view, CustomViewCallback callback) {
-                appBar.hide();
-
-                // Show the fullScreenVideoFrameLayout.
-                fullScreenVideoFrameLayout.addView(view);
-                fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
-
-                // Hide the mainWebView.
-                mainWebView.setVisibility(View.GONE);
-
-                // Hide the ad if this is the free flavor.
+                // Pause the ad if this is the free flavor.
                 if (BuildConfig.FLAVOR.contentEquals("free")) {
-                    BannerAd.hideAd(adView);
+                    BannerAd.pauseAd(adView);
                 }
 
+                // Remove the translucent overlays.
+                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command.
+                drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+
                 /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
                  * 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 rehides them after they are shown.
                  */
-                view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+                rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+                // Set `rootCoordinatorLayout` to fill the entire screen.
+                rootCoordinatorLayout.setFitsSystemWindows(false);
+
+                // Add `view` to `fullScreenVideoFrameLayout` and display it on the screen.
+                fullScreenVideoFrameLayout.addView(view);
+                fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
             }
 
             // Exit full screen video
             public void onHideCustomView() {
-                appBar.show();
+                // Hide `fullScreenVideoFrameLayout`.
+                fullScreenVideoFrameLayout.removeAllViews();
+                fullScreenVideoFrameLayout.setVisibility(View.GONE);
 
-                // Show the mainWebView.
-                mainWebView.setVisibility(View.VISIBLE);
+                // Add the translucent status flag.  This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+                // Set `rootCoordinatorLayout` to fit inside the status and navigation bars.  This also clears the `SYSTEM_UI` flags.
+                rootCoordinatorLayout.setFitsSystemWindows(true);
 
                 // Show the ad if this is the free flavor.
                 if (BuildConfig.FLAVOR.contentEquals("free")) {
-                    BannerAd.showAd(adView);
-                }
+                    // Reload the ad.  Because the screen may have rotated, we need to use `reloadAfterRotate`.
+                    BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
 
-                // Hide the fullScreenVideoFrameLayout.
-                fullScreenVideoFrameLayout.removeAllViews();
-                fullScreenVideoFrameLayout.setVisibility(View.GONE);
+                    // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+                    adView = findViewById(R.id.adView);
+                }
             }
         });
 
@@ -924,7 +938,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             case R.id.clearFormData:
                 WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
                 mainWebViewDatabase.clearFormData();
-                mainWebView.reload();
+                Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_deleted, Snackbar.LENGTH_SHORT).show();
                 return true;
 
             case R.id.fontSizeFiftyPercent:
@@ -1096,8 +1110,8 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 domStorage.deleteAllData();
 
                 // Clear form data.
-                WebViewDatabase formData = WebViewDatabase.getInstance(this);
-                formData.clearFormData();
+                WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this);
+                webViewDatabase.clearFormData();
 
                 // Clear cache.  The argument of "true" includes disk files.
                 mainWebView.clearCache(true);
@@ -1153,16 +1167,13 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
-        // Handle the `adView` for the free version.
-        if (BuildConfig.FLAVOR.contentEquals("free")) {
-            // Reload the add if we are not in full screen mode.
-            if (adView.isShown()) {
-                // Reload the ad.
-                BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+        // Reload the ad for the free flavor if we are not in full screen mode.
+        if (BuildConfig.FLAVOR.contentEquals("free") && adView.isShown() && !fullScreenVideoFrameLayout.isShown()) {
+            // Reload the ad.
+            BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
 
-                // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
-                adView = findViewById(R.id.adView);
-            }
+            // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+            adView = findViewById(R.id.adView);
         }
 
         // `invalidateOptionsMenu` should recalculate the number of action buttons from the menu to display on the app bar, but it doesn't because of the this bug:  https://code.google.com/p/android/issues/detail?id=20493#c8
@@ -1178,6 +1189,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         final String imageUrl;
         final String linkUrl;
 
+        // Get a handle for the `ClipboardManager`.
+        final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+
         switch (hitTestResult.getType()) {
             // `SRC_ANCHOR_TYPE` is a link.
             case WebView.HitTestResult.SRC_ANCHOR_TYPE:
@@ -1187,7 +1201,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 // Set the target URL as the title of the `ContextMenu`.
                 menu.setHeaderTitle(linkUrl);
 
-                // Add a `Load URL` button.
+                // Add a `Load URL` entry.
                 menu.add(R.string.load_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                     @Override
                     public boolean onMenuItemClick(MenuItem item) {
@@ -1196,7 +1210,20 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                     }
                 });
 
-                // Add a `Cancel` button, which by default closes the `ContextMenu`.
+                // Add a `Copy URL` entry.
+                menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                    @Override
+                    public boolean onMenuItemClick(MenuItem item) {
+                        // Save the link URL in a `ClipData`.
+                        ClipData srcAnchorTypeClipData = ClipData.newPlainText(getResources().getString(R.string.url), linkUrl);
+
+                        // Set the `ClipData` as the clipboard's primary clip.
+                        clipboardManager.setPrimaryClip(srcAnchorTypeClipData);
+                        return false;
+                    }
+                });
+
+                // Add a `Cancel` entry, which by default closes the `ContextMenu`.
                 menu.add(R.string.cancel);
                 break;
 
@@ -1207,7 +1234,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 // Set the target URL as the title of the `ContextMenu`.
                 menu.setHeaderTitle(linkUrl);
 
-                // Add a `Write Email` button.
+                // Add a `Write Email` entry.
                 menu.add(R.string.write_email).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                     @Override
                     public boolean onMenuItemClick(MenuItem item) {
@@ -1226,7 +1253,20 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                     }
                 });
 
-                // Add a `Cancel` button, which by default closes the `ContextMenu`.
+                // Add a `Copy Email Address` entry.
+                menu.add(R.string.copy_email_address).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                    @Override
+                    public boolean onMenuItemClick(MenuItem item) {
+                        // Save the email address in a `ClipData`.
+                        ClipData srcEmailTypeClipData = ClipData.newPlainText(getResources().getString(R.string.email_address), linkUrl);
+
+                        // Set the `ClipData` as the clipboard's primary clip.
+                        clipboardManager.setPrimaryClip(srcEmailTypeClipData);
+                        return false;
+                    }
+                });
+
+                // Add a `Cancel` entry, which by default closes the `ContextMenu`.
                 menu.add(R.string.cancel);
                 break;
 
@@ -1238,7 +1278,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 // Set the image URL as the title of the `ContextMenu`.
                 menu.setHeaderTitle(imageUrl);
 
-                // Add a `View Image` button.
+                // Add a `View Image` entry.
                 menu.add(R.string.view_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                     @Override
                     public boolean onMenuItemClick(MenuItem item) {
@@ -1247,7 +1287,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                     }
                 });
 
-                // Add a `Download Image` button.
+                // Add a `Download Image` entry.
                 menu.add(R.string.download_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                     @Override
                     public boolean onMenuItemClick(MenuItem item) {
@@ -1258,7 +1298,20 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                     }
                 });
 
-                // Add a `Cancel` button, which by default closes the `ContextMenu`.
+                // Add a `Copy URL` entry.
+                menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                    @Override
+                    public boolean onMenuItemClick(MenuItem item) {
+                        // Save the image URL in a `ClipData`.
+                        ClipData srcImageTypeClipData = ClipData.newPlainText(getResources().getString(R.string.url), imageUrl);
+
+                        // Set the `ClipData` as the clipboard's primary clip.
+                        clipboardManager.setPrimaryClip(srcImageTypeClipData);
+                        return false;
+                    }
+                });
+
+                // Add a `Cancel` entry, which by default closes the `ContextMenu`.
                 menu.add(R.string.cancel);
                 break;
 
@@ -1271,7 +1324,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 // Set the image URL as the title of the `ContextMenu`.
                 menu.setHeaderTitle(imageUrl);
 
-                // Add a `View Image` button.
+                // Add a `View Image` entry.
                 menu.add(R.string.view_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                     @Override
                     public boolean onMenuItemClick(MenuItem item) {
@@ -1280,7 +1333,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                     }
                 });
 
-                // Add a `Download Image` button.
+                // Add a `Download Image` entry.
                 menu.add(R.string.download_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                     @Override
                     public boolean onMenuItemClick(MenuItem item) {
@@ -1291,7 +1344,20 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                     }
                 });
 
-                // Add a `Cancel` button, which by default closes the `ContextMenu`.
+                // Add a `Copy URL` entry.
+                menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                    @Override
+                    public boolean onMenuItemClick(MenuItem item) {
+                        // Save the image URL in a `ClipData`.
+                        ClipData srcImageAnchorTypeClipData = ClipData.newPlainText(getResources().getString(R.string.url), imageUrl);
+
+                        // Set the `ClipData` as the clipboard's primary clip.
+                        clipboardManager.setPrimaryClip(srcImageAnchorTypeClipData);
+                        return false;
+                    }
+                });
+
+                // Add a `Cancel` entry, which by default closes the `ContextMenu`.
                 menu.add(R.string.cancel);
                 break;
         }
@@ -1408,11 +1474,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         mainWebView.clearHistory();
     }
 
-    // Override onBackPressed to handle the navigation drawer and mainWebView.
+    // Override `onBackPressed` to handle the navigation drawer and `mainWebView`.
     @Override
     public void onBackPressed() {
-        final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
-
         // Close the navigation drawer if it is available.  GravityCompat.START is the drawer on the left on Left-to-Right layout text.
         if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
             drawerLayout.closeDrawer(GravityCompat.START);
@@ -1421,7 +1485,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             if (mainWebView.canGoBack()) {
                 mainWebView.goBack();
             } else {
-                // Pass onBackPressed to the system.
+                // Pass `onBackPressed()` to the system.
                 super.onBackPressed();
             }
         }
@@ -1553,7 +1617,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Store the values from `sharedPreferences` in variables.
-        String userAgentString = sharedPreferences.getString("user_agent", "Default user agent");
+        String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
         String customUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
         String javaScriptDisabledSearchString = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
         String javaScriptDisabledCustomSearchString = sharedPreferences.getString("javascript_disabled_search_custom_url", "");