]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Fix a crash on restart by a new intent. https://redmine.stoutner.com/issues/981
authorSoren Stoutner <soren@stoutner.com>
Thu, 23 Mar 2023 21:33:26 +0000 (14:33 -0700)
committerSoren Stoutner <soren@stoutner.com>
Thu, 23 Mar 2023 21:33:26 +0000 (14:33 -0700)
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/adapters/AboutPagerAdapter.kt
app/src/main/java/com/stoutner/privacybrowser/adapters/GuidePagerAdapter.kt
app/src/main/java/com/stoutner/privacybrowser/helpers/UrlHelper.kt

index 0560c017a0a78deb65ceba3e9bc952103b1bc7f5..11aa500d6138ec1693b0c8877334365216105612 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * 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>.
  *
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -166,456 +166,461 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
         // Initialize the database handler.
         bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this);
 
         // Initialize the database handler.
         bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this);
 
-        // Setup a matrix cursor for "All Folders" and "Home Folder".
+        // Create a matrix cursor column name string array.
         String[] matrixCursorColumnNames = {BookmarksDatabaseHelper.ID, BookmarksDatabaseHelper.BOOKMARK_NAME};
         String[] matrixCursorColumnNames = {BookmarksDatabaseHelper.ID, BookmarksDatabaseHelper.BOOKMARK_NAME};
-        MatrixCursor matrixCursor = new MatrixCursor(matrixCursorColumnNames);
-        matrixCursor.addRow(new Object[]{ALL_FOLDERS_DATABASE_ID, getString(R.string.all_folders)});
-        matrixCursor.addRow(new Object[]{HOME_FOLDER_DATABASE_ID, getString(R.string.home_folder)});
 
 
-        // Get a cursor with the list of all the folders.
-        Cursor foldersCursor = bookmarksDatabaseHelper.getAllFolders();
+        // Create the matrix cursor in a try-with-resources block so it is correctly closed when finished.
+        try (MatrixCursor matrixCursor = new MatrixCursor(matrixCursorColumnNames)) {
+            // Add "All Folders" and "Home Folder" to the matrix cursor.
+            matrixCursor.addRow(new Object[]{ALL_FOLDERS_DATABASE_ID, getString(R.string.all_folders)});
+            matrixCursor.addRow(new Object[]{HOME_FOLDER_DATABASE_ID, getString(R.string.home_folder)});
 
 
-        // Combine the matrix cursor and the folders cursor.
-        MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{matrixCursor, foldersCursor});
+            // Get a cursor with the list of all the folders.
+            Cursor foldersCursor = bookmarksDatabaseHelper.getAllFolders();
 
 
+            // Combine the matrix cursor and the folders cursor.
+            MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{matrixCursor, foldersCursor});
 
 
-        // Get the default folder bitmap.  `ContextCompat` must be used until the minimum API >= 21.
-        Drawable defaultFolderDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_blue_bitmap);
 
 
-        // Cast the default folder drawable to a bitmap drawable.
-        BitmapDrawable defaultFolderBitmapDrawable = (BitmapDrawable) defaultFolderDrawable;
+            // Get the default folder bitmap.  `ContextCompat` must be used until the minimum API >= 21.
+            Drawable defaultFolderDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_blue_bitmap);
 
 
-        // Remove the incorrect lint warning that `.getBitmap()` might be null.
-        assert defaultFolderBitmapDrawable != null;
+            // Cast the default folder drawable to a bitmap drawable.
+            BitmapDrawable defaultFolderBitmapDrawable = (BitmapDrawable) defaultFolderDrawable;
 
 
-        // Convert the default folder bitmap drawable to a bitmap.
-        Bitmap defaultFolderBitmap = defaultFolderBitmapDrawable.getBitmap();
+            // Remove the incorrect lint warning that `.getBitmap()` might be null.
+            assert defaultFolderBitmapDrawable != null;
 
 
+            // Convert the default folder bitmap drawable to a bitmap.
+            Bitmap defaultFolderBitmap = defaultFolderBitmapDrawable.getBitmap();
 
 
-        // Create a resource cursor adapter for the spinner.
-        ResourceCursorAdapter foldersCursorAdapter = new ResourceCursorAdapter(this, R.layout.appbar_spinner_item, foldersMergeCursor, 0) {
-            @Override
-            public void bindView(View view, Context context, Cursor cursor) {
-                // Get handles for the spinner views.
-                ImageView spinnerItemImageView = view.findViewById(R.id.spinner_item_imageview);
-                TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
 
 
-                // Set the folder icon according to the type.
-                if (foldersMergeCursor.getPosition() > 1) {  // Set a user folder icon.
-                    // Initialize a default folder icon byte array output stream.
-                    ByteArrayOutputStream defaultFolderIconByteArrayOutputStream = new ByteArrayOutputStream();
+            // Create a resource cursor adapter for the spinner.
+            ResourceCursorAdapter foldersCursorAdapter = new ResourceCursorAdapter(this, R.layout.appbar_spinner_item, foldersMergeCursor, 0) {
+                @Override
+                public void bindView(View view, Context context, Cursor cursor) {
+                    // Get handles for the spinner views.
+                    ImageView spinnerItemImageView = view.findViewById(R.id.spinner_item_imageview);
+                    TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
+
+                    // Set the folder icon according to the type.
+                    if (foldersMergeCursor.getPosition() > 1) {  // Set a user folder icon.
+                        // Initialize a default folder icon byte array output stream.
+                        ByteArrayOutputStream defaultFolderIconByteArrayOutputStream = new ByteArrayOutputStream();
 
 
-                    // Covert the default folder bitmap to a PNG and store it in the output stream.  `0` is for lossless compression (the only option for a PNG).
-                    defaultFolderBitmap.compress(Bitmap.CompressFormat.PNG, 0, defaultFolderIconByteArrayOutputStream);
+                        // Covert the default folder bitmap to a PNG and store it in the output stream.  `0` is for lossless compression (the only option for a PNG).
+                        defaultFolderBitmap.compress(Bitmap.CompressFormat.PNG, 0, defaultFolderIconByteArrayOutputStream);
 
 
-                    // Convert the default folder icon output stream to a byte array.
-                    byte[] defaultFolderIconByteArray = defaultFolderIconByteArrayOutputStream.toByteArray();
+                        // Convert the default folder icon output stream to a byte array.
+                        byte[] defaultFolderIconByteArray = defaultFolderIconByteArrayOutputStream.toByteArray();
 
 
 
 
-                    // Get the folder icon byte array from the cursor.
-                    byte[] folderIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
+                        // Get the folder icon byte array from the cursor.
+                        byte[] folderIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
 
 
-                    // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
-                    Bitmap folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.length);
+                        // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
+                        Bitmap folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.length);
 
 
 
 
-                    // Set the icon according to the type.
-                    if (Arrays.equals(folderIconByteArray, defaultFolderIconByteArray)) {  // The default folder icon is used.
-                        // Set a smaller and darker folder icon, which works well with the spinner.
-                        spinnerItemImageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.folder_dark_blue));
-                    } else {  // A custom folder icon is uses.
-                        // Set the folder image stored in the cursor.
-                        spinnerItemImageView.setImageBitmap(folderIconBitmap);
+                        // Set the icon according to the type.
+                        if (Arrays.equals(folderIconByteArray, defaultFolderIconByteArray)) {  // The default folder icon is used.
+                            // Set a smaller and darker folder icon, which works well with the spinner.
+                            spinnerItemImageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.folder_dark_blue));
+                        } else {  // A custom folder icon is uses.
+                            // Set the folder image stored in the cursor.
+                            spinnerItemImageView.setImageBitmap(folderIconBitmap);
+                        }
+                    } else {  // Set the `All Folders` or `Home Folder` icon.
+                        // Set the gray folder image.  `ContextCompat` must be used until the minimum API >= 21.
+                        spinnerItemImageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.folder_gray));
                     }
                     }
