Add the ability to select all bookmarks.
authorSoren Stoutner <soren@stoutner.com>
Tue, 12 Jul 2016 18:48:13 +0000 (11:48 -0700)
committerSoren Stoutner <soren@stoutner.com>
Tue, 12 Jul 2016 18:48:13 +0000 (11:48 -0700)
18 files changed:
app/build.gradle
app/src/main/AndroidManifest.xml
app/src/main/assets/about_licenses.html
app/src/main/assets/images/ic_select_all.png [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/BookmarksActivity.java
app/src/main/java/com/stoutner/privacybrowser/CreateBookmark.java
app/src/main/java/com/stoutner/privacybrowser/CreateHomeScreenShortcut.java
app/src/main/java/com/stoutner/privacybrowser/EditBookmark.java
app/src/main/res/drawable/select_all.xml [new file with mode: 0644]
app/src/main/res/layout/about_coordinatorlayout.xml
app/src/main/res/layout/bookmarks_coordinatorlayout.xml
app/src/main/res/layout/guide_coordinatorlayout.xml
app/src/main/res/layout/main_coordinatorlayout.xml
app/src/main/res/menu/bookmarks_context_menu.xml
app/src/main/res/menu/bookmarks_options_menu.xml [new file with mode: 0644]
app/src/main/res/menu/menu_bookmarks_options.xml [deleted file]
app/src/main/res/values/strings.xml
app/src/main/res/values/styles.xml

index 9b770e4..8b0f695 100644 (file)
@@ -54,6 +54,6 @@ android {
 dependencies {
     compile fileTree(dir: 'libs', include: ['*.jar'])
     compile 'com.android.support:design:23.4.0'
-    // Only compile com.google.android.gms:play-services-ads for the free version.
-    freeCompile 'com.google.android.gms:play-services-ads:9.2.0'
+    // Only compile `com.google.android.gms:play-services-ads` for the free flavor.
+    freeCompile 'com.google.android.gms:play-services-ads:9.2.1'
 }
index 246393e..17fb93a 100644 (file)
@@ -49,7 +49,6 @@
         <activity
             android:name=".MainWebViewActivity"
             android:label="@string/privacy_browser"
-            android:theme="@style/PrivacyBrowser.MainWebView"
             android:configChanges="orientation|screenSize"
             android:launchMode="singleTask"
             android:persistableMode="persistNever" >
@@ -86,7 +85,7 @@
         <activity
             android:name=".SettingsActivity"
             android:label="@string/privacy_browser_settings"
-            android:theme="@style/PrivacyBrowser.Settings"
+            android:theme="@style/Settings"
             android:parentActivityName=".MainWebViewActivity"
             android:configChanges="orientation|screenSize"
             android:persistableMode="persistNever" >
index 6ff6928..bb6fa1a 100644 (file)
@@ -80,6 +80,8 @@
 <p><img class="center" src="images/ic_edit.png" height="32" width="32"> ic_edit.</p>
 
 <p><img class="center" src="images/ic_delete.png" height="32" width="32"> ic_download.</p>
+
+<p><img class="center" src="images/ic_select_all.png" height="32" width="32"> ic_select_all</p>
 <hr/>
 
 <h3>GNU General Public License</h3>
diff --git a/app/src/main/assets/images/ic_select_all.png b/app/src/main/assets/images/ic_select_all.png
new file mode 100644 (file)
index 0000000..92aab4e
Binary files /dev/null and b/app/src/main/assets/images/ic_select_all.png differ
index 108dcc0..b6e67c8 100644 (file)
@@ -108,14 +108,18 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
             // `editBookmarkMenuItem` is used in `onCreateActionMode()` and `onItemCheckedStateChanged`.
             MenuItem editBookmarkMenuItem;
 
+            // `selectAllBookmarks` is used in `onCreateActionMode()` and `onItemCheckedStateChanges`.
+            MenuItem selectAllBookmarks;
+
             @Override
             public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                 // Inflate the menu for the contextual app bar and set the title.
                 getMenuInflater().inflate(R.menu.bookmarks_context_menu, menu);
                 mode.setTitle(R.string.bookmarks);
 
-                // Get a handle for `R.id.edit_bookmark`.
+                // Get a handle for `R.id.edit_bookmark` and `R.id.select_all_bookmarks`.
                 editBookmarkMenuItem = menu.findItem(R.id.edit_bookmark);
+                selectAllBookmarks = menu.findItem(R.id.context_menu_select_all_bookmarks);
 
                 return true;
             }
@@ -137,11 +141,18 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                 mode.setSubtitle(numberOfSelectedBookmarks + " " + getString(R.string.selected));
 
                 // Show the `Edit` option only if 1 bookmark is selected.
-                if (numberOfSelectedBookmarks == 1) {
+                if (numberOfSelectedBookmarks < 2) {
                     editBookmarkMenuItem.setVisible(true);
                 } else {
                     editBookmarkMenuItem.setVisible(false);
                 }
+
+                // Do not show `Select All` if all the bookmarks are already checked.
+                if (bookmarksListView.getCheckedItemIds().length == bookmarksListView.getCount()) {
+                    selectAllBookmarks.setVisible(false);
+                } else {
+                    selectAllBookmarks.setVisible(true);
+                }
             }
 
             @Override
@@ -210,6 +221,14 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                         // Close the contextual app bar.
                         mode.finish();
                         break;
+
+                    case R.id.context_menu_select_all_bookmarks:
+                        int numberOfBookmarks = bookmarksListView.getCount();
+
+                        for (int i = 0; i < numberOfBookmarks; i++) {
+                            bookmarksListView.setItemChecked(i, true);
+                        }
+                        break;
                 }
                 // Consume the click.
                 return true;
