Add Open With items to the context menus. https://redmine.stoutner.com/issues/374
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index 1ced078a63cab90867551591e8e0c60b8b2a7e96..a57831b7f14c8e4d0df81492c79099c63ca8964d 100644 (file)
@@ -2924,31 +2924,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 return true;
 
             case R.id.open_with_app:
-                // Create the open with intent with `ACTION_VIEW`.
-                Intent openWithAppIntent = new Intent(Intent.ACTION_VIEW);
-
-                // Set the URI but not the MIME type.  This should open all available apps.
-                openWithAppIntent.setData(Uri.parse(formattedUrlString));
-
-                // Flag the intent to open in a new task.
-                openWithAppIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-                // Show the chooser.
-                startActivity(Intent.createChooser(openWithAppIntent, getString(R.string.open_with)));
+                openWithApp(formattedUrlString);
                 return true;
 
             case R.id.open_with_browser:
-                // Create the open with intent with `ACTION_VIEW`.
-                Intent openWithBrowserIntent = new Intent(Intent.ACTION_VIEW);
-
-                // Set the URI and the MIME type.  `"text/html"` should load browser options.
-                openWithBrowserIntent.setDataAndType(Uri.parse(formattedUrlString), "text/html");
-
-                // Flag the intent to open in a new task.
-                openWithBrowserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
-                // Show the chooser.
-                startActivity(Intent.createChooser(openWithBrowserIntent, getString(R.string.open_with)));
+                openWithBrowser(formattedUrlString);
                 return true;
 
             case R.id.add_to_homescreen:
@@ -3330,7 +3310,19 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return false;
                 });
 
-                // Add a `Cancel` entry, which by default closes the `ContextMenu`.
+                // Add an Open with App entry.
+                menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithApp(linkUrl);
+                    return false;
+                });
+
+                // Add an Open with Browser entry.
+                menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithBrowser(linkUrl);
+                    return false;
+                });
+
+                // Add a Cancel entry, which by default closes the context menu.
                 menu.add(R.string.cancel);
                 break;
 
@@ -3341,7 +3333,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Set the target URL as the title of the `ContextMenu`.
                 menu.setHeaderTitle(linkUrl);
 
-                // Add a `Write Email` entry.
+                // Add a Write Email entry.
                 menu.add(R.string.write_email).setOnMenuItemClickListener(item -> {
                     // Use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
                     Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
@@ -3357,7 +3349,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return false;
                 });
 
-                // Add a `Copy Email Address` entry.
+                // Add a Copy Email Address entry.
                 menu.add(R.string.copy_email_address).setOnMenuItemClickListener(item -> {
                     // Save the email address in a `ClipData`.
                     ClipData srcEmailTypeClipData = ClipData.newPlainText(getString(R.string.email_address), linkUrl);
@@ -3379,13 +3371,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Set the image URL as the title of the `ContextMenu`.
                 menu.setHeaderTitle(imageUrl);
 
-                // Add a `View Image` entry.
+                // Add a View Image entry.
                 menu.add(R.string.view_image).setOnMenuItemClickListener(item -> {
                     loadUrl(imageUrl);
                     return false;
                 });
 
-                // Add a `Download Image` entry.
+                // Add a Download Image entry.
                 menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> {
                     // Check if the download should be processed by an external app.
                     if (downloadWithExternalApp) {  // Download with an external app.
@@ -3418,7 +3410,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return false;
                 });
 
-                // Add a `Copy URL` entry.
+                // Add a Copy URL entry.
                 menu.add(R.string.copy_url).setOnMenuItemClickListener(item -> {
                     // Save the image URL in a `ClipData`.
                     ClipData srcImageTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
@@ -3428,6 +3420,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return false;
                 });
 
+                // Add an Open with App entry.
+                menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithApp(imageUrl);
+                    return false;
+                });
+
+                // Add an Open with Browser entry.
+                menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithBrowser(imageUrl);
+                    return false;
+                });
+
                 // Add a `Cancel` entry, which by default closes the `ContextMenu`.
                 menu.add(R.string.cancel);
                 break;
@@ -3490,6 +3494,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     return false;
                 });
 
+                // Add an Open with App entry.
+                menu.add(R.string.open_with_app).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithApp(imageUrl);
+                    return false;
+                });
+
+                // Add an Open with Browser entry.
+                menu.add(R.string.open_with_browser).setOnMenuItemClickListener((MenuItem item) -> {
+                    openWithBrowser(imageUrl);
+                    return false;
+                });
+
                 // Add a `Cancel` entry, which by default closes the `ContextMenu`.
                 menu.add(R.string.cancel);
                 break;
@@ -4536,7 +4552,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Set the loading of webpage images.
                 mainWebView.getSettings().setLoadsImagesAutomatically(displayWebpageImages);
 
-                // Set a transparent background on `urlTextBox`.  We have to use the deprecated `.getDrawable()` until the minimum API >= 21.
+                // Set a transparent background on `urlTextBox`.  The deprecated `.getDrawable()` must be used until the minimum API >= 21.
                 urlAppBarRelativeLayout.setBackgroundDrawable(getResources().getDrawable(R.color.transparent));
             }
 