-                } else {  // Set the `All Folders` or `Home Folder` icon.
-                    // Set the gray folder image.  `ContextCompat` must be used until the minimum API >= 21.
-                    spinnerItemImageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.folder_gray));
-                }
 
 
-                // Set the text view to display the folder name.
-                spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME)));
-            }
-        };
+                    // Set the text view to display the folder name.
+                    spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+                }
+            };
 
 
-        // Set the resource cursor adapter drop drown view resource.
-        foldersCursorAdapter.setDropDownViewResource(R.layout.appbar_spinner_dropdown_item);
+            // Set the resource cursor adapter drop drown view resource.
+            foldersCursorAdapter.setDropDownViewResource(R.layout.appbar_spinner_dropdown_item);
 
 
-        // Get a handle for the folder spinner and set the adapter.
-        Spinner folderSpinner = findViewById(R.id.spinner);
-        folderSpinner.setAdapter(foldersCursorAdapter);
+            // Get a handle for the folder spinner and set the adapter.
+            Spinner folderSpinner = findViewById(R.id.spinner);
+            folderSpinner.setAdapter(foldersCursorAdapter);
 
 
-        // Wait to set the on item selected listener until the spinner has been inflated.  Otherwise the activity will crash on restart.
-        folderSpinner.post(() -> {
-            // Handle taps on the spinner dropdown.
-            folderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
-                @Override
-                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                    // Store the current folder database ID.
-                    currentFolderDatabaseId = (int) id;
+            // Wait to set the on item selected listener until the spinner has been inflated.  Otherwise the activity will crash on restart.
+            folderSpinner.post(() -> {
+                // Handle taps on the spinner dropdown.
+                folderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+                    @Override
+                    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                        // Store the current folder database ID.
+                        currentFolderDatabaseId = (int) id;
 
 
-                    // Get a handle for the selected view.
-                    TextView selectedFolderTextView = findViewById(R.id.spinner_item_textview);
+                        // Get a handle for the selected view.
+                        TextView selectedFolderTextView = findViewById(R.id.spinner_item_textview);
 
 
-                    // Store the current folder name.
-                    currentFolderName = selectedFolderTextView.getText().toString();
+                        // Store the current folder name.
+                        currentFolderName = selectedFolderTextView.getText().toString();
 
 
-                    // Update the list view.
-                    updateBookmarksListView();
-                }
+                        // Update the list view.
+                        updateBookmarksListView();
+                    }
 
 
-                @Override
-                public void onNothingSelected(AdapterView<?> parent) {
-                    // Do nothing.
-                }
+                    @Override
+                    public void onNothingSelected(AdapterView<?> parent) {
+                        // Do nothing.
+                    }
+                });
             });
             });
