]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Finish creating the bookmark drawer. https://redmine.stoutner.com/issues/132
authorSoren Stoutner <soren@stoutner.com>
Sat, 7 Oct 2017 00:41:31 +0000 (17:41 -0700)
committerSoren Stoutner <soren@stoutner.com>
Sat, 7 Oct 2017 00:41:31 +0000 (17:41 -0700)
16 files changed:
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/dialogs/CreateBookmarkFolderDialog.java
app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.java
app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java
app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java
app/src/main/java/com/stoutner/privacybrowser/fragments/GuideTabFragment.java
app/src/main/res/drawable/block_ads_disabled_dark.xml
app/src/main/res/drawable/block_ads_disabled_light.xml
app/src/main/res/drawable/block_ads_enabled_dark.xml
app/src/main/res/drawable/block_ads_enabled_light.xml
app/src/main/res/drawable/bookmarks.xml [deleted file]
app/src/main/res/drawable/bookmarks_dark.xml [new file with mode: 0644]
app/src/main/res/drawable/bookmarks_light.xml [new file with mode: 0644]
app/src/main/res/layout/main_drawerlayout.xml
app/src/main/res/menu/webview_navigation_menu.xml

index 6ea013c9d6675c90437a9a0ad07b0385f807382a..97b4f3a6e39f588be07a2bf71a5623c274615845 100644 (file)
@@ -64,16 +64,15 @@ import java.io.ByteArrayOutputStream;
 public class BookmarksActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, EditBookmarkDialog.EditBookmarkListener,
         EditBookmarkFolderDialog.EditBookmarkFolderListener, MoveToFolderDialog.MoveToFolderListener {
 
-    // `bookmarksDatabaseHelper` is public static so it can be accessed from `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog` and `MoveToFolderDialog`.  It is also used in `onCreate()`, `onOptionsItemSelected()`,
-    // `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`, and `loadFolder().
+    // `bookmarksDatabaseHelper` is public static so it can be accessed from `MoveToFolderDialog`.  It is also used in `onCreate()`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`,
+    // `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`, and `loadFolder().
     public static BookmarksDatabaseHelper bookmarksDatabaseHelper;
 
     // `currentFolder` is public static so it can be accessed from `MoveToFolderDialog`.
     // It is used in `onCreate`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `loadFolder()`.
     public static String currentFolder;
 
-    // `checkedItemIds` is public static so it can be accessed from `EditBookmarkDialog`, `EditBookmarkFolderDialog`, and `MoveToFolderDialog`.
-    // It is also used in `onCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `updateMoveIcons()`.
+    // `checkedItemIds` is public static so it can be accessed from `MoveToFolderDialog`.  It is also used in `onCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `updateMoveIcons()`.
     public static long[] checkedItemIds;
 
 
@@ -114,6 +113,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         // Run the default commands.
         super.onCreate(savedInstanceState);
 
+        // Get the intent that launched the activity.
+        Intent launchingIntent = getIntent();
+
+        // Get the current folder from the `Intent`.
+        currentFolder = launchingIntent.getStringExtra("Current Folder");
+
         // Set the content view.
         setContentView(R.layout.bookmarks_coordinatorlayout);
 
@@ -136,9 +141,6 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         // The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
         bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this, null, null, 0);
 
-        // Set currentFolder to the home folder, which is `""` in the database.
-        currentFolder = "";
-
         // Load the home folder.
         loadFolder();
 
@@ -164,6 +166,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                     // Get the bookmark URL and assign it to `formattedUrlString`.  `mainWebView` will automatically reload when `BookmarksActivity` closes.
                     MainWebViewActivity.formattedUrlString = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
 
+                    // Update the bookmarks folder for the bookmarks drawer in `MainWebViewActivity`.
+                    MainWebViewActivity.currentBookmarksFolder = currentFolder;
+
+                    // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`.
+                    MainWebViewActivity.restartFromBookmarksActivity = true;
+
                     // Return to `MainWebViewActivity`.
                     NavUtils.navigateUpFromSameTask(bookmarksActivity);
                 }
@@ -380,23 +388,23 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                         // Get the position of the selected bookmark.  Only one bookmark is selected when `edit_bookmark_down` is enabled.
                         selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(0);
 
-                        // Move to the selected database ID and find out if it is a folder.
+                        // Move to the selected position and find out if it is a folder.
                         bookmarksCursor.moveToPosition(selectedBookmarkPosition);
                         boolean isFolder = (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
 
-                        // Store `checkedItemIds` for use by the `AlertDialog`.
-                        checkedItemIds = bookmarksListView.getCheckedItemIds();
+                        // Get the selected bookmark database ID.
+                        int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper._ID));
 
                         if (isFolder) {
                             // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
                             oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
-                            // Show the `EditBookmarkFolderDialog` `AlertDialog` and name the instance `@string/edit_folder`.
-                            AppCompatDialogFragment editFolderDialog = new EditBookmarkFolderDialog();
+                            // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`.
+                            AppCompatDialogFragment editFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId);
                             editFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder));
                         } else {
-                            // Show the `EditBookmarkDialog` `AlertDialog` and name the instance `@string/edit_bookmark`.
-                            AppCompatDialogFragment editBookmarkDialog = new EditBookmarkDialog();
+                            // Show the edit bookmark `AlertDialog` and name the instance `@string/edit_bookmark`.
+                            AppCompatDialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId);
                             editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
                         }
                         break;
@@ -553,6 +561,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         switch (menuItemId) {
             case android.R.id.home:  // The home arrow is identified as `android.R.id.home`, not just `R.id.home`.
                 if (currentFolder.isEmpty()) {  // Currently in the home folder.
+                    // Update the bookmarks folder for the bookmarks drawer in `MainWebViewActivity`.
+                    MainWebViewActivity.currentBookmarksFolder = "";
+
+                    // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`.
+                    MainWebViewActivity.restartFromBookmarksActivity = true;
+
                     // Return to `MainWebViewActivity`.
                     NavUtils.navigateUpFromSameTask(this);
                 } else {  // Currently in a subfolder.
@@ -586,6 +600,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
     @Override
     public void onBackPressed() {
         if (currentFolder.isEmpty()) {  // Currently in the home folder.
+            // Update the bookmarks folder for the bookmarks drawer in `MainWebViewActivity`.
+            MainWebViewActivity.currentBookmarksFolder = "";
+
+            // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`.
+            MainWebViewActivity.restartFromBookmarksActivity = true;
+
             // Exit `BookmarksActivity`.
             super.onBackPressed();
         } else {  // Currently in a subfolder.
@@ -607,9 +627,8 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         String bookmarkNameString = createBookmarkNameEditText.getText().toString();
         String bookmarkUrlString = createBookmarkUrlEditText.getText().toString();
 
-        // Convert the favoriteIcon Bitmap to a byte array.
+        // Convert the favoriteIcon Bitmap to a byte array.  `0` is for lossless compression (the only option for a PNG).
         ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
-        // `0` is for lossless compression (the only option for a PNG).
         MainWebViewActivity.favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream);
         byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray();
 
@@ -675,7 +694,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
     }
 
     @Override
-    public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment) {
+    public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
         // Get handles for the views from `dialogFragment`.
         EditText editBookmarkNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext);
         EditText editBookmarkUrlEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext);
