]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Refactor style code to use attrs.xml. Create a dark theme for Find on Page.
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index 63617b699cc56db36616b01ad1bdc0ff531f8eb7..02f3742f179468bd309cea8788235046733b433a 100644 (file)
@@ -34,6 +34,7 @@ import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.Typeface;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -59,7 +60,10 @@ import android.support.v7.app.AppCompatActivity;
 import android.support.v7.app.AppCompatDialogFragment;
 import android.support.v7.widget.Toolbar;
 import android.text.Editable;
+import android.text.Spanned;
 import android.text.TextWatcher;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
 import android.util.Patterns;
 import android.view.ContextMenu;
 import android.view.GestureDetector;
@@ -118,8 +122,8 @@ import java.util.Set;
 public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener,
         SslCertificateErrorDialog.SslCertificateErrorListener, DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, UrlHistoryDialog.UrlHistoryListener {
 
-    // `appBar` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()`, `onOptionsItemSelected()`, `closeFindOnPage()`, and `applyAppSettings()`.
-    public static ActionBar appBar;
+    // `darkTheme` is public static so it can be accessed from `AboutActivity` and `GuideActivity`.  It is also used in `onCreate()`, `applyAppSettings()`, and `applyDomainSettings()`.
+    public static boolean darkTheme;
 
     // `favoriteIconBitmap` is public static so it can be accessed from `CreateHomeScreenShortcutDialog`, `BookmarksActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `ViewSslCertificateDialog`.
     // It is also used in `onCreate()`, `onCreateHomeScreenShortcutCreate()`, and `applyDomainSettings`.
@@ -138,9 +142,15 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `webViewTitle` is public static so it can be accessed from `CreateBookmarkDialog` and `CreateHomeScreenShortcutDialog`.  It is also used in `onCreate()`.
     public static String webViewTitle;
 
-    // `displayWebpageImagesBoolean` is public static so it can be accessed from `DomainSettingsFragment`.  It is also used in `applyAppSettings` and `applyDomainSettings()`.
+    // `displayWebpageImagesBoolean` is public static so it can be accessed from `DomainSettingsFragment`.  It is also used in `applyAppSettings()` and `applyDomainSettings()`.
     public static boolean displayWebpageImagesBoolean;
 
+    // `reloadOnRestartBoolean` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onRestart()`
+    public static boolean reloadOnRestartBoolean;
+
+
+    // `appBar` is used in `onCreate()`, `onOptionsItemSelected()`, `closeFindOnPage()`, and `applyAppSettings()`.
+    private ActionBar appBar;
 
     // `navigatingHistory` is used in `onCreate()`, `onNavigationItemSelected()`, and `applyDomainSettings()`.
     private boolean navigatingHistory;
@@ -237,9 +247,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `onTheFlyDisplayImagesSet` is used in `applyDomainSettings()` and `setDisplayWebpageImages()`.
     private boolean onTheFlyDisplayImagesSet;
 
-    // `loadingNewIntentBoolean` is used in `onNewIntent()` and `onRestart()`.
-    private boolean loadingNewIntentBoolean;
-
     // `waitingForOrbotData` is used in `onCreate()` and `applyAppSettings()`.
     private String waitingForOrbotHTMLString;
 
@@ -261,9 +268,21 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `supportAppBar` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
     private Toolbar supportAppBar;
 
-    // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `loadUrl()`.
+    // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, `loadUrlFromTextBox()`, `loadUrl()`, and `highlightUrlText()`.
     private EditText urlTextBox;
 
+    // `redColorSpan` is used in `onCreate()` and `highlightUrlText()`.
+    private ForegroundColorSpan redColorSpan;
+
+    // `initialGrayColorSpan` is sued in `onCreate()` and `highlightUrlText()`.
+    private ForegroundColorSpan initialGrayColorSpan;
+
+    // `finalGrayColorSpam` is used in `onCreate()` and `highlightUrlText()`.
+    private ForegroundColorSpan finalGrayColorSpan;
+
+    // `boldStyleSpan` is used in `onCreate()` and `highlightUrlText()`.
+    private StyleSpan boldStyleSpan;
+
     // `adView` is used in `onCreate()` and `onConfigurationChanged()`.
     private View adView;
 
@@ -279,8 +298,26 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     @Override
     // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.  The whole premise of Privacy Browser is built around an understanding of these dangers.
     @SuppressLint("SetJavaScriptEnabled")
+    // Remove Android Studio's warning about deprecations.  We have to use the deprecated `getColor()` until API >= 23.
+    @SuppressWarnings("deprecation")
     protected void onCreate(Bundle savedInstanceState) {
+        // Get a handle for `sharedPreferences`.  `this` references the current context.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
+
+        // Get the theme preference.
+        darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+
+        // Set the activity theme.
+        if (darkTheme) {
+            setTheme(R.style.PrivacyBrowserDark);
+        } else {
+            setTheme(R.style.PrivacyBrowserLight);
+        }
+
+        // Run the default commands.
         super.onCreate(savedInstanceState);
+
+        // Set the content view.
         setContentView(R.layout.main_drawerlayout);
 
         // Get a handle for `inputMethodManager`.
@@ -298,8 +335,36 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         appBar.setCustomView(R.layout.url_app_bar);
         appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
 
-        // Set the "go" button on the keyboard to load the URL in urlTextBox.
+        // Initialize the `ForegroundColorSpans` and `StyleSpan` for highlighting `urlTextBox`.  We have to use the deprecated `getColor()` until API >= 23.
+        redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
+        initialGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500));
+        finalGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500));
+        boldStyleSpan = new StyleSpan(Typeface.BOLD);
+
+        // Get a handle for `urlTextBox`.
         urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.url_edittext);