-        });
 
 
 
 
-        // Get a handle for the bookmarks listview.
-        ListView bookmarksListView = findViewById(R.id.bookmarks_databaseview_listview);
+            // Get a handle for the bookmarks listview.
+            ListView bookmarksListView = findViewById(R.id.bookmarks_databaseview_listview);
 
 
-        // Check to see if the activity was restarted.
-        if (savedInstanceState == null) {  // The activity was not restarted.
-            // Set the default current folder database ID.
-            currentFolderDatabaseId = ALL_FOLDERS_DATABASE_ID;
-        } else {  // The activity was restarted.
-            // Restore the class variables from the saved instance state.
-            currentFolderDatabaseId = savedInstanceState.getInt(CURRENT_FOLDER_DATABASE_ID);
-            currentFolderName = savedInstanceState.getString(CURRENT_FOLDER_NAME);
-            sortByDisplayOrder = savedInstanceState.getBoolean(SORT_BY_DISPLAY_ORDER);
-
-            // Update the spinner if the home folder is selected.  Android handles this by default for the main cursor but not the matrix cursor.
-            if (currentFolderDatabaseId == HOME_FOLDER_DATABASE_ID) {
-                folderSpinner.setSelection(1);
+            // Check to see if the activity was restarted.
+            if (savedInstanceState == null) {  // The activity was not restarted.
+                // Set the default current folder database ID.
+                currentFolderDatabaseId = ALL_FOLDERS_DATABASE_ID;
+            } else {  // The activity was restarted.
+                // Restore the class variables from the saved instance state.
+                currentFolderDatabaseId = savedInstanceState.getInt(CURRENT_FOLDER_DATABASE_ID);
+                currentFolderName = savedInstanceState.getString(CURRENT_FOLDER_NAME);
+                sortByDisplayOrder = savedInstanceState.getBoolean(SORT_BY_DISPLAY_ORDER);
+
+                // Update the spinner if the home folder is selected.  Android handles this by default for the main cursor but not the matrix cursor.
+                if (currentFolderDatabaseId == HOME_FOLDER_DATABASE_ID) {
+                    folderSpinner.setSelection(1);
+                }
             }
             }
-        }
-
-        // Update the bookmarks listview.
-        updateBookmarksListView();
 
 
-        // Setup a `CursorAdapter` with `this` 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.
-                return getLayoutInflater().inflate(R.layout.bookmarks_databaseview_item_linearlayout, parent, false);
-            }
+            // Update the bookmarks listview.
+            updateBookmarksListView();
 
 
-            @Override
-            public void bindView(View view, Context context, Cursor cursor) {
-                boolean isFolder = (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
-
-                // Get the database ID from the `Cursor` and display it in `bookmarkDatabaseIdTextView`.
-                int bookmarkDatabaseId = cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID));
-                TextView bookmarkDatabaseIdTextView = view.findViewById(R.id.bookmarks_databaseview_database_id);
-                bookmarkDatabaseIdTextView.setText(String.valueOf(bookmarkDatabaseId));
-
-                // Get the favorite icon byte array from the `Cursor`.
-                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
-                // Convert the byte array to a `Bitmap` beginning at the beginning at the first byte and ending at the last.
-                Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
-                // Display the bitmap in `bookmarkFavoriteIcon`.
-                ImageView bookmarkFavoriteIcon = view.findViewById(R.id.bookmarks_databaseview_favorite_icon);
-                bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
-
-                // Get the bookmark name from the `Cursor` and display it in `bookmarkNameTextView`.
-                String bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
-                TextView bookmarkNameTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_name);
-                bookmarkNameTextView.setText(bookmarkNameString);
-
-                // Make the font bold for folders.
-                if (isFolder) {
-                    // The first argument is `null` prevent changing of the font.
-                    bookmarkNameTextView.setTypeface(null, Typeface.BOLD);
-                } else {  // Reset the font to default.
-                    bookmarkNameTextView.setTypeface(Typeface.DEFAULT);
+            // Setup a `CursorAdapter` with `this` 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.
+                    return getLayoutInflater().inflate(R.layout.bookmarks_databaseview_item_linearlayout, parent, false);
                 }
 
                 }
 
-                // Get the bookmark URL form the `Cursor` and display it in `bookmarkUrlTextView`.
-                String bookmarkUrlString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL));
-                TextView bookmarkUrlTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_url);
-                bookmarkUrlTextView.setText(bookmarkUrlString);
-
-                // Hide the URL if the bookmark is a folder.
-                if (isFolder) {
-                    bookmarkUrlTextView.setVisibility(View.GONE);
-                } else {
-                    bookmarkUrlTextView.setVisibility(View.VISIBLE);
-                }
+                @Override
+                public void bindView(View view, Context context, Cursor cursor) {
+                    boolean isFolder = (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
+
+                    // Get the database ID from the `Cursor` and display it in `bookmarkDatabaseIdTextView`.
+                    int bookmarkDatabaseId = cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID));
+                    TextView bookmarkDatabaseIdTextView = view.findViewById(R.id.bookmarks_databaseview_database_id);
+                    bookmarkDatabaseIdTextView.setText(String.valueOf(bookmarkDatabaseId));
+
+                    // Get the favorite icon byte array from the `Cursor`.
+                    byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
+                    // Convert the byte array to a `Bitmap` beginning at the beginning at the first byte and ending at the last.
+                    Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
+                    // Display the bitmap in `bookmarkFavoriteIcon`.
+                    ImageView bookmarkFavoriteIcon = view.findViewById(R.id.bookmarks_databaseview_favorite_icon);
+                    bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
+
+                    // Get the bookmark name from the `Cursor` and display it in `bookmarkNameTextView`.
+                    String bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                    TextView bookmarkNameTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_name);
+                    bookmarkNameTextView.setText(bookmarkNameString);
+
+                    // Make the font bold for folders.
+                    if (isFolder) {
+                        // The first argument is `null` prevent changing of the font.
+                        bookmarkNameTextView.setTypeface(null, Typeface.BOLD);
+                    } else {  // Reset the font to default.
+                        bookmarkNameTextView.setTypeface(Typeface.DEFAULT);
+                    }
 
 
-                // Get the display order from the `Cursor` and display it in `bookmarkDisplayOrderTextView`.
-                int bookmarkDisplayOrder = cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER));
-                TextView bookmarkDisplayOrderTextView = view.findViewById(R.id.bookmarks_databaseview_display_order);
-                bookmarkDisplayOrderTextView.setText(String.valueOf(bookmarkDisplayOrder));
-
-                // Get the parent folder from the `Cursor` and display it in `bookmarkParentFolder`.
-                String bookmarkParentFolder = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER));
-                ImageView parentFolderImageView = view.findViewById(R.id.bookmarks_databaseview_parent_folder_icon);
-                TextView bookmarkParentFolderTextView = view.findViewById(R.id.bookmarks_databaseview_parent_folder);
-
-                // Make the folder name gray if it is the home folder.
-                if (bookmarkParentFolder.isEmpty()) {
-                    parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_gray));
-                    bookmarkParentFolderTextView.setText(R.string.home_folder);
-                    bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.gray_500));
-                } else {
-                    parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_dark_blue));
-                    bookmarkParentFolderTextView.setText(bookmarkParentFolder);
+                    // Get the bookmark URL form the `Cursor` and display it in `bookmarkUrlTextView`.
+                    String bookmarkUrlString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL));
+                    TextView bookmarkUrlTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_url);
+                    bookmarkUrlTextView.setText(bookmarkUrlString);
 
 
-                    // Get the current theme status.
-                    int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+                    // Hide the URL if the bookmark is a folder.
+                    if (isFolder) {
+                        bookmarkUrlTextView.setVisibility(View.GONE);
+                    } else {
+                        bookmarkUrlTextView.setVisibility(View.VISIBLE);
+                    }
 
 
-                    // Set the text color according to the theme.
-                    if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
-                        // This color is a little darker than the default night mode text.  But the effect is rather nice.
-                        bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.gray_300));
+                    // Get the display order from the `Cursor` and display it in `bookmarkDisplayOrderTextView`.
+                    int bookmarkDisplayOrder = cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER));
+                    TextView bookmarkDisplayOrderTextView = view.findViewById(R.id.bookmarks_databaseview_display_order);
+                    bookmarkDisplayOrderTextView.setText(String.valueOf(bookmarkDisplayOrder));
+
+                    // Get the parent folder from the `Cursor` and display it in `bookmarkParentFolder`.
+                    String bookmarkParentFolder = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER));
+                    ImageView parentFolderImageView = view.findViewById(R.id.bookmarks_databaseview_parent_folder_icon);
+                    TextView bookmarkParentFolderTextView = view.findViewById(R.id.bookmarks_databaseview_parent_folder);
+
+                    // Make the folder name gray if it is the home folder.
+                    if (bookmarkParentFolder.isEmpty()) {
+                        parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_gray));
+                        bookmarkParentFolderTextView.setText(R.string.home_folder);
+                        bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.gray_500));
                     } else {
                     } else {
-                        bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black));
+                        parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_dark_blue));
+                        bookmarkParentFolderTextView.setText(bookmarkParentFolder);
+
+                        // Get the current theme status.
+                        int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+
+                        // Set the text color according to the theme.
+                        if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
+                            // This color is a little darker than the default night mode text.  But the effect is rather nice.
+                            bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.gray_300));
+                        } else {
+                            bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black));
+                        }
                     }
                 }
                     }
                 }