@@ -685,12 +704,6 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         String bookmarkNameString = editBookmarkNameEditText.getText().toString();
         String bookmarkUrlString = editBookmarkUrlEditText.getText().toString();
 
-        // Get an array of the selected row IDs.
-        long[] selectedBookmarksLongArray = bookmarksListView.getCheckedItemIds();
-
-        // Get the database ID of the selected bookmark.  Editing a bookmark is only possible where only one item is selected.
-        int selectedBookmarkDatabaseId = (int) selectedBookmarksLongArray[0];
-
         // Update the bookmark.
         if (currentBookmarkIconRadioButton.isChecked()) {  // Update the bookmark without changing the favorite icon.
             bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString);
@@ -715,7 +728,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
     }
 
     @Override
-    public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment) {
+    public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId) {
         // Get handles for the views from `dialogFragment`.
         EditText editFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext);
         RadioButton currentFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton);
@@ -725,12 +738,6 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         // Get the new folder name.
         String newFolderNameString = editFolderNameEditText.getText().toString();
 
-        // Get an array of the selected row IDs.
-        long[] selectedBookmarksLongArray = bookmarksListView.getCheckedItemIds();
-
-        // Get the database ID of the selected bookmark.  Editing a folder is only possible where only one item is selected.
-        int selectedFolderDatabaseId = (int) selectedBookmarksLongArray[0];
-
         // Check if the favorite icon has changed.
         if (currentFolderIconRadioButton.isChecked()) {  // Only the name has changed.
             // Update the name in the database.
index 6bc302adc988ff2f72c513ce8be9bcb2a2f33023..bb7ae1dedb6eac55911b4d0a0f9db371e439dc3e 100644 (file)
@@ -97,14 +97,19 @@ import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.ProgressBar;
+import android.widget.RadioButton;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.stoutner.privacybrowser.BannerAd;
 import com.stoutner.privacybrowser.BuildConfig;
 import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog;
+import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog;
 import com.stoutner.privacybrowser.dialogs.CreateHomeScreenShortcutDialog;
 import com.stoutner.privacybrowser.dialogs.DownloadImageDialog;
+import com.stoutner.privacybrowser.dialogs.EditBookmarkDialog;
+import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDialog;
 import com.stoutner.privacybrowser.dialogs.HttpAuthenticationDialog;
 import com.stoutner.privacybrowser.dialogs.PinnedSslCertificateMismatchDialog;
 import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog;
@@ -117,6 +122,7 @@ import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -132,9 +138,9 @@ import java.util.Map;
 import java.util.Set;
 
 // We need to use AppCompatActivity from android.support.v7.app.AppCompatActivity to have access to the SupportActionBar until the minimum API is >= 21.
-public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener,
-        HttpAuthenticationDialog.HttpAuthenticationListener, PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, DownloadFileDialog.DownloadFileListener,
-        DownloadImageDialog.DownloadImageListener, UrlHistoryDialog.UrlHistoryListener {
+public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener,
+        DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, EditBookmarkDialog.EditBookmarkListener, EditBookmarkFolderDialog.EditBookmarkFolderListener, HttpAuthenticationDialog.HttpAuthenticationListener,
+        NavigationView.OnNavigationItemSelectedListener, PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
 
     // `darkTheme` is public static so it can be accessed from `AboutActivity`, `GuideActivity`, `AddDomainDialog`, `SettingsActivity`, `DomainsActivity`, `DomainsListFragment`, `BookmarksActivity`, `BookmarksDatabaseViewActivity`,
     // `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `DownloadFileDialog`, `DownloadImageDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `HttpAuthenticationDialog`, `MoveToFolderDialog`, `SslCertificateErrorDialog`, `UrlHistoryDialog`,
@@ -142,7 +148,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     public static boolean darkTheme;
 
     // `favoriteIconBitmap` is public static so it can be accessed from `CreateHomeScreenShortcutDialog`, `BookmarksActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`,
-    // and `ViewSslCertificateDialog`.  It is also used in `onCreate()`, `onCreateHomeScreenShortcutCreate()`, and `applyDomainSettings`.
+    // and `ViewSslCertificateDialog`.  It is also used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onCreateHomeScreenShortcutCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `applyDomainSettings()`.
     public static Bitmap favoriteIconBitmap;
 
     // `formattedUrlString` is public static so it can be accessed from `BookmarksActivity`, `CreateBookmarkDialog`, and `AddDomainDialog`.
@@ -167,6 +173,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `reloadUrlOnRestart` is public static so it can be accessed from `SettingsFragment`.  It is also used in `onRestart()`.
     public static boolean loadUrlOnRestart;
 
+    // `restartFromBookmarksActivity` is public static so it can be accessed from `BookmarksActivity`.  It is also used in `onRestart()`.
+    public static boolean restartFromBookmarksActivity;
+
+    // `currentBookmarksFolder` is public static so it can be accessed from `BookmarksActivity`.  It is also used in `onCreate()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and
+    // `loadBookmarksFolder()`.
+    public static String currentBookmarksFolder;
+
     // The pinned domain SSL Certificate variables are public static so they can be accessed from `PinnedSslCertificateMismatchDialog`.  They are also used in `onCreate()` and `applyDomainSettings()`.
     public static int domainSettingsDatabaseId;
     public static String pinnedDomainSslIssuedToCNameString;
@@ -188,7 +201,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `favoriteIconDefaultBitmap` is used in `onCreate()` and `applyDomainSettings`.
     private Bitmap favoriteIconDefaultBitmap;
 
-    // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`.
+    // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, `onBackPressed()`, and `onRestart()`.
     private DrawerLayout drawerLayout;
 
     // `rootCoordinatorLayout` is used in `onCreate()` and `applyAppSettings()`.
@@ -336,18 +349,24 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
     // `pinnedDomainSslCertificate` is used in `onCreate()` and `applyDomainSettings()`.
     private boolean pinnedDomainSslCertificate;
 
-    // `bookmarksDatabaseHelper` is used in `onCreate()` and `loadBookmarksFolder()`.
+    // `bookmarksDatabaseHelper` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
     private BookmarksDatabaseHelper bookmarksDatabaseHelper;
 
-    // `bookmarksListView` is used in `onCreate()` and `loadBookmarksFolder()`.
+    // `bookmarksListView` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, and `loadBookmarksFolder()`.
     private ListView bookmarksListView;
 
-    // `currentBookmarksFolder` is used in `onCreate()`, `onBackPressed()`, and `loadBookmarksFolder()`.
-    private String currentBookmarksFolder;
-
     // `bookmarksTitleTextView` is used in `onCreate()` and `loadBookmarksFolder()`.
     private TextView bookmarksTitleTextView;
 
+    // `bookmarksCursor` is used in `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
+    private Cursor bookmarksCursor;
+
+    // `bookmarksCursorAdapter` is used in `onCreateBookmark()`, `onCreateBookmarkFolder()` `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
+    private CursorAdapter bookmarksCursorAdapter;
+
+    // `oldFolderNameString` is used in `onCreate()` and `onSaveEditBookmarkFolder()`.
+    private String oldFolderNameString;
+
     @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")
@@ -467,7 +486,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout);
         bookmarksListView = (ListView) findViewById(R.id.bookmarks_drawer_listview);
         bookmarksTitleTextView = (TextView) findViewById(R.id.bookmarks_title_textview);
-        FloatingActionButton createBookmarksFolderFab = (FloatingActionButton) findViewById(R.id.create_bookmark_folder_fab);
+        FloatingActionButton launchBookmarksActivityFab = (FloatingActionButton) findViewById(R.id.launch_bookmarks_activity_fab);
+        FloatingActionButton createBookmarkFolderFab = (FloatingActionButton) findViewById(R.id.create_bookmark_folder_fab);
         FloatingActionButton createBookmarkFab = (FloatingActionButton) findViewById(R.id.create_bookmark_fab);
         mainWebViewRelativeLayout = (RelativeLayout) findViewById(R.id.main_webview_relativelayout);
         mainWebView = (WebView) findViewById(R.id.main_webview);
@@ -479,15 +499,52 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
         // Set the bookmarks drawer resources according to the theme.  This can't be done in the layout due to compatibility issues with the `DrawerLayout` support widget.
         if (darkTheme) {
-            createBookmarksFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_dark));
+            launchBookmarksActivityFab.setImageDrawable(getResources().getDrawable(R.drawable.bookmarks_dark));
+            createBookmarkFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_dark));
             createBookmarkFab.setImageDrawable(getResources().getDrawable(R.drawable.create_bookmark_dark));
             bookmarksListView.setBackgroundColor(getResources().getColor(R.color.gray_850));
         } else {
-            createBookmarksFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_light));
+            launchBookmarksActivityFab.setImageDrawable(getResources().getDrawable(R.drawable.bookmarks_light));
+            createBookmarkFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_light));
             createBookmarkFab.setImageDrawable(getResources().getDrawable(R.drawable.create_bookmark_light));
             bookmarksListView.setBackgroundColor(getResources().getColor(R.color.white));
         }
 