+
+        // Remove the formatting from `urlTextBar` when the user is editing the text.
+        urlTextBox.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(View v, boolean hasFocus) {
+                if (hasFocus) {  // The user is editing `urlTextBox`.
+                    // Remove the highlighting.
+                    urlTextBox.getText().removeSpan(redColorSpan);
+                    urlTextBox.getText().removeSpan(initialGrayColorSpan);
+                    urlTextBox.getText().removeSpan(finalGrayColorSpan);
+                    urlTextBox.getText().removeSpan(boldStyleSpan);
+                } else {  // The user has stopped editing `urlTextBox`.
+                    // Reapply the highlighting.
+                    highlightUrlText();
+
+                    // Scroll to the beginning of the text.
+                    urlTextBox.setScrollX(0);
+                }
+            }
+        });
+
+        // Set the `Go` button on the keyboard to load the URL in `urlTextBox`.
         urlTextBox.setOnKeyListener(new View.OnKeyListener() {
             @Override
             public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -547,8 +612,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                     navigationForwardMenuItem.setEnabled(mainWebView.canGoForward());
                     navigationHistoryMenuItem.setEnabled((mainWebView.canGoBack() || mainWebView.canGoForward()));
 
-                    // Hide the keyboard so we can see the navigation menu.  `0` indicates no additional flags.
+                    // Hide the keyboard (if displayed) so we can see the navigation menu.  `0` indicates no additional flags.
                     inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
+
+                    // Clear the focus from `urlTextBox` if it has it.
+                    urlTextBox.clearFocus();
                 }
             }
         });
@@ -656,8 +724,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                     // We need to update `formattedUrlString` at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
                     formattedUrlString = url;
 
-                    // Display the loading URL is the URL text box.
-                    urlTextBox.setText(url);
+                    // Display the formatted URL text.
+                    urlTextBox.setText(formattedUrlString);
+
+                    // Apply text highlighting to `urlTextBox`.
+                    highlightUrlText();
 
                     // Apply any custom domain settings if the URL was loaded by navigating history.
                     if (navigatingHistory) {
@@ -696,7 +767,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                         // Set `formattedUrlString` to `""`.
                         formattedUrlString = "";
 
-                        // Update `urlTextBox`.
                         urlTextBox.setText(formattedUrlString);
 
                         // Request focus for `urlTextBox`.
@@ -705,7 +775,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                         // Display the keyboard.
                         inputMethodManager.showSoftInput(urlTextBox, 0);
 
-                        // Apply the domain settings.
+                        // Apply the domain settings.  This clears any settings from the previous domain.
                         applyDomainSettings(formattedUrlString);
                     } else {  // `WebView` has loaded a webpage.
                         // Set `formattedUrlString`.
@@ -713,7 +783,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
                         // Only update `urlTextBox` if the user is not typing in it.
                         if (!urlTextBox.hasFocus()) {
+                            // Display the formatted URL text.
                             urlTextBox.setText(formattedUrlString);
+
+                            // Apply text highlighting to `urlTextBox`.
+                            highlightUrlText();
                         }
                     }
 