@@ -234,6 +253,41 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         });
     }
 
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        //Inflate the menu.
+        getMenuInflater().inflate(R.menu.bookmarks_options_menu, menu);
+
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem menuItem) {
+        int menuItemId = menuItem.getItemId();
+
+        switch (menuItemId) {
+            case android.R.id.home:
+                NavUtils.navigateUpFromSameTask(this);
+                break;
+
+            case R.id.options_menu_select_all_bookmarks:
+                int numberOfBookmarks = bookmarksListView.getCount();
+
+                for (int i = 0; i < numberOfBookmarks; i++) {
+                    bookmarksListView.setItemChecked(i, true);
+                }
+                break;
+        }
+        return true;
+    }
+
     @Override
     public void onCreateBookmarkCancel(DialogFragment createBookmarkDialogFragment) {
         // Do nothing because the user selected `Cancel`.
index 6471435..c5acd03 100644 (file)
@@ -62,7 +62,7 @@ public class CreateBookmark extends DialogFragment {
         Drawable favoriteIconDrawable = new BitmapDrawable(getResources(), MainWebViewActivity.favoriteIcon);
 
         // Use `AlertDialog.Builder` to create the `AlertDialog`.  The style formats the color of the button text.
-        AlertDialog.Builder createBookmarkDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowser_AlertDialog);
+        AlertDialog.Builder createBookmarkDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.LightAlertDialog);
         createBookmarkDialogBuilder.setTitle(R.string.create_bookmark);
         createBookmarkDialogBuilder.setIcon(favoriteIconDrawable);
         // The parent view is `null` because it will be assigned by `AlertDialog`.
index ea225ca..71e84ab 100644 (file)
@@ -64,7 +64,7 @@ public class CreateHomeScreenShortcut extends DialogFragment {
         LayoutInflater customDialogInflater = getActivity().getLayoutInflater();
 
         // Use AlertDialog.Builder to create the AlertDialog.  The style formats the color of the button text.
-        AlertDialog.Builder createHomeScreenShorcutDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowser_AlertDialog);
+        AlertDialog.Builder createHomeScreenShorcutDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.LightAlertDialog);
         createHomeScreenShorcutDialogBuilder.setTitle(R.string.create_shortcut);
         createHomeScreenShorcutDialogBuilder.setIcon(favoriteIconDrawable);
         // The parent view is "null" because it will be assigned by AlertDialog.
index 27d522b..8eee58d 100644 (file)
@@ -77,7 +77,7 @@ public class EditBookmark extends DialogFragment {
         Drawable favoriteIconDrawable = new BitmapDrawable(getResources(), favoriteIconBitmap);
 
         // Use `AlertDialog.Builder` to create the `AlertDialog`.  The style formats the color of the button text.
-        AlertDialog.Builder editBookmarkDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowser_AlertDialog);
+        AlertDialog.Builder editBookmarkDialogBuilder = new AlertDialog.Builder(getActivity(), R.style.LightAlertDialog);
         editBookmarkDialogBuilder.setTitle(R.string.edit_bookmark);
         editBookmarkDialogBuilder.setIcon(favoriteIconDrawable);
         // The parent view is `null` because it will be assigned by `AlertDialog`.