+        // Set the launch bookmarks activity FAB to launch the bookmarks activity.
+        launchBookmarksActivityFab.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // Create an intent to launch the bookmarks activity.
+                Intent bookmarksIntent = new Intent(getApplicationContext(), BookmarksActivity.class);
+
+                // Include the current folder with the `Intent`.
+                bookmarksIntent.putExtra("Current Folder", currentBookmarksFolder);
+
+                // Make it so.
+                startActivity(bookmarksIntent);
+            }
+        });
+
+        // Set the create new bookmark folder FAB to display the `AlertDialog`.
+        createBookmarkFolderFab.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // Show the `CreateBookmarkFolderDialog` `AlertDialog` and name the instance `@string/create_folder`.
+                AppCompatDialogFragment createBookmarkFolderDialog = new CreateBookmarkFolderDialog();
+                createBookmarkFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.create_folder));
+            }
+        });
+
+        // Set the create new bookmark FAB to display the `AlertDialog`.
+        createBookmarkFab.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                // Show the `CreateBookmarkDialog` `AlertDialog` and name the instance `@string/create_bookmark`.
+                AppCompatDialogFragment createBookmarkDialog = new CreateBookmarkDialog();
+                createBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.create_bookmark));
+            }
+        });
+
         // Create a double-tap listener to toggle full-screen mode.
         final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
             // Override `onDoubleTap()`.  All other events are handled using the default settings.
@@ -694,6 +751,33 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             }
         });
 
+        bookmarksListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
+            @Override
+            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+                // Convert the database ID from `long` to `int`.
+                int databaseId = (int) id;
+
+                // Find out if the selected bookmark is a folder.
+                boolean isFolder = bookmarksDatabaseHelper.isFolder(databaseId);
+
+                if (isFolder) {
+                    // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
+                    oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+
+                    // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`.
+                    AppCompatDialogFragment editFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId);
+                    editFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder));
+                } else {
+                    // Show the edit bookmark `AlertDialog` and name the instance `@string/edit_bookmark`.
+                    AppCompatDialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId);
+                    editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
+                }
+
+                // Consume the event.
+                return true;
+            }
+        });
+
         // The `DrawerListener` allows us to update the Navigation Menu.
         drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
             @Override
@@ -1284,6 +1368,18 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             // Reset `loadUrlOnRestart.
             loadUrlOnRestart = false;
         }
+
+        //
+        if (restartFromBookmarksActivity) {
+            // Close the bookmarks drawer.
+            drawerLayout.closeDrawer(GravityCompat.END);
+
+            // Reload the bookmarks drawer.
+            loadBookmarksFolder();
+
+            // Reset `restartFromBookmarksActivity`.
+            restartFromBookmarksActivity = false;
+        }
     }
 
     // `onResume()` runs after `onStart()`, which runs after `onCreate()` and `onRestart()`.
@@ -1847,12 +1943,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 urlHistoryDialogFragment.show(getSupportFragmentManager(), getString(R.string.history));
                 break;
 