@@ -4719,59 +4735,62 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     private void highlightUrlText() {
-        // Get the URL string.
-        String urlString = urlTextBox.getText().toString();
-
-        // Highlight the URL according to the protocol.
-        if (urlString.startsWith("file://")) {  // This is a file URL.
-            // De-emphasize only the protocol.
-            urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-        } else if (urlString.startsWith("content://")) {
-            // De-emphasize only the protocol.
-            urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 10, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-        } else {  // This is a web URL.
-            // Get the index of the `/` immediately after the domain name.
-            int endOfDomainName = urlString.indexOf("/", (urlString.indexOf("//") + 2));
-
-            // Create a base URL string.
-            String baseUrl;
-
-            // Get the base URL.
-            if (endOfDomainName > 0) {  // There is at least one character after the base URL.
+        // Only highlight the URL text if the box is not currently selected.
+        if (!urlTextBox.hasFocus()) {
+            // Get the URL string.
+            String urlString = urlTextBox.getText().toString();
+
+            // Highlight the URL according to the protocol.
+            if (urlString.startsWith("file://")) {  // This is a file URL.
+                // De-emphasize only the protocol.
+                urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+            } else if (urlString.startsWith("content://")) {
+                // De-emphasize only the protocol.
+                urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 10, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+            } else {  // This is a web URL.
+                // Get the index of the `/` immediately after the domain name.
+                int endOfDomainName = urlString.indexOf("/", (urlString.indexOf("//") + 2));
+
+                // Create a base URL string.
+                String baseUrl;
+
                 // Get the base URL.
-                baseUrl = urlString.substring(0, endOfDomainName);
-            } else {  // There are no characters after the base URL.
-                // Set the base URL to be the entire URL string.
-                baseUrl = urlString;
-            }
+                if (endOfDomainName > 0) {  // There is at least one character after the base URL.
+                    // Get the base URL.
+                    baseUrl = urlString.substring(0, endOfDomainName);
+                } else {  // There are no characters after the base URL.
+                    // Set the base URL to be the entire URL string.
+                    baseUrl = urlString;
+                }
 
-            // Get the index of the last `.` in the domain.
-            int lastDotIndex = baseUrl.lastIndexOf(".");
+                // Get the index of the last `.` in the domain.
+                int lastDotIndex = baseUrl.lastIndexOf(".");
 
-            // Get the index of the penultimate `.` in the domain.
-            int penultimateDotIndex = baseUrl.lastIndexOf(".", lastDotIndex - 1);
+                // Get the index of the penultimate `.` in the domain.
+                int penultimateDotIndex = baseUrl.lastIndexOf(".", lastDotIndex - 1);
 
-            // Markup the beginning of the URL.
-            if (urlString.startsWith("http://")) {  // Highlight the protocol of connections that are not encrypted.
-                urlTextBox.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                // Markup the beginning of the URL.
+                if (urlString.startsWith("http://")) {  // Highlight the protocol of connections that are not encrypted.
+                    urlTextBox.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
 
-                // De-emphasize subdomains.
-                if (penultimateDotIndex > 0) {  // There is more than one subdomain in the domain name.
-                    urlTextBox.getText().setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-                }
-            } else if (urlString.startsWith("https://")) {  // De-emphasize the protocol of connections that are encrypted.
-                if (penultimateDotIndex > 0) {  // There is more than one subdomain in the domain name.
-                    // De-emphasize the protocol and the additional subdomains.
-                    urlTextBox.getText().setSpan(initialGrayColorSpan, 0, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-                } else {  // There is only one subdomain in the domain name.
-                    // De-emphasize only the protocol.
-                    urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                    // De-emphasize subdomains.
+                    if (penultimateDotIndex > 0) {  // There is more than one subdomain in the domain name.
+                        urlTextBox.getText().setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                    }
+                } else if (urlString.startsWith("https://")) {  // De-emphasize the protocol of connections that are encrypted.
+                    if (penultimateDotIndex > 0) {  // There is more than one subdomain in the domain name.
+                        // De-emphasize the protocol and the additional subdomains.
+                        urlTextBox.getText().setSpan(initialGrayColorSpan, 0, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                    } else {  // There is only one subdomain in the domain name.
+                        // De-emphasize only the protocol.
+                        urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                    }
                 }
-            }
 
-            // De-emphasize the text after the domain name.
-            if (endOfDomainName > 0) {
-                urlTextBox.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                // De-emphasize the text after the domain name.
+                if (endOfDomainName > 0) {
+                    urlTextBox.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                }
             }
         }
     }
@@ -4827,6 +4846,34 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         }
     }
 
+    private void openWithApp(String url) {
+        // Create the open with intent with `ACTION_VIEW`.
+        Intent openWithAppIntent = new Intent(Intent.ACTION_VIEW);
+
+        // Set the URI but not the MIME type.  This should open all available apps.
+        openWithAppIntent.setData(Uri.parse(url));
+
+        // Flag the intent to open in a new task.
+        openWithAppIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        // Show the chooser.
+        startActivity(openWithAppIntent);
+    }
+
+    private void openWithBrowser(String url) {
+        // Create the open with intent with `ACTION_VIEW`.
+        Intent openWithBrowserIntent = new Intent(Intent.ACTION_VIEW);
+
+        // Set the URI and the MIME type.  `"text/html"` should load browser options.
+        openWithBrowserIntent.setDataAndType(Uri.parse(url), "text/html");
+
+        // Flag the intent to open in a new task.
+        openWithBrowserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        // Show the chooser.
+        startActivity(openWithBrowserIntent);
+    }
+
     // This must run asynchronously because it involves a network request.  `String` declares the parameters.  `Void` does not declare progress units.  `String` contains the results.
     private static class GetHostIpAddresses extends AsyncTask<String, Void, String> {
         // The weak references are used to determine if the activity have disappeared while the AsyncTask is running.