package com.stoutner.privacybrowser.activities;
import android.annotation.SuppressLint;
-import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar; // The AndroidX toolbar must be used until the minimum API is >= 21.
-import androidx.core.app.NavUtils;
+import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
public class BookmarksActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, EditBookmarkDialog.EditBookmarkListener,
EditBookmarkFolderDialog.EditBookmarkFolderListener, MoveToFolderDialog.MoveToFolderListener {
public static boolean restartFromBookmarksDatabaseViewActivity;
+ // Define the saved instance state constants.
+ private final String CHECKED_BOOKMARKS_ARRAY_LIST = "checked_bookmarks_array_list";
+
+ // Define the class menu items.
+ private MenuItem moveBookmarkUpMenuItem;
+ private MenuItem moveBookmarkDownMenuItem;
+
// `bookmarksDatabaseHelper` is used in `onCreate()`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`,
// `onMoveToFolder()`, `deleteBookmarkFolderContents()`, `loadFolder()`, and `onDestroy()`.
private BookmarksDatabaseHelper bookmarksDatabaseHelper;
// `oldFolderName` is used in `onCreate()` and `onSaveBookmarkFolder()`.
private String oldFolderNameString;
- // `moveBookmarkUpMenuItem` is used in `onCreate()` and `updateMoveIcons()`.
- private MenuItem moveBookmarkUpMenuItem;
-
- // `moveBookmarkDownMenuItem` is used in `onCreate()` and `updateMoveIcons()`.
- private MenuItem moveBookmarkDownMenuItem;
-
// `bookmarksDeletedSnackbar` is used in `onCreate()`, `onOptionsItemSelected()`, and `onBackPressed()`.
private Snackbar bookmarksDeletedSnackbar;
final Toolbar toolbar = findViewById(R.id.bookmarks_toolbar);
setSupportActionBar(toolbar);
- // Get a handle for the activity, the app bar, and the ListView.
- final Activity bookmarksActivity = this;
+ // Get handles for the views.
appBar = getSupportActionBar();
bookmarksListView = findViewById(R.id.bookmarks_listview);
// Set a listener so that tapping a list item loads the URL or folder.
bookmarksListView.setOnItemClickListener((parent, view, position, id) -> {
// Convert the id from long to int to match the format of the bookmarks database.
- int databaseID = (int) id;
+ int databaseId = (int) id;
- // Get the bookmark cursor for this ID and move it to the first row.
- Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseID);
+ // Get the bookmark cursor for this ID.
+ Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseId);
+
+ // Move the cursor to the first entry.
bookmarkCursor.moveToFirst();
// Act upon the bookmark according to the type.
// Load the new folder.
loadFolder();
} else { // The selected bookmark is not a folder.
- // Get the bookmark URL and assign it to `formattedUrlString`.
- MainWebViewActivity.urlToLoadOnRestart = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
-
- // Set `MainWebViewActivity` to load the new URL on restart.
- MainWebViewActivity.loadUrlOnRestart = true;
+ // Instantiate the edit bookmark dialog.
+ DialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId, favoriteIconBitmap);
- // 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);
+ // Make it so.
+ editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
}
- // Close the `Cursor`.
+ // Close the cursor.
bookmarkCursor.close();
});
// Get the number of selected bookmarks.
int numberOfSelectedBookmarks = bookmarksListView.getCheckedItemCount();
- // Adjust the ActionMode and the menu according to the number of selected bookmarks.
- if (numberOfSelectedBookmarks == 1) { // One bookmark is selected.
- // List the number of selected bookmarks in the subtitle.
- mode.setSubtitle(getString(R.string.selected) + " 1");
-
- // Show the `Move Up`, `Move Down`, and `Edit` options.
- moveBookmarkUpMenuItem.setVisible(true);
- moveBookmarkDownMenuItem.setVisible(true);
- editBookmarkMenuItem.setVisible(true);
-
- // Update the enabled status of the move icons.
- updateMoveIcons();
- } else { // More than one bookmark is selected.
- // List the number of selected bookmarks in the subtitle.
- mode.setSubtitle(getString(R.string.selected) + " " + numberOfSelectedBookmarks);
-
- // Hide non-applicable `MenuItems`.
- moveBookmarkUpMenuItem.setVisible(false);
- moveBookmarkDownMenuItem.setVisible(false);
- editBookmarkMenuItem.setVisible(false);
- }
+ // Only process commands if at least one bookmark is selected. Otherwise, a context menu with 0 selected bookmarks is briefly displayed.
+ if (numberOfSelectedBookmarks > 0) {
+ // Adjust the ActionMode and the menu according to the number of selected bookmarks.
+ if (numberOfSelectedBookmarks == 1) { // One bookmark is selected.
+ // List the number of selected bookmarks in the subtitle.
+ mode.setSubtitle(getString(R.string.selected) + " 1");
+
+ // Show the `Move Up`, `Move Down`, and `Edit` options.
+ moveBookmarkUpMenuItem.setVisible(true);
+ moveBookmarkDownMenuItem.setVisible(true);
+ editBookmarkMenuItem.setVisible(true);
- // Do not show the select all menu item if all the bookmarks are already checked.
- if (bookmarksListView.getCheckedItemCount() == bookmarksListView.getCount()) {
- selectAllBookmarksMenuItem.setVisible(false);
- } else {
- selectAllBookmarksMenuItem.setVisible(true);
+ // Update the enabled status of the move icons.
+ updateMoveIcons();
+ } else { // More than one bookmark is selected.
+ // List the number of selected bookmarks in the subtitle.
+ mode.setSubtitle(getString(R.string.selected) + " " + numberOfSelectedBookmarks);
+
+ // Hide non-applicable `MenuItems`.
+ moveBookmarkUpMenuItem.setVisible(false);
+ moveBookmarkDownMenuItem.setVisible(false);
+ editBookmarkMenuItem.setVisible(false);
+ }
+
+ // Do not show the select all menu item if all the bookmarks are already checked.
+ if (bookmarksListView.getCheckedItemCount() == bookmarksListView.getCount()) {
+ selectAllBookmarksMenuItem.setVisible(false);
+ } else {
+ selectAllBookmarksMenuItem.setVisible(true);
+ }
}
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- // Instantiate the common variables.
- int selectedBookmarkPosition;
+ // Declare the common variables.
int selectedBookmarkNewPosition;
final SparseBooleanArray selectedBookmarksPositionsSparseBooleanArray;
+ // Initialize the selected bookmark position.
+ int selectedBookmarkPosition = 0;
+
switch (item.getItemId()) {
case R.id.move_bookmark_up:
// Get the array of checked bookmark positions.
selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.getCheckedItemPositions();
- // Store the position of the selected bookmark. Only one bookmark is selected when `move_bookmark_up` is enabled.
- selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(0);
+ // Get the position of the bookmark that is selected. If other bookmarks have previously been selected they will be included in the sparse boolean array with a value of `false`.
+ for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
+ // Check to see if the value for the bookmark is true, meaning it is currently selected.
+ if (selectedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
+ // Only one bookmark should have a value of `true` when move bookmark up is enabled.
+ selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(i);
+ }
+ }
// Calculate the new position of the selected bookmark.
selectedBookmarkNewPosition = selectedBookmarkPosition - 1;
// Get the array of checked bookmark positions.
selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.getCheckedItemPositions();
- // Store the position of the selected bookmark. Only one bookmark is selected when `move_bookmark_down` is enabled.
- selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(0);
+ // Get the position of the bookmark that is selected. If other bookmarks have previously been selected they will be included in the sparse boolean array with a value of `false`.
+ for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
+ // Check to see if the value for the bookmark is true, meaning it is currently selected.
+ if (selectedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
+ // Only one bookmark should have a value of `true` when move bookmark down is enabled.
+ selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(i);
+ }
+ }
// Calculate the new position of the selected bookmark.
selectedBookmarkNewPosition = selectedBookmarkPosition + 1;
// Get the array of checked bookmark positions.
selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.getCheckedItemPositions();
- // Get the position of the selected bookmark. Only one bookmark is selected when `edit_bookmark_down` is enabled.
- selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(0);
+ // Get the position of the bookmark that is selected. If other bookmarks have previously been selected they will be included in the sparse boolean array with a value of `false`.
+ for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
+ // Check to see if the value for the bookmark is true, meaning it is currently selected.
+ if (selectedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
+ // Only one bookmark should have a value of `true` when move edit bookmark is enabled.
+ selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(i);
+ }
+ }
- // Move the `Cursor` to the selected position and find out if it is a folder.
+ // Move the cursor to the selected position.
bookmarksCursor.moveToPosition(selectedBookmarkPosition);
+
+ // Find out if this bookmark is a folder.
boolean isFolder = (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
// Get the selected bookmark database ID.
// Save the current folder name, which is used in `onSaveBookmarkFolder()`.
oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- // Show the edit bookmark folder dialog.
+ // Instantiate the edit bookmark folder dialog.
DialogFragment editFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, favoriteIconBitmap);
+
+ // Make it so.
editFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder));
} else {
- // Show the edit bookmark dialog.
+ // Instantiate the edit bookmark dialog.
DialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId, favoriteIconBitmap);
+
+ // Make it so.
editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
}
break;
// Display the create bookmark dialog.
createBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.create_bookmark));
});
+
+ // Restore the state if the app has been restarted.
+ if (savedInstanceState != null) {
+ // Update the bookmarks list view after it has loaded.
+ bookmarksListView.post(() -> {
+ // Get the checked bookmarks array list.
+ ArrayList<Integer> checkedBookmarksArrayList = savedInstanceState.getIntegerArrayList(CHECKED_BOOKMARKS_ARRAY_LIST);
+
+ // Check each previously checked bookmark in the list view. When the minimum API >= 24 a `forEach()` command can be used instead.
+ if (checkedBookmarksArrayList != null) {
+ for (int i = 0; i < checkedBookmarksArrayList.size(); i++) {
+ bookmarksListView.setItemChecked(checkedBookmarksArrayList.get(i), true);
+ }
+ }
+ });
+ }
}
@Override
}
}
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
+ // Run the default commands.
+ super.onSaveInstanceState(savedInstanceState);
+
+ // Get the array of the checked items.
+ SparseBooleanArray checkedBookmarksSparseBooleanArray = bookmarksListView.getCheckedItemPositions();
+
+ // Create a checked items array list.
+ ArrayList<Integer> checkedBookmarksArrayList = new ArrayList<>();
+
+ // Add each checked bookmark position to the array list.
+ for (int i = 0; i < checkedBookmarksSparseBooleanArray.size(); i++) {
+ // Check to see if the bookmark is currently checked. Bookmarks that have previously been checked but currently aren't will be populated in the sparse boolean array, but will return false.
+ if (checkedBookmarksSparseBooleanArray.valueAt(i)) {
+ // Add the bookmark position to the checked bookmarks array list.
+ checkedBookmarksArrayList.add(checkedBookmarksSparseBooleanArray.keyAt(i));
+ }
+ }
+
+ // Store the checked items array list in the saved instance state.
+ savedInstanceState.putIntegerArrayList(CHECKED_BOOKMARKS_ARRAY_LIST, checkedBookmarksArrayList);
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu.
}
@Override
- public void onSaveBookmark(DialogFragment dialogFragment, int selectedBookmarkDatabaseId, Bitmap favoriteIconBitmap) {
+ public void onSaveBookmark(DialogFragment dialogFragment, int selectedBookmarkDatabaseId, @NonNull Bitmap favoriteIconBitmap) {
// Get the dialog from the dialog fragment.
Dialog dialog = dialogFragment.getDialog();