@@ -911,9 +985,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
     @Override
     protected void onNewIntent(Intent intent) {
-        // Set `loadingNewIntentBoolean`.
-        loadingNewIntentBoolean = true;
-
         // Sets the new intent as the activity intent, so that any future `getIntent()`s pick up this one instead of creating a new activity.
         setIntent(intent);
 
@@ -948,12 +1019,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // Set the display webpage images mode.
         setDisplayWebpageImages();
 
-        // Only reload `mainWebView` if not loading a new intent and not waiting for Orbot.
-        if (!loadingNewIntentBoolean && !waitingForOrbot) {
-            // Reload the webpage to remove images if `setDisplayWebpageImages` has turned them off.
+        // Reload the webpage if displaying of images has been disabled in `SettingsFragment`.
+        if (reloadOnRestartBoolean) {
+            // Reload `mainWebView`.
             mainWebView.reload();
-        } else if (loadingNewIntentBoolean) {  // Reset `loadingNewIntentBoolean` if this run comes from a new intent.
-            loadingNewIntentBoolean = false;
+
+            // Reset `reloadOnRestartBoolean`.
+            reloadOnRestartBoolean = false;
         }
     }
 
@@ -2126,7 +2198,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Store the values from `sharedPreferences` in variables.
-        String homepageString = sharedPreferences.getString("homepage", "https://duckduckgo.com");
+        String homepageString = sharedPreferences.getString("homepage", "https://start.duckduckgo.com");
         String torHomepageString = sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion");
         String torSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
         String torSearchCustomURLString = sharedPreferences.getString("tor_search_custom_url", "");
@@ -2162,6 +2234,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             // Set the proxy.  `this` refers to the current activity where an `AlertDialog` might be displayed.
             OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118");
 
+            // Set the `appBar` background to indicate proxying through Orbot is enabled.  `this` refers to the context.
+            if (darkTheme) {
+                appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.dark_blue_30));
+            } else {
+                appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.blue_50));
+            }
+
             // Display a message to the user if we are waiting on Orbot.
             if (!orbotStatus.equals("ON")) {
                 // Set `waitingForOrbot`.
@@ -2189,6 +2268,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             // Reset the proxy to default.  The host is `""` and the port is `"0"`.
             OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
 
+            // Set the default `appBar` background.  `this` refers to the context.
+            if (darkTheme) {
+                appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.gray_900));
+            } else {
+                appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.gray_100));
+            }
+
             // Reset `waitingForOrbot.
             waitingForOrbot = false;
         }
@@ -2388,7 +2474,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 }
 
                 // Set a green background on `urlTextBox` to indicate that custom domain settings are being used.  We have to use the deprecated `.getDrawable()` until the minimum API >= 21.
-                urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_green));
+                if (darkTheme) {
+                    urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
+                } else {
+                    urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
+                }
             } else {  // The URL we are loading does not have custom domain settings.  Load the defaults.
                 // Store the values from `sharedPreferences` in variables.
                 javaScriptEnabled = sharedPreferences.getBoolean("javascript_enabled", false);
@@ -2431,7 +2521,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 }
 
                 // Set a transparent background on `urlTextBox`.  We have to use the deprecated `.getDrawable()` until the minimum API >= 21.
-                urlAppBarRelativeLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.url_bar_background_transparent));
+                urlAppBarRelativeLayout.setBackgroundDrawable(getResources().getDrawable(R.color.transparent));
             }
 
             // Close `domainsDatabaseHelper`.
@@ -2514,4 +2604,23 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             ActivityCompat.invalidateOptionsMenu(this);
         }
     }
+
+    private void highlightUrlText() {
+        String urlString = urlTextBox.getText().toString();
+
+        if (urlString.startsWith("http://")) {  // Highlight connections that are not encrypted.
+            urlTextBox.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+            urlTextBox.getText().setSpan(boldStyleSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        } else if (urlString.startsWith("https://")) {  // Highlight connections that are encrypted.
+            urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        }
+
+        // Get the index of the `/` immediately after the domain name.
+        int endOfDomainName = urlString.indexOf("/", (urlString.indexOf("//") + 2));
+
+        // De-emphasize the text after the domain name.
+        if (endOfDomainName > 0) {
+            urlTextBox.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+        }
+    }
 }