diff --git a/app/src/main/res/drawable/select_all.xml b/app/src/main/res/drawable/select_all.xml
new file mode 100644 (file)
index 0000000..24205a5
--- /dev/null
@@ -0,0 +1,14 @@
+<!-- select_all.xml comes from the Android Material icon set, where it is called ic_select_all.
+  It is released under the CC-BY license <https://creativecommons.org/licenses/by/4.0/>. -->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="24dp"
+    android:width="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0" >
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
+</vector>
index 46fe249..a0d221e 100644 (file)
@@ -41,7 +41,7 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:background="@color/blue"
-            android:theme="@style/PrivacyBrowser.AppBarOverlay" >
+            android:theme="@style/AppBarOverlay" >
 
             <!-- android:theme="@style/PrivacyBrowser.DarkAppBar" makes the text and icons in the AppBar white. -->
             <android.support.v7.widget.Toolbar
@@ -49,8 +49,8 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:background="@color/blue"
-                android:theme="@style/PrivacyBrowser.DarkAppBar"
-                app:popupTheme="@style/PrivacyBrowser.PopupOverlay" />
+                android:theme="@style/DarkAppBar"
+                app:popupTheme="@style/LightPopupOverlay" />
 
             <android.support.design.widget.TabLayout
                 android:id="@+id/about_tablayout"
index 15bde09..783a19b 100644 (file)
@@ -39,7 +39,7 @@
             android:id="@+id/bookmarks_appbarlayout"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
-            android:theme="@style/PrivacyBrowser.AppBarOverlay" >
+            android:theme="@style/AppBarOverlay" >
 
             <!-- android:theme="@style/PrivacyBrowser.DarkAppBar" makes the text and icons in the AppBar white. -->
             <android.support.v7.widget.Toolbar
@@ -47,8 +47,8 @@
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:background="@color/blue"
-                android:theme="@style/PrivacyBrowser.DarkAppBar"
-                app:popupTheme="@style/PrivacyBrowser.PopupOverlay" />
+                android:theme="@style/DarkAppBar"
+                app:popupTheme="@style/LightPopupOverlay" />
         </android.support.design.widget.AppBarLayout>
 
         <!-- android:choiceMode="multipleChoiceModal" allows the contextual action menu to select more than one item at a time.
index 2165440..9f755e7 100644 (file)
@@ -41,7 +41,7 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:background="@color/blue"
-            android:theme="@style/PrivacyBrowser.AppBarOverlay" >
+            android:theme="@style/AppBarOverlay" >
 
             <!-- android:theme="@style/PrivacyBrowser.DarkAppBar" makes the text and icons in the AppBar white. -->
             <android.support.v7.widget.Toolbar
@@ -49,8 +49,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:background="@color/blue"
-                android:theme="@style/PrivacyBrowser.DarkAppBar"
-                app:popupTheme="@style/PrivacyBrowser.PopupOverlay" />
+                android:theme="@style/DarkAppBar"
+                app:popupTheme="@style/LightPopupOverlay" />
 
             <android.support.design.widget.TabLayout
                 android:id="@+id/guide_tablayout"
index 520f450..3394098 100644 (file)
                 android:id="@+id/appBarLayout"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:theme="@style/PrivacyBrowser.AppBarOverlay" >
+                android:theme="@style/AppBarOverlay" >
 
                 <android.support.v7.widget.Toolbar
                     android:id="@+id/appBar"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:background="?attr/colorPrimary"
-                    app:popupTheme="@style/PrivacyBrowser.PopupOverlay" />
+                    app:popupTheme="@style/LightPopupOverlay" />
             </android.support.design.widget.AppBarLayout>
 
             <include layout="@layout/main_webview" />
index 6b2fc74..98b790a 100644 (file)
         android:orderInCategory="20"
         android:icon="@drawable/delete"
         app:showAsAction="ifRoom" />