-            }
-        };
+            };
 
 
-        // Update the ListView.
-        bookmarksListView.setAdapter(bookmarksCursorAdapter);
-
-        // Set a listener to edit a bookmark when it is tapped.
-        bookmarksListView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
-            // Convert the database ID to an int.
-            int databaseId = (int) id;
-
-            // Show the edit bookmark or edit bookmark folder dialog.
-            if (bookmarksDatabaseHelper.isFolder(databaseId)) {
-                // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
-                oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
-
-                // Show the edit bookmark folder dialog.
-                DialogFragment editBookmarkFolderDatabaseViewDialog = EditBookmarkFolderDatabaseViewDialog.folderDatabaseId(databaseId, favoriteIconBitmap);
-                editBookmarkFolderDatabaseViewDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder));
-            } else {
-                // Show the edit bookmark dialog.
-                DialogFragment editBookmarkDatabaseViewDialog = EditBookmarkDatabaseViewDialog.bookmarkDatabaseId(databaseId, favoriteIconBitmap);
-                editBookmarkDatabaseViewDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
-            }
-        });
 
 
-        // Handle long presses on the list view.
-        bookmarksListView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
-            // Instantiate the common variables.
-            MenuItem selectAllMenuItem;
-            MenuItem deleteMenuItem;
-            boolean deletingBookmarks;
+            // Update the ListView.
+            bookmarksListView.setAdapter(bookmarksCursorAdapter);
 
 
-            @Override
-            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-                // Inflate the menu for the contextual app bar.
-                getMenuInflater().inflate(R.menu.bookmarks_databaseview_context_menu, menu);
+            // Set a listener to edit a bookmark when it is tapped.
+            bookmarksListView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
+                // Convert the database ID to an int.
+                int databaseId = (int) id;
 
 
-                // Set the title.
-                mode.setTitle(R.string.bookmarks);
+                // Show the edit bookmark or edit bookmark folder dialog.
+                if (bookmarksDatabaseHelper.isFolder(databaseId)) {
+                    // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
+                    oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
 
-                // Get handles for the menu items.
-                selectAllMenuItem = menu.findItem(R.id.select_all);
-                deleteMenuItem = menu.findItem(R.id.delete);
+                    // Show the edit bookmark folder dialog.
+                    DialogFragment editBookmarkFolderDatabaseViewDialog = EditBookmarkFolderDatabaseViewDialog.folderDatabaseId(databaseId, favoriteIconBitmap);
+                    editBookmarkFolderDatabaseViewDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder));
+                } else {
+                    // Show the edit bookmark dialog.
+                    DialogFragment editBookmarkDatabaseViewDialog = EditBookmarkDatabaseViewDialog.bookmarkDatabaseId(databaseId, favoriteIconBitmap);
+                    editBookmarkDatabaseViewDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
+                }
+            });
 
 
-                // Disable the delete menu item if a delete is pending.
-                deleteMenuItem.setEnabled(!deletingBookmarks);
+            // Handle long presses on the list view.
+            bookmarksListView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
+                // Instantiate the common variables.
+                MenuItem selectAllMenuItem;
+                MenuItem deleteMenuItem;
+                boolean deletingBookmarks;
 
 
-                // Get the number of currently selected bookmarks.
-                int numberOfSelectedBookmarks = bookmarksListView.getCheckedItemCount();
+                @Override
+                public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+                    // Inflate the menu for the contextual app bar.
+                    getMenuInflater().inflate(R.menu.bookmarks_databaseview_context_menu, menu);
 
 
-                // Set the action mode subtitle according to the number of selected bookmarks.  This must be set here or it will be missing if the activity is restarted.
-                mode.setSubtitle(getString(R.string.selected) + "  " + numberOfSelectedBookmarks);
+                    // Set the title.
+                    mode.setTitle(R.string.bookmarks);
 
 
-                // Do not show the select all menu item if all the bookmarks are already checked.
-                if (bookmarksListView.getCheckedItemCount() == bookmarksListView.getCount()) {
-                    selectAllMenuItem.setVisible(false);
-                }
+                    // Get handles for the menu items.
+                    selectAllMenuItem = menu.findItem(R.id.select_all);
+                    deleteMenuItem = menu.findItem(R.id.delete);
 
 
-                // Make it so.
-                return true;
-            }
+                    // Disable the delete menu item if a delete is pending.
+                    deleteMenuItem.setEnabled(!deletingBookmarks);
 
 
-            @Override
-            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-                // Do nothing.
-                return false;
-            }
+                    // Get the number of currently selected bookmarks.
+                    int numberOfSelectedBookmarks = bookmarksListView.getCheckedItemCount();
 
 
-            @Override
-            public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
-                // Calculate the number of selected bookmarks.
-                int numberOfSelectedBookmarks = bookmarksListView.getCheckedItemCount();
-
-                // Only run the commands if at least one bookmark is selected.  Otherwise, a context menu with 0 selected bookmarks is briefly displayed.
-                if (numberOfSelectedBookmarks > 0) {
-                    // Update the action mode subtitle according to the number of selected bookmarks.
+                    // Set the action mode subtitle according to the number of selected bookmarks.  This must be set here or it will be missing if the activity is restarted.
                     mode.setSubtitle(getString(R.string.selected) + "  " + numberOfSelectedBookmarks);
 
                     mode.setSubtitle(getString(R.string.selected) + "  " + numberOfSelectedBookmarks);
 
-                    // Only show the select all menu item if all of the bookmarks are not already selected.
-                    selectAllMenuItem.setVisible(bookmarksListView.getCheckedItemCount() != bookmarksListView.getCount());
+                    // Do not show the select all menu item if all the bookmarks are already checked.
+                    if (bookmarksListView.getCheckedItemCount() == bookmarksListView.getCount()) {
+                        selectAllMenuItem.setVisible(false);
+                    }
 
 
-                    // Convert the database ID to an int.
-                    int databaseId = (int) id;
+                    // Make it so.
+                    return true;
+                }
 
 
-                    // If a folder was selected, also select all the contents.
-                    if (checked && bookmarksDatabaseHelper.isFolder(databaseId)) {
-                        selectAllBookmarksInFolder(databaseId);
-                    }
+                @Override
+                public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+                    // Do nothing.
+                    return false;
+                }
+
+                @Override
+                public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+                    // Calculate the number of selected bookmarks.
+                    int numberOfSelectedBookmarks = bookmarksListView.getCheckedItemCount();
+
+                    // Only run the commands if at least one bookmark is selected.  Otherwise, a context menu with 0 selected bookmarks is briefly displayed.
+                    if (numberOfSelectedBookmarks > 0) {
+                        // Update the action mode subtitle according to the number of selected bookmarks.
+                        mode.setSubtitle(getString(R.string.selected) + "  " + numberOfSelectedBookmarks);
 
 
-                    // Do not allow a bookmark to be deselected if the folder is selected.
-                    if (!checked) {
-                        // Get the folder name.
-                        String folderName = bookmarksDatabaseHelper.getParentFolderName((int) id);
+                        // Only show the select all menu item if all of the bookmarks are not already selected.
+                        selectAllMenuItem.setVisible(bookmarksListView.getCheckedItemCount() != bookmarksListView.getCount());
 
 
-                        // If the bookmark is not in the root folder, check to see if the folder is selected.
-                        if (!folderName.isEmpty()) {
-                            // Get the database ID of the folder.
-                            int folderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(folderName);
+                        // Convert the database ID to an int.
+                        int databaseId = (int) id;
 
 
-                            // Move the bookmarks cursor to the first position.
-                            bookmarksCursor.moveToFirst();
+                        // If a folder was selected, also select all the contents.
+                        if (checked && bookmarksDatabaseHelper.isFolder(databaseId)) {
+                            selectAllBookmarksInFolder(databaseId);
+                        }
 
 
-                            // Initialize the folder position variable.
-                            int folderPosition = -1;
+                        // Do not allow a bookmark to be deselected if the folder is selected.
+                        if (!checked) {
+                            // Get the folder name.
+                            String folderName = bookmarksDatabaseHelper.getParentFolderName((int) id);
 
 
-                            // Get the position of the folder in the bookmarks cursor.
-                            while ((folderPosition < 0) && (bookmarksCursor.getPosition() < bookmarksCursor.getCount())) {
-                                // Check if the folder database ID matches the bookmark database ID.
-                                if (folderDatabaseId == bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID))) {
-                                    // Get the folder position.
-                                    folderPosition = bookmarksCursor.getPosition();
+                            // If the bookmark is not in the root folder, check to see if the folder is selected.
+                            if (!folderName.isEmpty()) {
+                                // Get the database ID of the folder.
+                                int folderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(folderName);
 
 
-                                    // Check if the folder is selected.
-                                    if (bookmarksListView.isItemChecked(folderPosition)) {
-                                        // Reselect the bookmark.
-                                        bookmarksListView.setItemChecked(position, true);
+                                // Move the bookmarks cursor to the first position.
+                                bookmarksCursor.moveToFirst();
 
 
-                                        // Display a snackbar explaining why the bookmark cannot be deselected.
-                                        Snackbar.make(bookmarksListView, R.string.cannot_deselect_bookmark, Snackbar.LENGTH_LONG).show();
+                                // Initialize the folder position variable.
+                                int folderPosition = -1;
+
+                                // Get the position of the folder in the bookmarks cursor.
+                                while ((folderPosition < 0) && (bookmarksCursor.getPosition() < bookmarksCursor.getCount())) {
+                                    // Check if the folder database ID matches the bookmark database ID.
+                                    if (folderDatabaseId == bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID))) {
+                                        // Get the folder position.
+                                        folderPosition = bookmarksCursor.getPosition();
+
+                                        // Check if the folder is selected.
+                                        if (bookmarksListView.isItemChecked(folderPosition)) {
+                                            // Reselect the bookmark.
+                                            bookmarksListView.setItemChecked(position, true);
+
+                                            // Display a snackbar explaining why the bookmark cannot be deselected.
+                                            Snackbar.make(bookmarksListView, R.string.cannot_deselect_bookmark, Snackbar.LENGTH_LONG).show();
+                                        }
                                     }
                                     }
-                                }
 
 
-                                // Increment the bookmarks cursor.
-                                bookmarksCursor.moveToNext();
+                                    // Increment the bookmarks cursor.
+                                    bookmarksCursor.moveToNext();
+                                }
                             }
                         }
                     }
                 }
                             }
                         }
                     }
                 }