-            case R.id.bookmarks:
-                // Launch BookmarksActivity.
-                Intent bookmarksIntent = new Intent(this, BookmarksActivity.class);
-                startActivity(bookmarksIntent);
-                break;
-
             case R.id.downloads:
                 // Launch the system Download Manager.
                 Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
@@ -1863,22 +1953,22 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
                 startActivity(downloadManagerIntent);
                 break;
 
-            case R.id.settings:
+            case R.id.domains:
                 // Reset `currentDomainName` so that domain settings are reapplied after returning to `MainWebViewActivity`.
                 currentDomainName = "";
 
-                // Launch `SettingsActivity`.
-                Intent settingsIntent = new Intent(this, SettingsActivity.class);
-                startActivity(settingsIntent);
+                // Launch `DomainsActivity`.
+                Intent domainsIntent = new Intent(this, DomainsActivity.class);
+                startActivity(domainsIntent);
                 break;
 
-            case R.id.domains:
+            case R.id.settings:
                 // Reset `currentDomainName` so that domain settings are reapplied after returning to `MainWebViewActivity`.
                 currentDomainName = "";
 
-                // Launch `DomainsActivity`.
-                Intent domainsIntent = new Intent(this, DomainsActivity.class);
-                startActivity(domainsIntent);
+                // Launch `SettingsActivity`.
+                Intent settingsIntent = new Intent(this, SettingsActivity.class);
+                startActivity(settingsIntent);
                 break;
 
             case R.id.guide:
@@ -2224,6 +2314,82 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         }
     }
 
+    @Override
+    public void onCreateBookmark(AppCompatDialogFragment dialogFragment) {
+        // Get the `EditTexts` from the `dialogFragment`.
+        EditText createBookmarkNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.create_bookmark_name_edittext);
+        EditText createBookmarkUrlEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.create_bookmark_url_edittext);
+
+        // Extract the strings from the `EditTexts`.
+        String bookmarkNameString = createBookmarkNameEditText.getText().toString();
+        String bookmarkUrlString = createBookmarkUrlEditText.getText().toString();
+
+        // Convert the favoriteIcon Bitmap to a byte array.  `0` is for lossless compression (the only option for a PNG).
+        ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
+        favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream);
+        byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray();
+
+        // Display the new bookmark below the current items in the (0 indexed) list.
+        int newBookmarkDisplayOrder = bookmarksListView.getCount();
+
+        // Create the bookmark.
+        bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, newBookmarkDisplayOrder, currentBookmarksFolder, favoriteIconByteArray);
+
+        // Update `bookmarksCursor` with the current contents of this folder.
+        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
+
+        // Update the `ListView`.
+        bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+
+        // Scroll to the new bookmark.
+        bookmarksListView.setSelection(newBookmarkDisplayOrder);
+    }
+
+    @Override
+    public void onCreateBookmarkFolder(AppCompatDialogFragment dialogFragment) {
+        // Get handles for the views in `dialogFragment`.
+        EditText createFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.create_folder_name_edittext);
+        RadioButton defaultFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon_radiobutton);
+        ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon);
+
+        // Get new folder name string.
+        String folderNameString = createFolderNameEditText.getText().toString();
+
+        // Get the new folder icon `Bitmap`.
+        Bitmap folderIconBitmap;
+        if (defaultFolderIconRadioButton.isChecked()) {  // Use the default folder icon.
+            // Get the default folder icon and convert it to a `Bitmap`.
+            Drawable folderIconDrawable = folderIconImageView.getDrawable();
+            BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable;
+            folderIconBitmap = folderIconBitmapDrawable.getBitmap();
+        } else {  // Use the `WebView` favorite icon.
+            folderIconBitmap = favoriteIconBitmap;
+        }
+
+        // Convert `folderIconBitmap` to a byte array.  `0` is for lossless compression (the only option for a PNG).
+        ByteArrayOutputStream folderIconByteArrayOutputStream = new ByteArrayOutputStream();
+        folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, folderIconByteArrayOutputStream);
+        byte[] folderIconByteArray = folderIconByteArrayOutputStream.toByteArray();
+
+        // Move all the bookmarks down one in the display order.
+        for (int i = 0; i < bookmarksListView.getCount(); i++) {
+            int databaseId = (int) bookmarksListView.getItemIdAtPosition(i);
+            bookmarksDatabaseHelper.updateDisplayOrder(databaseId, i + 1);
+        }
+
+        // Create the folder, placing it at the top of the ListView
+        bookmarksDatabaseHelper.createFolder(folderNameString, 0, currentBookmarksFolder, folderIconByteArray);
+
+        // Update `bookmarksCursor` with the current contents of this folder.
+        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
+
+        // Update the `ListView`.
+        bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+
+        // Scroll to the new folder.
+        bookmarksListView.setSelection(0);
+    }
+
     @Override
     public void onCreateHomeScreenShortcut(AppCompatDialogFragment dialogFragment) {
         // Get shortcutNameEditText from the alert dialog.
@@ -2338,6 +2504,99 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         }
     }
 