+
+    <item
+        android:id="@+id/context_menu_select_all_bookmarks"
+        android:title="@string/select_all"
+        android:orderInCategory="30"
+        android:icon="@drawable/select_all"
+        app:showAsAction="ifRoom" />
 </menu>
\ No newline at end of file
diff --git a/app/src/main/res/menu/bookmarks_options_menu.xml b/app/src/main/res/menu/bookmarks_options_menu.xml
new file mode 100644 (file)
index 0000000..856594c
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright 2015-2016 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<menu
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <item
+        android:id="@+id/options_menu_select_all_bookmarks"
+        android:title="@string/select_all"
+        android:orderInCategory="10"
+        android:icon="@drawable/select_all"
+        app:showAsAction="ifRoom" />
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_bookmarks_options.xml b/app/src/main/res/menu/menu_bookmarks_options.xml
deleted file mode 100644 (file)
index 97d6487..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright 2015-2016 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
-
-  Privacy Browser is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  Privacy Browser is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<menu
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
-
-    <item
-        android:id="@+id/delete_bookmark1"
-        android:title="@string/delete"
-        android:orderInCategory="10"
-        android:icon="@drawable/delete"
-        app:showAsAction="ifRoom" />
-</menu>
\ No newline at end of file
index 5b5ad90..6942445 100644 (file)
@@ -82,6 +82,7 @@
     <string name="selected">Selected</string>
     <string name="edit">Edit</string>
     <string name="delete">Delete</string>
+    <string name="select_all">Select All</string>
     <string name="one_bookmark_deleted">1 Bookmark Deleted</string>
     <string name="bookmarks_deleted">Bookmarks Deleted</string>
     <string name="undo">Undo</string>
index 0b1697e..25ca3a0 100644 (file)
         <item name="colorAccent">@color/blue</item>
     </style>
 
-    <style name="PrivacyBrowser.MainWebView" />
-
-    <!-- `android:windowTranslucentStatus` makes the system status bar transparent.
-        When it is specified the root layout should include android:fitsSystemWindows="true".
-        `colorPrimaryDark` goes behind the status bar, which is then darkened by the overlay.
-        `windowActionModeOverlay` makes the contextual app bar cover the support app bar.
-        `actionModeStyle` sets the style of the contextual app bar. -->
+    <!-- `colorPrimaryDark` goes behind the status bar, which is then darkened by the overlay.
+        `windowActionModeOverlay` makes the contextual app bar cover the support app bar. -->
     <style name="PrivacyBrowser.SecondaryActivity">
-        <item name="android:windowTranslucentStatus">true</item>
         <item name="colorPrimaryDark">@color/blue</item>
         <item name="windowActionModeOverlay">true</item>
         <item name="android:actionModeBackground">@color/blue</item>
+        <item name="actionBarPopupTheme">@style/LightPopupOverlay</item>
     </style>
 
     <!-- `colorPrimaryDark` is the color of the status bar. -->
-    <style name="PrivacyBrowser.Settings" parent="Theme.AppCompat.Light.DarkActionBar">
+    <style name="Settings" parent="Theme.AppCompat.Light.DarkActionBar">
         <item name="colorPrimary">@color/blue</item>
         <item name="colorPrimaryDark">@color/dark_blue</item>
         <item name="colorAccent">@color/blue</item>
     </style>
 
-    <!-- `ThemeOverlay.AppCompat.Dark.ActionBar` makes the text and the icons in the AppBar white.-->
-    <style name="PrivacyBrowser.DarkAppBar" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+    <!-- `ThemeOverlay.AppCompat.Dark.ActionBar` makes the text and the icons in the AppBar white. -->
+    <style name="DarkAppBar" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
 
-    <style name="PrivacyBrowser.AppBarOverlay" parent="ThemeOverlay.AppCompat.ActionBar" />
+    <style name="AppBarOverlay" parent="ThemeOverlay.AppCompat.ActionBar" />
 
-    <style name="PrivacyBrowser.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
+    <!-- `ThemeOverlay.AppCompat.Light` makes the popups have a white background with black text. -->
+    <style name="LightPopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
 
-    <style name="PrivacyBrowser.AlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
+    <style name="LightAlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert" >
         <item name="colorAccent">@color/blue</item>
     </style>
 </resources>
\ No newline at end of file