-            }
 
 
-            @Override
-            public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) {
-                // Get a the menu item ID.
-                int menuItemId = menuItem.getItemId();
-
-                // Run the command that corresponds to the selected menu item.
-                if (menuItemId == R.id.select_all) {  // Select all the bookmarks.
-                    // Get the total number of bookmarks.
-                    int numberOfBookmarks = bookmarksListView.getCount();
-
-                    // Select them all.
-                    for (int i = 0; i < numberOfBookmarks; i++) {
-                        bookmarksListView.setItemChecked(i, true);
-                    }
-                } else if (menuItemId == R.id.delete) {  // Delete the selected bookmarks.
-                    // Set the deleting bookmarks flag, which prevents the delete menu item from being enabled until the current process finishes.
-                    deletingBookmarks = true;
-
-                    // Get an array of the selected row IDs.
-                    long[] selectedBookmarksIdsLongArray = bookmarksListView.getCheckedItemIds();
-
-                    // Get an array of checked bookmarks.  `.clone()` makes a copy that won't change if the list view is reloaded, which is needed for re-selecting the bookmarks on undelete.
-                    SparseBooleanArray selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.getCheckedItemPositions().clone();
-
-                    // Update the bookmarks cursor with the current contents of the bookmarks database except for the specified database IDs.
-                    switch (currentFolderDatabaseId) {
-                        // Get a cursor with all the folders.
-                        case ALL_FOLDERS_DATABASE_ID:
-                            if (sortByDisplayOrder) {
-                                bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray);
-                            } else {
-                                bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksExcept(selectedBookmarksIdsLongArray);
-                            }
-                            break;
-
-                        // Get a cursor for the home folder.
-                        case HOME_FOLDER_DATABASE_ID:
-                            if (sortByDisplayOrder) {
-                                bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray, "");
-                            } else {
-                                bookmarksCursor = bookmarksDatabaseHelper.getBookmarksExcept(selectedBookmarksIdsLongArray, "");
-                            }
-                            break;
-
-                        // Display the selected folder.
-                        default:
-                            // Get a cursor for the selected folder.
-                            if (sortByDisplayOrder) {
-                                bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray, currentFolderName);
-                            } else {
-                                bookmarksCursor = bookmarksDatabaseHelper.getBookmarksExcept(selectedBookmarksIdsLongArray, currentFolderName);
-                            }
-                    }
+                @Override
+                public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) {
+                    // Get a the menu item ID.
+                    int menuItemId = menuItem.getItemId();
+
+                    // Run the command that corresponds to the selected menu item.
+                    if (menuItemId == R.id.select_all) {  // Select all the bookmarks.
+                        // Get the total number of bookmarks.
+                        int numberOfBookmarks = bookmarksListView.getCount();
+
+                        // Select them all.
+                        for (int i = 0; i < numberOfBookmarks; i++) {
+                            bookmarksListView.setItemChecked(i, true);
+                        }
+                    } else if (menuItemId == R.id.delete) {  // Delete the selected bookmarks.
+                        // Set the deleting bookmarks flag, which prevents the delete menu item from being enabled until the current process finishes.
+                        deletingBookmarks = true;
+
+                        // Get an array of the selected row IDs.
+                        long[] selectedBookmarksIdsLongArray = bookmarksListView.getCheckedItemIds();
+
+                        // Get an array of checked bookmarks.  `.clone()` makes a copy that won't change if the list view is reloaded, which is needed for re-selecting the bookmarks on undelete.
+                        SparseBooleanArray selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.getCheckedItemPositions().clone();
+
+                        // Update the bookmarks cursor with the current contents of the bookmarks database except for the specified database IDs.
+                        switch (currentFolderDatabaseId) {
+                            // Get a cursor with all the folders.
+                            case ALL_FOLDERS_DATABASE_ID:
+                                if (sortByDisplayOrder) {
+                                    bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray);
+                                } else {
+                                    bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksExcept(selectedBookmarksIdsLongArray);
+                                }
+                                break;
+
+                            // Get a cursor for the home folder.
+                            case HOME_FOLDER_DATABASE_ID:
+                                if (sortByDisplayOrder) {
+                                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray, "");
+                                } else {
+                                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksExcept(selectedBookmarksIdsLongArray, "");
+                                }
+                                break;
+
+                            // Display the selected folder.
+                            default:
+                                // Get a cursor for the selected folder.
+                                if (sortByDisplayOrder) {
+                                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray, currentFolderName);
+                                } else {
+                                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksExcept(selectedBookmarksIdsLongArray, currentFolderName);
+                                }
+                        }
 
 
-                    // Update the list view.
-                    bookmarksCursorAdapter.changeCursor(bookmarksCursor);
-
-                    // Create a Snackbar with the number of deleted bookmarks.
-                    bookmarksDeletedSnackbar = Snackbar.make(findViewById(R.id.bookmarks_databaseview_coordinatorlayout),
-                            getString(R.string.bookmarks_deleted) + "  " + selectedBookmarksIdsLongArray.length, Snackbar.LENGTH_LONG)
-                            .setAction(R.string.undo, view -> {
-                                // Do nothing because everything will be handled by `onDismissed()` below.
-                            })
-                            .addCallback(new Snackbar.Callback() {
-                                @SuppressLint("SwitchIntDef")  // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
-                                @Override
-                                public void onDismissed(Snackbar snackbar, int event) {
-                                    if (event == Snackbar.Callback.DISMISS_EVENT_ACTION) {  // The user pushed the undo button.
-                                        // Update the bookmarks list view with the current contents of the bookmarks database, including the "deleted bookmarks.
-                                        updateBookmarksListView();
-
-                                        // Re-select the previously selected bookmarks.
-                                        for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
-                                            bookmarksListView.setItemChecked(selectedBookmarksPositionsSparseBooleanArray.keyAt(i), true);
-                                        }
-                                    } else {  // The Snackbar was dismissed without the undo button being pushed.
-                                        // Delete each selected bookmark.
-                                        for (long databaseIdLong : selectedBookmarksIdsLongArray) {
-                                            // Convert `databaseIdLong` to an int.
-                                            int databaseIdInt = (int) databaseIdLong;
-
-                                            // Delete the selected bookmark.
-                                            bookmarksDatabaseHelper.deleteBookmark(databaseIdInt);
+                        // Update the list view.
+                        bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+
+                        // Create a Snackbar with the number of deleted bookmarks.
+                        bookmarksDeletedSnackbar = Snackbar.make(findViewById(R.id.bookmarks_databaseview_coordinatorlayout),
+                                        getString(R.string.bookmarks_deleted) + "  " + selectedBookmarksIdsLongArray.length, Snackbar.LENGTH_LONG)
+                                .setAction(R.string.undo, view -> {
+                                    // Do nothing because everything will be handled by `onDismissed()` below.
+                                })
+                                .addCallback(new Snackbar.Callback() {
+                                    @SuppressLint("SwitchIntDef")  // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
+                                    @Override
+                                    public void onDismissed(Snackbar snackbar, int event) {
+                                        if (event == Snackbar.Callback.DISMISS_EVENT_ACTION) {  // The user pushed the undo button.
+                                            // Update the bookmarks list view with the current contents of the bookmarks database, including the "deleted bookmarks.
+                                            updateBookmarksListView();
+
+                                            // Re-select the previously selected bookmarks.
+                                            for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
+                                                bookmarksListView.setItemChecked(selectedBookmarksPositionsSparseBooleanArray.keyAt(i), true);
+                                            }
+                                        } else {  // The Snackbar was dismissed without the undo button being pushed.
+                                            // Delete each selected bookmark.
+                                            for (long databaseIdLong : selectedBookmarksIdsLongArray) {
+                                                // Convert `databaseIdLong` to an int.
+                                                int databaseIdInt = (int) databaseIdLong;
+
+                                                // Delete the selected bookmark.
+                                                bookmarksDatabaseHelper.deleteBookmark(databaseIdInt);
+                                            }
                                         }
                                         }
-                                    }
 
 
-                                    // Reset the deleting bookmarks flag.
-                                    deletingBookmarks = false;
+                                        // Reset the deleting bookmarks flag.
+                                        deletingBookmarks = false;
 
 
-                                    // Enable the delete menu item.
-                                    deleteMenuItem.setEnabled(true);
+                                        // Enable the delete menu item.
+                                        deleteMenuItem.setEnabled(true);
 
 
-                                    // Close the activity if back has been pressed.
-                                    if (closeActivityAfterDismissingSnackbar) {
-                                        finish();
+                                        // Close the activity if back has been pressed.
+                                        if (closeActivityAfterDismissingSnackbar) {
+                                            finish();
+                                        }
                                     }
                                     }
-                                }
-                            });
+                                });
 
 
-                    // Show the Snackbar.
-                    bookmarksDeletedSnackbar.show();
-                }
+                        // Show the Snackbar.
+                        bookmarksDeletedSnackbar.show();
+                    }
 
 
-                // Consume the click.
-                return false;
-            }
+                    // Consume the click.
+                    return false;
+                }
 
 
-            @Override
-            public void onDestroyActionMode(ActionMode mode) {
-                // Do nothing.
-            }
-        });
+                @Override
+                public void onDestroyActionMode(ActionMode mode) {
+                    // Do nothing.
+                }
+            });
+        }
     }
 
     @Override
     }
 
     @Override