+    @Override
+    public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
+        // Get handles for the views from `dialogFragment`.
+        EditText editBookmarkNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext);
+        EditText editBookmarkUrlEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext);
+        RadioButton currentBookmarkIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_current_icon_radiobutton);
+
+        // Store the bookmark strings.
+        String bookmarkNameString = editBookmarkNameEditText.getText().toString();
+        String bookmarkUrlString = editBookmarkUrlEditText.getText().toString();
+
+        // Update the bookmark.
+        if (currentBookmarkIconRadioButton.isChecked()) {  // Update the bookmark without changing the favorite icon.
+            bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString);
+        } else {  // Update the bookmark using the `WebView` favorite icon.
+            // Convert the favorite icon to a byte array.  `0` is for lossless compression (the only option for a PNG).
+            ByteArrayOutputStream newFavoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
+            favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, newFavoriteIconByteArrayOutputStream);
+            byte[] newFavoriteIconByteArray = newFavoriteIconByteArrayOutputStream.toByteArray();
+
+            //  Update the bookmark and the favorite icon.
+            bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString, newFavoriteIconByteArray);
+        }
+
+        // Update `bookmarksCursor` with the current contents of this folder.
+        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
+
+        // Update the `ListView`.
+        bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+    }
+
+    @Override
+    public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId) {
+        // Get handles for the views from `dialogFragment`.
+        EditText editFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext);
+        RadioButton currentFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton);
+        RadioButton defaultFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton);
+        ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon);
+
+        // Get the new folder name.
+        String newFolderNameString = editFolderNameEditText.getText().toString();
+
+        // Check if the favorite icon has changed.
+        if (currentFolderIconRadioButton.isChecked()) {  // Only the name has changed.
+            // Update the name in the database.
+            bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString);
+        } else if (!currentFolderIconRadioButton.isChecked() && newFolderNameString.equals(oldFolderNameString)) {  // Only the icon has changed.
+            // Get the new folder icon `Bitmap`.
+            Bitmap folderIconBitmap;
+            if (defaultFolderIconRadioButton.isChecked()) {
+                // Get the default folder icon and convert it to a `Bitmap`.
+                Drawable folderIconDrawable = folderIconImageView.getDrawable();
+                BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable;
+                folderIconBitmap = folderIconBitmapDrawable.getBitmap();
+            } else {  // Use the `WebView` favorite icon.
+                folderIconBitmap = favoriteIconBitmap;
+            }
+
+            // Convert the folder `Bitmap` to a byte array.  `0` is for lossless compression (the only option for a PNG).
+            ByteArrayOutputStream folderIconByteArrayOutputStream = new ByteArrayOutputStream();
+            folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, folderIconByteArrayOutputStream);
+            byte[] folderIconByteArray = folderIconByteArrayOutputStream.toByteArray();
+
+            // Update the folder icon in the database.
+            bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, folderIconByteArray);
+        } else {  // The folder icon and the name have changed.
+            // Get the new folder icon `Bitmap`.
+            Bitmap folderIconBitmap;
+            if (defaultFolderIconRadioButton.isChecked()) {
+                // Get the default folder icon and convert it to a `Bitmap`.
+                Drawable folderIconDrawable = folderIconImageView.getDrawable();
+                BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable;
+                folderIconBitmap = folderIconBitmapDrawable.getBitmap();
+            } else {  // Use the `WebView` favorite icon.
+                folderIconBitmap = MainWebViewActivity.favoriteIconBitmap;
+            }
+
+            // Convert the folder `Bitmap` to a byte array.  `0` is for lossless compression (the only option for a PNG).
+            ByteArrayOutputStream folderIconByteArrayOutputStream = new ByteArrayOutputStream();
+            folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, folderIconByteArrayOutputStream);
+            byte[] folderIconByteArray = folderIconByteArrayOutputStream.toByteArray();
+
+            // Update the folder name and icon in the database.
+            bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString, folderIconByteArray);
+        }
+
+        // Update `bookmarksCursor` with the current contents of this folder.
+        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
+
+        // Update the `ListView`.
+        bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+    }
+
     @Override
     public void onHttpAuthenticationCancel() {
         // Cancel the `HttpAuthHandler`.
@@ -3060,10 +3319,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
 
     private void loadBookmarksFolder() {
         // Update `bookmarksCursor` with the contents of the bookmarks database for the current folder.
-        Cursor bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
+        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
 
-        // Setup a `CursorAdapter`.  `this` specifies the `Context`.  `false` disables `autoRequery`.
-        CursorAdapter bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) {
+        // Populate the bookmarks cursor adapter.  `this` specifies the `Context`.  `false` disables `autoRequery`.
+        bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) {
             @Override
             public View newView(Context context, Cursor cursor, ViewGroup parent) {
                 // Inflate the individual item layout.  `false` does not attach it to the root.
index dfe6cbd8a1a861b66ffedac5bd36ceab0df878a3..7954478e623745ccf8d57885c26ca37eca861fad 100644 (file)
@@ -38,9 +38,9 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ImageView;
 
-import com.stoutner.privacybrowser.activities.BookmarksActivity;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
 import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
 
 public class CreateBookmarkFolderDialog extends AppCompatDialogFragment {
     // The public interface is used to send information back to the parent activity.
@@ -113,13 +113,17 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment {
         // The `AlertDialog` must be shown before items in the alert dialog can be modified.
         alertDialog.show();
 
-        // Get a handle for the create button.
+        // Get handles for the views in the dialog.
         final Button createButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
         EditText folderNameEditText = (EditText) alertDialog.findViewById(R.id.create_folder_name_edittext);
+        ImageView webPageIconImageView = (ImageView) alertDialog.findViewById(R.id.create_folder_web_page_icon);
 
         // Initially disable the create button.
         createButton.setEnabled(false);
 
+        // Initialize the database helper.  The two `nulls` do not specify the database name or a `CursorFactory`.  The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
+        final BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(getContext(), null, null, 0);
+
         // Enable the create button if the new folder name is unique.
         folderNameEditText.addTextChangedListener(new TextWatcher() {
             @Override
@@ -138,7 +142,7 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment {
                 String folderName = s.toString();
 
                 // Check if a folder with the name already exists.
-                Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(folderName);
+                Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(folderName);
 
                 // Enable the create button if the new folder name is not empty and doesn't already exist.
                 createButton.setEnabled(!folderName.isEmpty() && (folderExistsCursor.getCount() == 0));
@@ -163,7 +167,6 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment {
         });
 
         // Display the current favorite icon.
-        ImageView webPageIconImageView = (ImageView) alertDialog.findViewById(R.id.create_folder_web_page_icon);
         webPageIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap);
 
         // `onCreateDialog()` requires the return of an `AlertDialog`.
index ab3a8a3b0689c8e44c1160ed9aa15693c7de08b2..a25864ba048165f1fef5715637843732a7cfe5d7 100644 (file)
@@ -30,7 +30,7 @@ import android.graphics.BitmapFactory;
 import android.os.Bundle;
 import android.support.annotation.IdRes;
 import android.support.annotation.NonNull;
-// We have to use `AppCompatDialogFragment` instead of `DialogFragment` or an error is produced on API <=22.
+// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
 import android.support.v7.app.AppCompatDialogFragment;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -43,21 +43,28 @@ import android.widget.ImageView;
 import android.widget.RadioButton;
 import android.widget.RadioGroup;
 
-import com.stoutner.privacybrowser.activities.BookmarksActivity;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
 import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
 import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
 
 public class EditBookmarkDialog extends AppCompatDialogFragment {
     // The public interface is used to send information back to the parent activity.
     public interface EditBookmarkListener {
-        void onSaveEditBookmark(AppCompatDialogFragment dialogFragment);
+        void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId);
     }
 
-    // `editBookmarkListener` is used in `onAttach()` and `onCreateDialog()`
+    // Instantiate the class variables.
     private EditBookmarkListener editBookmarkListener;
+    private int selectedBookmarkDatabaseId;
+    private EditText nameEditText;
+    private EditText urlEditText;
+    private RadioButton newIconRadioButton;
+    private Button editButton;
+    private String currentName;
+    private String currentUrl;
 
     public void onAttach(Context context) {
+        // Run the default commands.
         super.onAttach(context);
 
         // Get a handle for `EditBookmarkListener` from `context`.
@@ -68,25 +75,41 @@ public class EditBookmarkDialog extends AppCompatDialogFragment {
         }
     }
 
-    // Instantiate the class variables.
-    EditText nameEditText;
-    EditText urlEditText;
-    RadioButton newIconRadioButton;
-    Button editButton;
-    String currentName;
-    String currentUrl;
+    // Store the database ID in the arguments bundle.
+    public static EditBookmarkDialog bookmarkDatabaseId(int databaseId) {
+        // Create a bundle.
+        Bundle bundle = new Bundle();
+
+        // Store the bookmark database ID in the bundle.
+        bundle.putInt("Database ID", databaseId);
+
+        // Add the bundle to the dialog.
+        EditBookmarkDialog editBookmarkDialog = new EditBookmarkDialog();
+        editBookmarkDialog.setArguments(bundle);
+
+        // Return the new dialog.
+        return editBookmarkDialog;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        // Run the default commands.
+        super.onCreate(savedInstanceState);
+
+        // Store the bookmark database ID in the class variable.
+        selectedBookmarkDatabaseId = getArguments().getInt("Database ID");
+    }
 
     // `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`.
     @SuppressLint("InflateParams")
     @Override
     @NonNull
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        // Get a long array with the the databaseId of the selected bookmark and convert it to an `int`.
-        long[] selectedBookmarkLongArray = BookmarksActivity.checkedItemIds;
-        int selectedBookmarkDatabaseId = (int) selectedBookmarkLongArray[0];
+        // Initialize the database helper.  The two `nulls` do not specify the database name or a `CursorFactory`.  The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
+        BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(getContext(), null, null, 0);
 
-        // Get a `Cursor` with the specified bookmark and move it to the first position.
-        Cursor bookmarkCursor = BookmarksActivity.bookmarksDatabaseHelper.getBookmarkCursor(selectedBookmarkDatabaseId);
+        // Get a `Cursor` with the selected bookmark and move it to the first position.
+        Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(selectedBookmarkDatabaseId);
         bookmarkCursor.moveToFirst();
 
         // Use `AlertDialog.Builder` to create the `AlertDialog`.
@@ -118,7 +141,7 @@ public class EditBookmarkDialog extends AppCompatDialogFragment {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 // Return the `DialogFragment` to the parent activity on save.
-                editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this);
+                editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
             }
         });
 
@@ -220,7 +243,7 @@ public class EditBookmarkDialog extends AppCompatDialogFragment {
                 // If the event is an `ACTION_DOWN` on the `enter` key, save the bookmark.
                 if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) {  // The enter key was pressed and the edit button is enabled.
                     // Trigger `onSaveEditBookmark()` and return the `DialogFragment` to the parent activity.
-                    editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this);
+                    editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
                     // Manually dismiss `alertDialog`.
                     alertDialog.dismiss();
                     // Consume the event.
@@ -237,7 +260,7 @@ public class EditBookmarkDialog extends AppCompatDialogFragment {
                 // If the event is a key-down on the `enter` button, select the PositiveButton `Save`.
                 if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) {  // The enter key was pressed and the edit button is enabled.
                     // Trigger `editBookmarkListener` and return the DialogFragment to the parent activity.
-                    editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this);
+                    editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
                     // Manually dismiss the `AlertDialog`.
                     alertDialog.dismiss();
                     // Consume the event.
index f702293445bef0d7c46f9df8c98b625005734b4d..4bd1a689c09d1a096aa110afe9e10493fb514d35 100644 (file)
@@ -30,7 +30,7 @@ import android.graphics.BitmapFactory;
 import android.os.Bundle;
 import android.support.annotation.IdRes;
 import android.support.annotation.NonNull;
-// We have to use `AppCompatDialogFragment` instead of `DialogFragment` or an error is produced on API <=22.
+// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
 import android.support.v7.app.AppCompatDialogFragment;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -43,21 +43,22 @@ import android.widget.ImageView;
 import android.widget.RadioButton;
 import android.widget.RadioGroup;
 
-import com.stoutner.privacybrowser.activities.BookmarksActivity;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
 import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
 import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
 
 public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
     // The public interface is used to send information back to the parent activity.
     public interface EditBookmarkFolderListener {
-        void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment);
+        void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId);
     }
 
-    // `editFolderListener` is used in `onAttach()` and `onCreateDialog`.
+    // Instantiate the class variables.
     private EditBookmarkFolderListener editBookmarkFolderListener;
+    private int selectedFolderDatabaseId;
 
     public void onAttach(Context context) {
+        // Run the default commands.
         super.onAttach(context);
 
         // Get a handle for `EditFolderListener` from `parentActivity`.
@@ -68,18 +69,42 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
         }
     }
 
