/*
- * Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
*
* This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
*
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.preference.PreferenceManager;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.Menu;
import android.widget.RadioButton;
import android.widget.TextView;
+import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
+import androidx.preference.PreferenceManager;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
+import com.stoutner.privacybrowser.R;
import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog;
import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog;
import com.stoutner.privacybrowser.dialogs.EditBookmarkDialog;
import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDialog;
import com.stoutner.privacybrowser.dialogs.MoveToFolderDialog;
-import com.stoutner.privacybrowser.R;
import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
import java.io.ByteArrayOutputStream;
public class BookmarksActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, EditBookmarkDialog.EditBookmarkListener,
EditBookmarkFolderDialog.EditBookmarkFolderListener, MoveToFolderDialog.MoveToFolderListener {
- // `currentFolder` is public static so it can be accessed from `BookmarksDatabaseViewActivity`.
+ // Declare the public static variables, which are accessed from the bookmarks database view activity.
public static String currentFolder;
-
- // `restartFromBookmarksDatabaseViewActivity` is public static so it can be accessed from `BookmarksDatabaseViewActivity`. It is also used in `onRestart()`.
public static boolean restartFromBookmarksDatabaseViewActivity;
-
// Define the saved instance state constants.
private final String CHECKED_BOOKMARKS_ARRAY_LIST = "checked_bookmarks_array_list";
+ private final String CURRENT_FOLDER = "current_folder";
// 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()`.
+ // Declare the class variables.
private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+ private Snackbar bookmarksDeletedSnackbar;
+ private boolean closeActivityAfterDismissingSnackbar;
// `bookmarksListView` is used in `onCreate()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`,
// `updateMoveIcons()`, `scrollBookmarks()`, and `loadFolder()`.
// `oldFolderName` is used in `onCreate()` and `onSaveBookmarkFolder()`.
private String oldFolderNameString;
- // `bookmarksDeletedSnackbar` is used in `onCreate()`, `onOptionsItemSelected()`, and `onBackPressed()`.
- private Snackbar bookmarksDeletedSnackbar;
-
- // `closeActivityAfterDismissingSnackbar` is used in `onCreate()`, `onOptionsItemSelected()`, and `onBackPressed()`.
- private boolean closeActivityAfterDismissingSnackbar;
-
// The favorite icon byte array is populated in `onCreate()` and used in `onOptionsItemSelected()`.
private byte[] favoriteIconByteArray;
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
- // Set the theme.
- setTheme(R.style.PrivacyBrowser);
-
// Run the default commands.
super.onCreate(savedInstanceState);
// Display the home arrow on the app bar.
appBar.setDisplayHomeAsUpEnabled(true);
- // Initialize the database helper. `this` specifies the context. 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 = new BookmarksDatabaseHelper(this, null, null, 0);
+ // Control what the system back command does.
+ OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true) {
+ @Override
+ public void handleOnBackPressed() {
+ // Prepare to finish the activity.
+ prepareFinish();
+ }
+ };
- // Load the home folder.
- loadFolder();
+ // Register the on back pressed callback.
+ getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
+
+ // Initialize the database helper.
+ bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this);
// Set a listener so that tapping a list item loads the URL or folder.
bookmarksListView.setOnItemClickListener((parent, view, position, id) -> {
// 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");
+ mode.setSubtitle(getString(R.string.selected) + "1");
// Show the `Move Up`, `Move Down`, and `Edit` options.
moveBookmarkUpMenuItem.setVisible(true);
updateMoveIcons();
} else { // More than one bookmark is selected.
// List the number of selected bookmarks in the subtitle.
- mode.setSubtitle(getString(R.string.selected) + " " + numberOfSelectedBookmarks);
+ mode.setSubtitle(getString(R.string.selected) + numberOfSelectedBookmarks);
// Hide non-applicable `MenuItems`.
moveBookmarkUpMenuItem.setVisible(false);
boolean isFolder = (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
// Get the selected bookmark database ID.
- int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
+ int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID));
// Show the edit bookmark or edit bookmark folder dialog.
if (isFolder) {
bookmarksCursorAdapter.changeCursor(bookmarksCursor);
// Create a Snackbar with the number of deleted bookmarks.
- bookmarksDeletedSnackbar = Snackbar.make(findViewById(R.id.bookmarks_coordinatorlayout), getString(R.string.bookmarks_deleted) + " " + numberOfBookmarksToDelete,
+ bookmarksDeletedSnackbar = Snackbar.make(findViewById(R.id.bookmarks_coordinatorlayout), getString(R.string.bookmarks_deleted) + numberOfBookmarksToDelete,
Snackbar.LENGTH_LONG)
.setAction(R.string.undo, view -> {
// Do nothing because everything will be handled by `onDismissed()` below.
// Close the activity if back has been pressed.
if (closeActivityAfterDismissingSnackbar) {
- onBackPressed();
+ finish();
}
}
});
// Restore the state if the app has been restarted.
if (savedInstanceState != null) {
+ // Restore the current folder.
+ currentFolder = savedInstanceState.getString(CURRENT_FOLDER);
+
// 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);
- }
- }
+ // Check each previously checked bookmark in the list view.
+ if (checkedBookmarksArrayList != null)
+ checkedBookmarksArrayList.forEach((position) -> bookmarksListView.setItemChecked(position, true));
});
}
+
+ // Load the home folder.
+ loadFolder();
}
@Override
}
}
- // Store the checked items array list in the saved instance state.
+ // Store the variables in the saved instance state.
+ savedInstanceState.putString(CURRENT_FOLDER, currentFolder);
savedInstanceState.putIntegerArrayList(CHECKED_BOOKMARKS_ARRAY_LIST, checkedBookmarksArrayList);
}
// Run the command according to the selected option.
if (menuItemId == android.R.id.home) { // Home. The home arrow is identified as `android.R.id.home`, not just `R.id.home`.
if (currentFolder.isEmpty()) { // Currently in the home folder.
- // Run the back commands.
- onBackPressed();
+ // Prepare to finish the activity.
+ prepareFinish();
} else { // Currently in a subfolder.
// Place the former parent folder in `currentFolder`.
currentFolder = bookmarksDatabaseHelper.getParentFolderName(currentFolder);
return true;
}
- @Override
- public void onBackPressed() {
- // Check to see if a snackbar is currently displayed. If so, it must be closed before exiting so that a pending delete is completed before reloading the list view in the bookmarks drawer.
- if ((bookmarksDeletedSnackbar != null) && bookmarksDeletedSnackbar.isShown()) { // Close the bookmarks deleted snackbar before going home.
- // Set the close flag.
- closeActivityAfterDismissingSnackbar = true;
-
- // Dismiss the snackbar.
- bookmarksDeletedSnackbar.dismiss();
- } else { // Go home immediately.
- // Update the bookmarks folder for the bookmarks drawer in the main WebView activity.
- MainWebViewActivity.currentBookmarksFolder = currentFolder;
-
- // Close the bookmarks drawer and reload the bookmarks ListView when returning to the main WebView activity.
- MainWebViewActivity.restartFromBookmarksActivity = true;
-
- // Exit the bookmarks activity.
- super.onBackPressed();
- }
- }
-
@Override
public void onCreateBookmark(DialogFragment dialogFragment, Bitmap favoriteIconBitmap) {
// Get the alert dialog from the fragment.
folderCursor.moveToPosition(i);
// Get the database ID of the item.
- int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
+ int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID));
// If this is a folder, recursively count the contents first.
if (bookmarksDatabaseHelper.isFolder(itemDatabaseId)) {
folderCursor.moveToPosition(i);
// Get the database ID of the item.
- int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
+ int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID));
// If this is a folder, recursively delete the contents first.
if (bookmarksDatabaseHelper.isFolder(itemDatabaseId)) {
}
}
+ private void prepareFinish() {
+ // Check to see if a snackbar is currently displayed. If so, it must be closed before exiting so that a pending delete is completed before reloading the list view in the bookmarks drawer.
+ if ((bookmarksDeletedSnackbar != null) && bookmarksDeletedSnackbar.isShown()) { // Close the bookmarks deleted snackbar before going home.
+ // Set the close flag.
+ closeActivityAfterDismissingSnackbar = true;
+
+ // Dismiss the snackbar.
+ bookmarksDeletedSnackbar.dismiss();
+ } else { // Go home immediately.
+ // Update the bookmarks folder for the bookmarks drawer in the main WebView activity.
+ MainWebViewActivity.currentBookmarksFolder = currentFolder;
+
+ // Close the bookmarks drawer and reload the bookmarks ListView when returning to the main WebView activity.
+ MainWebViewActivity.restartFromBookmarksActivity = true;
+
+ // Exit the bookmarks activity.
+ finish();
+ }
+ }
+
private void updateMoveIcons() {
// Get a long array of the selected bookmarks.
long[] selectedBookmarksLongArray = bookmarksListView.getCheckedItemIds();
// Run the default commands.
super.onDestroy();
}
-}
\ No newline at end of file
+}