index f2bf75366c0288d993e970a2615f7b623e54d990..91c3a71ebbaa125590debe2d2bbf99ead47a0e2f 100644 (file)
@@ -759,8 +759,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
             }
         } else {  // The app has been restarted.
                 }
             }
         } else {  // The app has been restarted.
-            // Set the saved tab position to be the size of the saved state array list.  The tab position is 0 based, meaning the at the new tab will be the tab position that is restored.
-            savedTabPosition = savedStateArrayList.size();
+            // Get the information from the intent.
+            String intentAction = intent.getAction();
+            Uri intentUriData = intent.getData();
+            String intentStringExtra = intent.getStringExtra(Intent.EXTRA_TEXT);
+
+            // Determine if this is a web search.
+            boolean isWebSearch = ((intentAction != null) && intentAction.equals(Intent.ACTION_WEB_SEARCH));
+
+            // If the new intent will open a new tab, set the saved tab position to be the size of the saved state array list.
+            // The tab position is 0 based, meaning the at the new tab will be the tab position that is restored.
+            if (intentUriData != null || intentStringExtra != null || isWebSearch)
+                savedTabPosition = savedStateArrayList.size();
 
             // Replace the intent that started the app with this one.  This will load the tab after the others have been restored.
             setIntent(intent);
 
             // Replace the intent that started the app with this one.  This will load the tab after the others have been restored.
             setIntent(intent);
index ad1a150c9e1120f4359418ed7ee430366da1ad21..ff00a2842342eb394c2a2c584255c2193b1dbd6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * 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>.
  *
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -32,7 +32,8 @@ import com.stoutner.privacybrowser.fragments.AboutWebViewFragment
 import java.util.LinkedList
 
 class AboutPagerAdapter(fragmentManager: FragmentManager, private val context: Context, private val blocklistVersions: Array<String>) :
 import java.util.LinkedList
 
 class AboutPagerAdapter(fragmentManager: FragmentManager, private val context: Context, private val blocklistVersions: Array<String>) :
-        FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
+    FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
+
     // Define the class variables.
     private val aboutFragmentList = LinkedList<Fragment>()
 
     // Define the class variables.
     private val aboutFragmentList = LinkedList<Fragment>()
 
@@ -42,20 +43,6 @@ class AboutPagerAdapter(fragmentManager: FragmentManager, private val context: C
         return 7
     }
 
         return 7
     }
 