+    // Store the database ID in the arguments bundle.
+    public static EditBookmarkFolderDialog folderDatabaseId(int databaseId) {
+        // Create a bundle
+        Bundle bundle = new Bundle();
+
+        // Store the folder database ID in the bundle.
+        bundle.putInt("Database ID", databaseId);
+
+        // Add the bundle to the dialog.
+        EditBookmarkFolderDialog editBookmarkFolderDialog = new EditBookmarkFolderDialog();
+        editBookmarkFolderDialog.setArguments(bundle);
+
+        // Return the new dialog.
+        return editBookmarkFolderDialog;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        // Run the default commands.
+        super.onCreate(savedInstanceState);
+
+        // Store the folder database ID in the class variable.
+        selectedFolderDatabaseId = getArguments().getInt("Database ID");
+    }
+
     // `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`.
     @SuppressLint("InflateParams")
     @Override
     @NonNull
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        // Get a long array with the the databaseId of the selected bookmark and convert it to an `int`.
-        long[] selectedBookmarkLongArray = BookmarksActivity.checkedItemIds;
-        int selectedBookmarkDatabaseId = (int) selectedBookmarkLongArray[0];
+        // Initialize the database helper.  The two `nulls` do not specify the database name or a `CursorFactory`.  The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
+        final BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(getContext(), null, null, 0);
 