-    // Get the name of each tab.  Tab numbers start at 0.
-    override fun getPageTitle(tab: Int): CharSequence {
-        return when (tab) {
-            0 -> context.getString(R.string.version)
-            1 -> context.getString(R.string.permissions)
-            2 -> context.getString(R.string.privacy_policy)
-            3 -> context.getString(R.string.changelog)
-            4 -> context.getString(R.string.licenses)
-            5 -> context.getString(R.string.contributors)
-            6 -> context.getString(R.string.links)
-            else -> ""
-        }
-    }
-
     // Setup each tab.
     override fun getItem(tabNumber: Int): Fragment {
         // Create the tab fragment and add it to the list.
     // Setup each tab.
     override fun getItem(tabNumber: Int): Fragment {
         // Create the tab fragment and add it to the list.
@@ -71,9 +58,17 @@ class AboutPagerAdapter(fragmentManager: FragmentManager, private val context: C
         return aboutFragmentList[tabNumber]
     }
 
         return aboutFragmentList[tabNumber]
     }
 
-    // Get a tab.
-    fun getTabFragment(tabNumber: Int): Fragment {
-        // Return the tab fragment.
-        return aboutFragmentList[tabNumber]
+    // Get the name of each tab.  Tab numbers start at 0.
+    override fun getPageTitle(tab: Int): CharSequence {
+        return when (tab) {
+            0 -> context.getString(R.string.version)
+            1 -> context.getString(R.string.permissions)
+            2 -> context.getString(R.string.privacy_policy)
+            3 -> context.getString(R.string.changelog)
+            4 -> context.getString(R.string.licenses)
+            5 -> context.getString(R.string.contributors)
+            6 -> context.getString(R.string.links)
+            else -> ""
+        }
     }
     }
-}
\ No newline at end of file
+}
index 6d63c2c6e3a65526ef43998eb2fd1c5b3f6e11d6..cd746897e269ffc63699e5992611c0f569f784ec 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright 2016-2020,2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2020,2022-2023 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -34,6 +34,11 @@ class GuidePagerAdapter(fragmentManager: FragmentManager, private val context: C
         return 10
     }
 
         return 10
     }
 