-        // Get a `Cursor` with the specified bookmark and move it to the first position.
-        Cursor bookmarkCursor = BookmarksActivity.bookmarksDatabaseHelper.getBookmarkCursor(selectedBookmarkDatabaseId);
-        bookmarkCursor.moveToFirst();
+        // Get a `Cursor` with the selected folder and move it to the first position.
+        Cursor folderCursor = bookmarksDatabaseHelper.getBookmarkCursor(selectedFolderDatabaseId);
+        folderCursor.moveToFirst();
 
         // Use `AlertDialog.Builder` to create the `AlertDialog`.
         AlertDialog.Builder dialogBuilder;
@@ -110,11 +135,10 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 // Return the `DialogFragment` to the parent activity on save.
-                editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this);
+                editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this, selectedFolderDatabaseId);
             }
         });
 
-
         // Create an `AlertDialog` from the `AlertDialog.Builder`.
         final AlertDialog alertDialog = dialogBuilder.create();
 
@@ -136,7 +160,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
         editButton.setEnabled(false);
 
         // Get the current favorite icon byte array from the `Cursor`.
-        byte[] currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
+        byte[] currentIconByteArray = folderCursor.getBlob(folderCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
         // Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last.
         Bitmap currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.length);
         // Display `currentIconBitmap` in `edit_folder_current_icon`.
@@ -148,7 +172,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
         webPageFavoriteIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap);
 
         // Get the current folder name.
-        final String currentFolderName = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+        final String currentFolderName = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
         // Display the current folder name in `edit_folder_name_edittext`.
         final EditText folderNameEditText = (EditText) alertDialog.findViewById(R.id.edit_folder_name_edittext);
@@ -172,7 +196,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
                 String newFolderName = s.toString();
 
                 // Get a cursor for the new folder name if it exists.
-                Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(newFolderName);
+                Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName);
 
                 // Is the new folder name empty?
                 boolean folderNameEmpty = newFolderName.isEmpty();
@@ -199,7 +223,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
                 String newFolderName = folderNameEditText.getText().toString();
 
                 // Get a cursor for the new folder name if it exists.
-                Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(newFolderName);
+                Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName);
 
                 // Is the new folder name empty?
                 boolean folderNameEmpty = newFolderName.isEmpty();
@@ -224,9 +248,11 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment {
                 // If the event is a key-down on the "enter" button, select the PositiveButton `Save`.
                 if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) {  // The enter key was pressed and the edit button is enabled.
                     // Trigger `editBookmarkListener` and return the DialogFragment to the parent activity.
-                    editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this);
+                    editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this, selectedFolderDatabaseId);
+
                     // Manually dismiss the `AlertDialog`.
                     alertDialog.dismiss();
+
                     // Consume the event.
                     return true;
                 } else {  // If any other key was pressed, or if the edit button is currently disabled, do not consume the event.
index 35522154bf56b6e04e0e542dc02d568549b687ec..4c7a0f4ec84116e3dc6536a97c7b25c72e663058 100644 (file)
@@ -22,8 +22,6 @@ package com.stoutner.privacybrowser.fragments;
 import android.annotation.SuppressLint;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
@@ -53,21 +51,28 @@ import java.util.Date;
 public class AboutTabFragment extends Fragment {
     private int tabNumber;
 
-    // `AboutTabFragment.createTab` stores the tab number in the bundle arguments so it can be referenced from `onCreate()`.
+    // Store the tab number in the arguments bundle.
     public static AboutTabFragment createTab(int tab) {
-        Bundle thisTabArguments = new Bundle();
-        thisTabArguments.putInt("Tab", tab);
+        // Create a bundle.
+        Bundle bundle = new Bundle();
 
-        AboutTabFragment thisTab = new AboutTabFragment();
-        thisTab.setArguments(thisTabArguments);
-        return thisTab;
+        // Store the tab number in the bundle.
+        bundle.putInt("Tab", tab);
+
+        // Add the bundle to the fragment.
+        AboutTabFragment aboutTabFragment = new AboutTabFragment();
+        aboutTabFragment.setArguments(bundle);
+
+        // Return the new fragment.
+        return aboutTabFragment;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        // Run the default commands.
         super.onCreate(savedInstanceState);
 
-        // Store the tab number in `tabNumber`.
+        // Store the tab number in a class variable.
         tabNumber = getArguments().getInt("Tab");
     }
 
index 9e5f568d0d2d0af4ecf1c0c1a94efc96d55bb579..a89ced02132f5d58c6946d36930bfb3d5fb5fc54 100644 (file)
@@ -34,21 +34,28 @@ public class GuideTabFragment extends Fragment {
     // `tabNumber` is used in `onCreate()` and `onCreateView()`.
     private int tabNumber;
 
-    // GuideTabFragment.createTab stores the tab number in the bundle arguments so it can be referenced from onCreate().
+    // Store the tab number in the arguments bundle.
     public static GuideTabFragment createTab (int tab) {
-        Bundle thisTabArguments = new Bundle();
-        thisTabArguments.putInt("Tab", tab);
+        // Create a bundle.
+        Bundle bundle = new Bundle();
 
-        GuideTabFragment thisTab = new GuideTabFragment();
-        thisTab.setArguments(thisTabArguments);
-        return thisTab;
+        // Store the tab number in the bundle.
+        bundle.putInt("Tab", tab);
+
+        // Add the bundle to the fragment.
+        GuideTabFragment guideTabFragment = new GuideTabFragment();
+        guideTabFragment.setArguments(bundle);
+
+        // Return the new fragment.
+        return guideTabFragment;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        // Run the default commands.
         super.onCreate(savedInstanceState);
 
-        // Store the tab number in `tabNumber`.
+        // Store the tab number in a class variable.
         tabNumber = getArguments().getInt("Tab");
     }
 
index f01efad9f44d50e4490f88af26b3d0fd2d3147bf..a3f2b6591cb26838134183c9198821bb41e94651 100644 (file)
@@ -5,7 +5,7 @@
         android:viewportHeight="24.0"
         android:viewportWidth="24.0" >
 
-    <!-- We have to use a hard coded color until API >= 21.  Then we can use `@color`. -->
+    <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
     <path
         android:fillColor="#FF9E9E9E"
         android:pathData="M20,12c0,-1.1 0.9,-2 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2zM15.58,16.8L12,14.5l-3.58,2.3 1.08,-4.12 -3.29,-2.69 4.24,-0.25L12,5.8l1.54,3.95 4.24,0.25 -3.29,2.69 1.09,4.11z"/>
index d60cbcabb33aa53b421a298a16ed355ca7481458..d6f726917b7e7c7e9c81edc6e54405fbaa256143 100644 (file)
@@ -5,7 +5,7 @@
         android:viewportHeight="24.0"
         android:viewportWidth="24.0" >
 
-    <!-- We have to use a hard coded color until API >= 21.  Then we can use `@color`. -->
+    <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
     <path
         android:fillColor="#88000000"
         android:pathData="M20,12c0,-1.1 0.9,-2 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2zM15.58,16.8L12,14.5l-3.58,2.3 1.08,-4.12 -3.29,-2.69 4.24,-0.25L12,5.8l1.54,3.95 4.24,0.25 -3.29,2.69 1.09,4.11z"/>
index a75ee70855258058979c5a27daf6b3349a3c043a..92fc78d620bb2e5b2cbbb13b6fcb6a7f06cb0b15 100644 (file)
@@ -5,7 +5,7 @@
         android:viewportHeight="24.0"
         android:viewportWidth="24.0" >
 
-    <!-- We have to use a hard coded color until API >= 21.  Then we can use `@color`. -->
+    <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
     <path
         android:fillColor="#FF1E88E5"
         android:pathData="M20,12c0,-1.1 0.9,-2 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2zM15.58,16.8L12,14.5l-3.58,2.3 1.08,-4.12 -3.29,-2.69 4.24,-0.25L12,5.8l1.54,3.95 4.24,0.25 -3.29,2.69 1.09,4.11z"/>
index ca8ae425644b34b08d8bd284fcacab1dae1311b7..73639aa54e3fa6b9f0cb2e5d5053f7457becd31c 100644 (file)
@@ -5,7 +5,7 @@
         android:viewportHeight="24.0"
         android:viewportWidth="24.0" >
 
-    <!-- We have to use a hard coded color until API >= 21.  Then we can use `@color`. -->
+    <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
     <path
         android:fillColor="#FF1565C0"
         android:pathData="M20,12c0,-1.1 0.9,-2 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2zM15.58,16.8L12,14.5l-3.58,2.3 1.08,-4.12 -3.29,-2.69 4.24,-0.25L12,5.8l1.54,3.95 4.24,0.25 -3.29,2.69 1.09,4.11z"/>
diff --git a/app/src/main/res/drawable/bookmarks.xml b/app/src/main/res/drawable/bookmarks.xml
deleted file mode 100644 (file)
index d282560..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- `bookmarks.xml` comes from the Android Material icon set, where it is called `ic_bookmark_border`.  It is released under the Apache License 2.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" >
-
-    <!-- We have to use a hard coded color until API >= 21.  Then we can use `@color`. -->
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M17,3L7,3c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,5h10v13z"/>
-</vector>
diff --git a/app/src/main/res/drawable/bookmarks_dark.xml b/app/src/main/res/drawable/bookmarks_dark.xml
new file mode 100644 (file)
index 0000000..a29fe71
--- /dev/null
@@ -0,0 +1,13 @@
+<!-- `bookmarks_dark.xml` comes from the Android Material icon set, where it is called `ic_bookmark_border`.  It is released under the Apache License 2.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" >
+
+    <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
+    <path
+        android:fillColor="#FFE0E0E0"
+        android:pathData="M17,3L7,3c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,5h10v13z"/>
+</vector>
diff --git a/app/src/main/res/drawable/bookmarks_light.xml b/app/src/main/res/drawable/bookmarks_light.xml
new file mode 100644 (file)
index 0000000..7947562
--- /dev/null
@@ -0,0 +1,13 @@
+<!-- `bookmarks_light.xml` comes from the Android Material icon set, where it is called `ic_bookmark_border`.  It is released under the Apache License 2.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" >
+
+    <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17,3L7,3c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,5h10v13z"/>
+</vector>
index 6339a31007def730a315682f6e482444564f8626..5a52bcdcb59cb5a0cb44a57925a617e39dde3b1d 100644 (file)
                 android:dividerHeight="0dp" />
         </LinearLayout>
 
+        <android.support.design.widget.FloatingActionButton
+            android:id="@+id/launch_bookmarks_activity_fab"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="bottom|end"
+            android:layout_marginEnd="16dp"
+            android:layout_marginBottom="155dp" />
+
         <android.support.design.widget.FloatingActionButton
             android:id="@+id/create_bookmark_folder_fab"
             android:layout_height="wrap_content"
index 16bdf8f69ad3af80bbbd2c19dd25eda9758c1802..4063ba2c563c1b2f19bd4ff9d0c59d7a7f0d56ad 100644 (file)
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
     <group
         android:id="@+id/navigationGroup1" >
-        <item
-            android:id="@+id/bookmarks"
-            android:title="@string/bookmarks"
-            android:icon="@drawable/bookmarks"
-            android:orderInCategory="50" />
 
         <item
             android:id="@+id/downloads"
             android:title="@string/downloads"
             android:icon="@drawable/downloads"
+            android:orderInCategory="50" />
+
+        <item
+            android:id="@+id/domains"
+            android:title="@string/domains"
+            android:icon="@drawable/domains"
             android:orderInCategory="60" />
-    </group>
 
-    <!-- If a group has an id, a line is drawn above it in the navigation view. -->
-    <group
-        android:id="@+id/navigationGroup2" >
         <item
             android:id="@+id/settings"
             android:title="@string/settings"
             android:icon="@drawable/settings"
             android:orderInCategory="70" />
-
-        <item
-            android:id="@+id/domains"
-            android:title="@string/domains"
-            android:icon="@drawable/domains"
-            android:orderInCategory="80" />
     </group>
 
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
     <group
-        android:id="@+id/navigationGroup3" >
+        android:id="@+id/navigationGroup2" >
         <item
             android:id="@+id/guide"
             android:title="@string/guide"
             android:icon="@drawable/guide"
-            android:orderInCategory="90" />
+            android:orderInCategory="80" />
 
         <item
             android:id="@+id/about"
             android:title="@string/about"
             android:icon="@drawable/about"
-            android:orderInCategory="100" />
+            android:orderInCategory="90" />
     </group>
 
     <!-- If a group has an id, a line is drawn above it in the navigation view. -->
     <group
-        android:id="@+id/navigationGroup4" >
+        android:id="@+id/navigationGroup3" >
         <item
             android:id="@+id/clearAndExit"
             android:title="@string/clear_and_exit"
             android:icon="@drawable/clear_and_exit"
-            android:orderInCategory="110" />
+            android:orderInCategory="100" />
     </group>
 </menu>
\ No newline at end of file