+    // Setup each tab.
+    override fun getItem(tabNumber: Int): Fragment {
+        return GuideWebViewFragment.createTab(tabNumber)
+    }
+
     // Get the name of each tab.  Tab numbers start at 0.
     override fun getPageTitle(tab: Int): CharSequence {
         return when (tab) {
     // Get the name of each tab.  Tab numbers start at 0.
     override fun getPageTitle(tab: Int): CharSequence {
         return when (tab) {
@@ -50,9 +55,4 @@ class GuidePagerAdapter(fragmentManager: FragmentManager, private val context: C
             else -> ""
         }
     }
             else -> ""
         }
     }
-
-    // Setup each tab.
-    override fun getItem(tabNumber: Int): Fragment {
-        return GuideWebViewFragment.createTab(tabNumber)
-    }
 }
 }
index 68a760d23eb3d6df99129c80ca2487675ef7e61f..14e299ceff50385a89d94321a4aafc5c4dfca46e 100644 (file)
@@ -196,73 +196,6 @@ object UrlHelper {
         return Pair(fileNameString, formattedFileSize)
     }
 
         return Pair(fileNameString, formattedFileSize)
     }
 
-    /*  This entire method might not be needed.
-    fun getSize(context: Context, url: URL, userAgent: String, cookiesEnabled: Boolean): String {
-        // Initialize the formatted file size string.
-        var formattedFileSize = context.getString(R.string.unknown_size)
-
-        // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch exceptions.
-        try {
-            // Instantiate the proxy helper.
-            val proxyHelper = ProxyHelper()
-
-            // Get the current proxy.
-            val proxy = proxyHelper.getCurrentProxy(context)
-
-            // Open a connection to the URL.  No data is actually sent at this point.
-            val httpUrlConnection = url.openConnection(proxy) as HttpURLConnection
-
-            // Add the user agent to the header property.
-            httpUrlConnection.setRequestProperty("User-Agent", userAgent)
-
-            // Add the cookies if they are enabled.
-            if (cookiesEnabled) {
-                // Get the cookies for the current domain.
-                val cookiesString = CookieManager.getInstance().getCookie(url.toString())
-
-                // Only add the cookies if they are not null.
-                if (cookiesString != null) {
-                    // Add the cookies to the header property.
-                    httpUrlConnection.setRequestProperty("Cookie", cookiesString)
-                }
-            }
-
-            // The actual network request is in a `try` bracket so that `disconnect()` is run in the `finally` section even if an error is encountered in the main block.
-            try {
-                // Get the status code.  This initiates a network connection.
-                val responseCode = httpUrlConnection.responseCode
-
-                // Check the response code.
-                if (responseCode >= 400) {  // The response code is an error message.
-                    // Set the formatted file size to indicate a bad URL.
-                    formattedFileSize = context.getString(R.string.invalid_url)
-                } else {  // The response code is not an error message.
-                    // Get the content length header.
-                    val contentLengthString = httpUrlConnection.getHeaderField("Content-Length")
-
-                    // Only process the content length string if it isn't null.
-                    if (contentLengthString != null) {
-                        // Convert the content length string to a long.
-                        val fileSize = contentLengthString.toLong()
-
-                        // Format the file size.
-                        formattedFileSize = NumberFormat.getInstance().format(fileSize) + " " + context.getString(R.string.bytes)
-                    }
-                }
-            } finally {
-                // Disconnect the HTTP URL connection.
-                httpUrlConnection.disconnect()
-            }
-        } catch (exception: Exception) {
-            // Set the formatted file size to indicate a bad URL.
-            formattedFileSize = context.getString(R.string.invalid_url)
-        }
-
-        // Return the formatted file size.
-        return formattedFileSize
-    }
-    */
-
     @JvmStatic
     fun highlightSyntax(urlEditText: EditText, initialGrayColorSpan: ForegroundColorSpan, finalGrayColorSpan: ForegroundColorSpan, redColorSpan: ForegroundColorSpan) {
         // Get the URL string.
     @JvmStatic
     fun highlightSyntax(urlEditText: EditText, initialGrayColorSpan: ForegroundColorSpan, finalGrayColorSpan: ForegroundColorSpan, redColorSpan: ForegroundColorSpan) {
         // Get the URL string.