]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.kt
First wrong button text in View Headers in night theme. https://redmine.stoutner...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / BookmarksActivity.kt
index 2353627eae2283fd7abcee67e7b4268746a899ff..fe7d080854cd60654136491e3b17d3343a53230c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2024 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -19,7 +19,6 @@
 
 package com.stoutner.privacybrowser.activities
 
-import android.annotation.SuppressLint
 import android.content.Context
 import android.content.Intent
 import android.database.Cursor
@@ -48,6 +47,7 @@ import androidx.activity.OnBackPressedCallback
 import androidx.appcompat.app.ActionBar
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.widget.Toolbar
+import androidx.core.graphics.drawable.toBitmap
 import androidx.cursoradapter.widget.CursorAdapter
 import androidx.fragment.app.DialogFragment
 import androidx.preference.PreferenceManager
@@ -56,38 +56,42 @@ 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.Companion.createBookmark
-import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog.CreateBookmarkListener
-import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog.Companion.createBookmarkFolder
-import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog.CreateBookmarkFolderListener
-import com.stoutner.privacybrowser.dialogs.EditBookmarkDialog.Companion.bookmarkDatabaseId
-import com.stoutner.privacybrowser.dialogs.EditBookmarkDialog.EditBookmarkListener
-import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDialog.Companion.folderDatabaseId
-import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDialog.EditBookmarkFolderListener
-import com.stoutner.privacybrowser.dialogs.MoveToFolderDialog.Companion.moveBookmarks
-import com.stoutner.privacybrowser.dialogs.MoveToFolderDialog.MoveToFolderListener
+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.helpers.BOOKMARK_NAME
+import com.stoutner.privacybrowser.helpers.DISPLAY_ORDER
+import com.stoutner.privacybrowser.helpers.FAVORITE_ICON
+import com.stoutner.privacybrowser.helpers.FOLDER_ID
+import com.stoutner.privacybrowser.helpers.ID
+import com.stoutner.privacybrowser.helpers.IS_FOLDER
 import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper
 
 import java.io.ByteArrayOutputStream
 import java.util.function.Consumer
 
 // Define the public constants.
-const val CURRENT_FOLDER = "current_folder"
-const val CURRENT_TITLE = "current_title"
-const val CURRENT_FAVORITE_ICON_BYTE_ARRAY = "current_favorite_icon_byte_array"
+const val CURRENT_FAVORITE_ICON_BYTE_ARRAY = "A"
+const val CURRENT_FOLDER_ID = "B"
+const val CURRENT_TITLE = "C"
 
 // Define the private constants.
-private const val CHECKED_BOOKMARKS_ARRAY_LIST = "checked_bookmarks_array_list"
+private const val CHECKED_BOOKMARKS_ARRAY_LIST = "D"
+
+class BookmarksActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, EditBookmarkDialog.EditBookmarkListener,
+    EditBookmarkFolderDialog.EditBookmarkFolderListener, MoveToFolderDialog.MoveToFolderListener {
 
-class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBookmarkFolderListener, EditBookmarkListener, EditBookmarkFolderListener, MoveToFolderListener {
     companion object {
         // Define the public static variables, which are accessed from the bookmarks database view activity.
-        var currentFolder: String = ""
+        var currentFolderId: Long = 0
         var restartFromBookmarksDatabaseViewActivity = false
     }
 
     // Define the class variables.
     private var bookmarksDeletedSnackbar: Snackbar? = null
+    private var checkingManyBookmarks = false
     private var closeActivityAfterDismissingSnackbar = false
     private var contextualActionMode: ActionMode? = null
 
@@ -100,7 +104,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
     private lateinit var currentFavoriteIconByteArray: ByteArray
     private lateinit var moveBookmarkDownMenuItem: MenuItem
     private lateinit var moveBookmarkUpMenuItem: MenuItem
-    private lateinit var oldFolderNameString: String
+    private lateinit var moveToFolderMenuItem: MenuItem
 
     override fun onCreate(savedInstanceState: Bundle?) {
         // Get a handle for the shared preferences.
@@ -122,7 +126,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         val launchingIntent = intent
 
         // Populate the variables from the launching intent.
-        currentFolder = launchingIntent.getStringExtra(CURRENT_FOLDER)!!
+        currentFolderId = launchingIntent.getLongExtra(CURRENT_FOLDER_ID, HOME_FOLDER_ID)
         val currentTitle = launchingIntent.getStringExtra(CURRENT_TITLE)!!
         val currentUrl = launchingIntent.getStringExtra(CURRENT_URL)!!
         currentFavoriteIconByteArray = launchingIntent.getByteArrayExtra(CURRENT_FAVORITE_ICON_BYTE_ARRAY)!!
@@ -171,7 +175,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         // Initialize the database helper.
         bookmarksDatabaseHelper = BookmarksDatabaseHelper(this)
 
-        // Set a listener so that tapping a list item loads the URL or folder.
+        // Set a listener so that tapping a list item edits the bookmark or opens a folder.
         bookmarksListView.onItemClickListener = AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, _: Int, id: Long ->
             // Convert the id from long to int to match the format of the bookmarks database.
             val databaseId = id.toInt()
@@ -183,15 +187,15 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             bookmarkCursor.moveToFirst()
 
             // Act upon the bookmark according to the type.
-            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
-                // Update the current folder.
-                currentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
+                // Update the current folder ID.
+                currentFolderId = bookmarkCursor.getLong(bookmarkCursor.getColumnIndexOrThrow(FOLDER_ID))
 
                 // Load the new folder.
                 loadFolder()
             } else {  // The selected bookmark is not a folder.
                 // Instantiate the edit bookmark dialog.
-                val editBookmarkDialog: DialogFragment = bookmarkDatabaseId(databaseId, currentFavoriteIconBitmap)
+                val editBookmarkDialog = EditBookmarkDialog.editBookmark(databaseId, currentFavoriteIconBitmap)
 
                 // Make it so.
                 editBookmarkDialog.show(supportFragmentManager, resources.getString(R.string.edit_bookmark))
@@ -216,15 +220,16 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                 menuInflater.inflate(R.menu.bookmarks_context_menu, menu)
 
                 // Set the title.
-                if (currentFolder.isEmpty()) {  // Use `R.string.bookmarks` if in the home folder.
+                if (currentFolderId == HOME_FOLDER_ID) {  // The current folder is the home folder.
                     mode.setTitle(R.string.bookmarks)
                 } else {  // Use the current folder name as the title.
-                    mode.title = currentFolder
+                    mode.title = bookmarksDatabaseHelper.getFolderName(currentFolderId)
                 }
 
                 // Get handles for menu items that need to be selectively disabled.
                 moveBookmarkUpMenuItem = menu.findItem(R.id.move_bookmark_up)
                 moveBookmarkDownMenuItem = menu.findItem(R.id.move_bookmark_down)
+                moveToFolderMenuItem = menu.findItem(R.id.move_to_folder)
                 editBookmarkMenuItem = menu.findItem(R.id.edit_bookmark)
                 deleteBookmarksMenuItem = menu.findItem(R.id.delete_bookmark)
                 selectAllBookmarksMenuItem = menu.findItem(R.id.context_menu_select_all_bookmarks)
@@ -240,56 +245,56 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             }
 
             override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
-                // Get a handle for the move to folder menu item.
-                val moveToFolderMenuItem = menu.findItem(R.id.move_to_folder)
-
-                // Get a Cursor with all of the folders.
-                val folderCursor = bookmarksDatabaseHelper.allFolders
-
-                // Display the move to folder menu item if at least one folder exists.
-                moveToFolderMenuItem.isVisible = folderCursor.count > 0
+                // Display the move to folder menu item if at least one other folder exists.
+                moveToFolderMenuItem.isVisible = bookmarksDatabaseHelper.hasFoldersExceptDatabaseId(bookmarksListView.checkedItemIds)
 
                 // Make it so.
                 return true
             }
 
-            override fun onItemCheckedStateChanged(mode: ActionMode, position: Int, id: Long, checked: Boolean) {
-                // Get the number of selected bookmarks.
-                val numberOfSelectedBookmarks = bookmarksListView.checkedItemCount
-
-                // 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 action mode and the menu according to the number of selected bookmarks.
-                    if (numberOfSelectedBookmarks == 1) {  // One bookmark is selected.
-                        // Show the applicable menu items.
-                        moveBookmarkUpMenuItem.isVisible = true
-                        moveBookmarkDownMenuItem.isVisible = true
-                        editBookmarkMenuItem.isVisible = true
-
-                        // Update the enabled status of the move icons.
-                        updateMoveIcons()
-                    } else {  // More than one bookmark is selected.
-                        // Hide non-applicable `MenuItems`.
-                        moveBookmarkUpMenuItem.isVisible = false
-                        moveBookmarkDownMenuItem.isVisible = false
-                        editBookmarkMenuItem.isVisible = false
-                    }
+            override fun onItemCheckedStateChanged(actionMode: ActionMode, position: Int, id: Long, checked: Boolean) {
+                // Only update the UI if not checking many bookmarks.  In that case, the flag will be reset on the last bookmark so the UI is only updated once.
+                if (!checkingManyBookmarks) {
+                    // Get the number of selected bookmarks.
+                    val numberOfSelectedBookmarks = bookmarksListView.checkedItemCount
+
+                    // 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 action mode and the menu according to the number of selected bookmarks.
+                        if (numberOfSelectedBookmarks == 1) {  // One bookmark is selected.
+                            // Show the applicable menu items.
+                            moveBookmarkUpMenuItem.isVisible = true
+                            moveBookmarkDownMenuItem.isVisible = true
+                            editBookmarkMenuItem.isVisible = true
+
+                            // Update the enabled status of the move icons.
+                            updateMoveIcons()
+                        } else {  // More than one bookmark is selected.
+                            // Hide non-applicable `MenuItems`.
+                            moveBookmarkUpMenuItem.isVisible = false
+                            moveBookmarkDownMenuItem.isVisible = false
+                            editBookmarkMenuItem.isVisible = false
+                        }
 
-                    // List the number of selected bookmarks in the subtitle.
-                    mode.subtitle = getString(R.string.selected, numberOfSelectedBookmarks)
+                        // Display the move to folder menu item if at least one other folder exists.
+                        moveToFolderMenuItem.isVisible = bookmarksDatabaseHelper.hasFoldersExceptDatabaseId(bookmarksListView.checkedItemIds)
 
-                    // Show the select all menu item if all the bookmarks are not selected.
-                    selectAllBookmarksMenuItem.isVisible = (numberOfSelectedBookmarks != bookmarksListView.count)
+                        // List the number of selected bookmarks in the subtitle.
+                        actionMode.subtitle = getString(R.string.selected, numberOfSelectedBookmarks)
+
+                        // Show the select all menu item if all the bookmarks are not selected.
+                        selectAllBookmarksMenuItem.isVisible = (numberOfSelectedBookmarks != bookmarksListView.count)
+                    }
                 }
             }
 
             override fun onActionItemClicked(actionMode: ActionMode, menuItem: MenuItem): Boolean {
                 // Declare the variables.
-                val selectedBookmarkNewPosition: Int
-                val selectedBookmarksPositionsSparseBooleanArray: SparseBooleanArray
+                val checkedBookmarkNewPosition: Int
+                val checkedBookmarksPositionsSparseBooleanArray: SparseBooleanArray
 
-                // Initialize the selected bookmark position.
-                var selectedBookmarkPosition = 0
+                // Initialize the checked bookmark position.
+                var checkedBookmarkPosition = 0
 
                 // Get the menu item ID.
                 val menuItemId = menuItem.itemId
@@ -297,30 +302,33 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                 // Run the commands according to the selected action item.
                 if (menuItemId == R.id.move_bookmark_up) {  // Move the bookmark up.
                     // Get the array of checked bookmark positions.
-                    selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions
+                    checkedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions
 
                     // 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 (i in 0 until selectedBookmarksPositionsSparseBooleanArray.size()) {
+                    for (i in 0 until checkedBookmarksPositionsSparseBooleanArray.size()) {
                         // Check to see if the value for the bookmark is true, meaning it is currently selected.
-                        if (selectedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
+                        if (checkedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
                             // Only one bookmark should have a value of `true` when move bookmark up is enabled.
-                            selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(i)
+                            checkedBookmarkPosition = checkedBookmarksPositionsSparseBooleanArray.keyAt(i)
                         }
                     }
 
-                    // Calculate the new position of the selected bookmark.
-                    selectedBookmarkNewPosition = selectedBookmarkPosition - 1
+                    // Calculate the new position of the checked bookmark.
+                    checkedBookmarkNewPosition = checkedBookmarkPosition - 1
+
+                    // Get the bookmarks count.
+                    val bookmarksCount = bookmarksListView.count
 
                     // Iterate through the bookmarks.
-                    for (i in 0 until bookmarksListView.count) {
+                    for (i in 0 until bookmarksCount) {
                         // Get the database ID for the current bookmark.
                         val currentBookmarkDatabaseId = bookmarksListView.getItemIdAtPosition(i).toInt()
 
                         // Update the display order for the current bookmark.
-                        if (i == selectedBookmarkPosition) {  // The current bookmark is the selected bookmark.
+                        if (i == checkedBookmarkPosition) {  // The current bookmark is the selected bookmark.
                             // Move the current bookmark up one.
                             bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i - 1)
-                        } else if ((i + 1) == selectedBookmarkPosition) {  // The current bookmark is immediately above the selected bookmark.
+                        } else if ((i + 1) == checkedBookmarkPosition) {  // The current bookmark is immediately above the selected bookmark.
                             // Move the current bookmark down one.
                             bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i + 1)
                         } else {  // The current bookmark is not changing positions.
@@ -328,37 +336,37 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                             bookmarksCursor.moveToPosition(i)
 
                             // Update the display order only if it is not correct in the database.  This fixes problems where the display order somehow got out of sync.
-                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i)
+                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) != i)
                                 bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i)
                         }
                     }
 
                     // Update the bookmarks cursor with the current contents of the bookmarks database.
-                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
                     // Update the list view.
                     bookmarksCursorAdapter.changeCursor(bookmarksCursor)
 
                     // Scroll to the new bookmark position.
-                    scrollBookmarks(selectedBookmarkNewPosition)
+                    scrollBookmarks(checkedBookmarkNewPosition)
 
                     // Update the enabled status of the move icons.
                     updateMoveIcons()
                 } else if (menuItemId == R.id.move_bookmark_down) {  // Move the bookmark down.
                     // Get the array of checked bookmark positions.
-                    selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions
+                    checkedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions
 
-                    // 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 (i in 0 until selectedBookmarksPositionsSparseBooleanArray.size()) {
+                    // Get the position of the bookmark that is selected.  If other bookmarks have previously been checked they will be included in the sparse boolean array with a value of `false`.
+                    for (i in 0 until checkedBookmarksPositionsSparseBooleanArray.size()) {
                         // Check to see if the value for the bookmark is true, meaning it is currently selected.
-                        if (selectedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
+                        if (checkedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
                             // Only one bookmark should have a value of `true` when move bookmark down is enabled.
-                            selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(i)
+                            checkedBookmarkPosition = checkedBookmarksPositionsSparseBooleanArray.keyAt(i)
                         }
                     }
 
-                    // Calculate the new position of the selected bookmark.
-                    selectedBookmarkNewPosition = selectedBookmarkPosition + 1
+                    // Calculate the new position of the checked bookmark.
+                    checkedBookmarkNewPosition = checkedBookmarkPosition + 1
 
                     // Iterate through the bookmarks.
                     for (i in 0 until bookmarksListView.count) {
@@ -366,10 +374,10 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                         val currentBookmarkDatabaseId = bookmarksListView.getItemIdAtPosition(i).toInt()
 
                         // Update the display order for the current bookmark.
-                        if (i == selectedBookmarkPosition) {  // The current bookmark is the selected bookmark.
+                        if (i == checkedBookmarkPosition) {  // The current bookmark is the checked bookmark.
                             // Move the current bookmark down one.
                             bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i + 1)
-                        } else if (i - 1 == selectedBookmarkPosition) {  // The current bookmark is immediately below the selected bookmark.
+                        } else if ((i - 1) == checkedBookmarkPosition) {  // The current bookmark is immediately below the checked bookmark.
                             // Move the bookmark below the selected bookmark up one.
                             bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i - 1)
                         } else {  // The current bookmark is not changing positions.
@@ -377,61 +385,58 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                             bookmarksCursor.moveToPosition(i)
 
                             // Update the display order only if it is not correct in the database.  This fixes problems where the display order somehow got out of sync.
-                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
+                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) != i) {
                                 bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i)
                             }
                         }
                     }
 
                     // Update the bookmarks cursor with the current contents of the bookmarks database.
-                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
                     // Update the list view.
                     bookmarksCursorAdapter.changeCursor(bookmarksCursor)
 
                     // Scroll to the new bookmark position.
-                    scrollBookmarks(selectedBookmarkNewPosition)
+                    scrollBookmarks(checkedBookmarkNewPosition)
 
                     // Update the enabled status of the move icons.
                     updateMoveIcons()
                 } else if (menuItemId == R.id.move_to_folder) {  // Move to folder.
                     // Instantiate the move to folder alert dialog.
-                    val moveToFolderDialog: DialogFragment = moveBookmarks(currentFolder, bookmarksListView.checkedItemIds)
+                    val moveToFolderDialog = MoveToFolderDialog.moveBookmarks(currentFolderId, bookmarksListView.checkedItemIds)
 
                     // Show the move to folder alert dialog.
                     moveToFolderDialog.show(supportFragmentManager, resources.getString(R.string.move_to_folder))
                 } else if (menuItemId == R.id.edit_bookmark) {
                     // Get the array of checked bookmark positions.
-                    selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions
+                    checkedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions
 
                     // 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 (i in 0 until selectedBookmarksPositionsSparseBooleanArray.size()) {
+                    for (i in 0 until checkedBookmarksPositionsSparseBooleanArray.size()) {
                         // Check to see if the value for the bookmark is true, meaning it is currently selected.
-                        if (selectedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
+                        if (checkedBookmarksPositionsSparseBooleanArray.valueAt(i)) {
                             // Only one bookmark should have a value of `true` when move edit bookmark is enabled.
-                            selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(i)
+                            checkedBookmarkPosition = checkedBookmarksPositionsSparseBooleanArray.keyAt(i)
                         }
                     }
 
                     // Move the cursor to the selected position.
-                    bookmarksCursor.moveToPosition(selectedBookmarkPosition)
+                    bookmarksCursor.moveToPosition(checkedBookmarkPosition)
 
                     // Get the selected bookmark database ID.
-                    val databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID))
+                    val databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(ID))
 
                     // Show the edit bookmark or edit bookmark folder dialog.
-                    if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // A folder is selected.
-                        // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
-                        oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
-
+                    if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(IS_FOLDER)) == 1) {  // A folder is selected.
                         // Instantiate the edit bookmark folder dialog.
-                        val editFolderDialog: DialogFragment = folderDatabaseId(databaseId, currentFavoriteIconBitmap)
+                        val editFolderDialog = EditBookmarkFolderDialog.editFolder(databaseId, currentFavoriteIconBitmap)
 
                         // Make it so.
                         editFolderDialog.show(supportFragmentManager, resources.getString(R.string.edit_folder))
                     } else {  // A bookmark is selected.
                         // Instantiate the edit bookmark dialog.
-                        val editBookmarkDialog: DialogFragment = bookmarkDatabaseId(databaseId, currentFavoriteIconBitmap)
+                        val editBookmarkDialog = EditBookmarkDialog.editBookmark(databaseId, currentFavoriteIconBitmap)
 
                         // Make it so.
                         editBookmarkDialog.show(supportFragmentManager, resources.getString(R.string.edit_bookmark))
@@ -440,14 +445,14 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                     // 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.
-                    val selectedBookmarksIdsLongArray = bookmarksListView.checkedItemIds
+                    // Get an array of the checked row IDs.
+                    val checkedBookmarksIdsLongArray = bookmarksListView.checkedItemIds
 
                     // Initialize a variable to count the number of bookmarks to delete.
                     var numberOfBookmarksToDelete = 0
 
                     // Count the number of bookmarks to delete.
-                    for (databaseIdLong in selectedBookmarksIdsLongArray) {
+                    for (databaseIdLong in checkedBookmarksIdsLongArray) {
                         // Convert the database ID long to an int.
                         val databaseIdInt = databaseIdLong.toInt()
 
@@ -462,10 +467,10 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                     }
 
                     // 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.
-                    selectedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions.clone()
+                    checkedBookmarksPositionsSparseBooleanArray = bookmarksListView.checkedItemPositions.clone()
 
                     // Update the bookmarks cursor with the current contents of the bookmarks database except for the specified database IDs.
-                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrderExcept(selectedBookmarksIdsLongArray, currentFolder)
+                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrderExcept(checkedBookmarksIdsLongArray, currentFolderId)
 
                     // Update the list view.
                     bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -474,21 +479,32 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                     bookmarksDeletedSnackbar = Snackbar.make(findViewById(R.id.bookmarks_coordinatorlayout), getString(R.string.bookmarks_deleted, numberOfBookmarksToDelete), Snackbar.LENGTH_LONG)
                         .setAction(R.string.undo) { }  // Do nothing because everything will be handled by `onDismissed()` below.
                         .addCallback(object : Snackbar.Callback() {
-                            @SuppressLint("SwitchIntDef")  // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
                             override fun onDismissed(snackbar: Snackbar, event: Int) {
                                 if (event == DISMISS_EVENT_ACTION) {  // The user pushed the undo button.
                                     // Update the bookmarks cursor with the current contents of the bookmarks database, including the "deleted" bookmarks.
-                                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+                                    bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
                                     // Update the list view.
                                     bookmarksCursorAdapter.changeCursor(bookmarksCursor)
 
-                                    // Re-select the previously selected bookmarks.
-                                    for (i in 0 until selectedBookmarksPositionsSparseBooleanArray.size())
-                                        bookmarksListView.setItemChecked(selectedBookmarksPositionsSparseBooleanArray.keyAt(i), true)
+                                    // Get the number of checked bookmarks.
+                                    val numberOfCheckedBookmarks = checkedBookmarksPositionsSparseBooleanArray.size()
+
+                                    // Set the checking many bookmarks flag.
+                                    checkingManyBookmarks = true
+
+                                    // Re-check the previously checked bookmarks.
+                                    for (i in 0 until numberOfCheckedBookmarks) {
+                                        // Reset the checking many bookmarks flag on the last bookmark so the UI is updated.
+                                        if (i == (numberOfCheckedBookmarks - 1))
+                                            checkingManyBookmarks = false
+
+                                        // Check the bookmark.
+                                        bookmarksListView.setItemChecked(checkedBookmarksPositionsSparseBooleanArray.keyAt(i), true)
+                                    }
                                 } else {  // The snackbar was dismissed without the undo button being pushed.
                                     // Delete each selected bookmark.
-                                    for (databaseIdLong in selectedBookmarksIdsLongArray) {
+                                    for (databaseIdLong in checkedBookmarksIdsLongArray) {
                                         // Convert the database long ID to an int.
                                         val databaseIdInt = databaseIdLong.toInt()
 
@@ -509,7 +525,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                                         bookmarksCursor.moveToPosition(i)
 
                                         // Update the display order only if it is not correct in the database.
-                                        if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i)
+                                        if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) != i)
                                             bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i)
                                     }
                                 }
@@ -521,8 +537,13 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                                 deleteBookmarksMenuItem.isEnabled = true
 
                                 // Close the activity if back has been pressed.
-                                if (closeActivityAfterDismissingSnackbar)
+                                if (closeActivityAfterDismissingSnackbar) {
+                                    // Close the bookmarks drawer and reload the bookmarks list view when returning to the main WebView activity.
+                                    MainWebViewActivity.restartFromBookmarksActivity = true
+
+                                    // Finish the activity.
                                     finish()
+                                }
                             }
                         })
 
@@ -532,8 +553,16 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                     // Get the total number of bookmarks.
                     val numberOfBookmarks = bookmarksListView.count
 
+                    // Set the checking many bookmarks flag.
+                    checkingManyBookmarks = true
+
                     // Select them all.
                     for (i in 0 until numberOfBookmarks) {
+                        // Reset the checking many bookmarks flag on the last bookmark so the UI is updated.
+                        if (i == (numberOfBookmarks - 1))
+                            checkingManyBookmarks = false
+
+                        // Check the bookmark.
                         bookmarksListView.setItemChecked(i, true)
                     }
                 }
@@ -550,7 +579,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         // Set the create new bookmark folder FAB to display the alert dialog.
         createBookmarkFolderFab.setOnClickListener {
             // Create a create bookmark folder dialog.
-            val createBookmarkFolderDialog: DialogFragment = createBookmarkFolder(currentFavoriteIconBitmap)
+            val createBookmarkFolderDialog = CreateBookmarkFolderDialog.createBookmarkFolder(currentFavoriteIconBitmap)
 
             // Show the create bookmark folder dialog.
             createBookmarkFolderDialog.show(supportFragmentManager, getString(R.string.create_folder))
@@ -559,7 +588,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         // Set the create new bookmark FAB to display the alert dialog.
         createBookmarkFab.setOnClickListener {
             // Instantiate the create bookmark dialog.
-            val createBookmarkDialog: DialogFragment = createBookmark(currentUrl, currentTitle, currentFavoriteIconBitmap)
+            val createBookmarkDialog = CreateBookmarkDialog.createBookmark(currentUrl, currentTitle, currentFavoriteIconBitmap)
 
             // Display the create bookmark dialog.
             createBookmarkDialog.show(supportFragmentManager, resources.getString(R.string.create_bookmark))
@@ -568,7 +597,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         // Restore the state if the app has been restarted.
         if (savedInstanceState != null) {
             // Restore the current folder.
-            currentFolder = savedInstanceState.getString(CURRENT_FOLDER)!!
+            currentFolderId = savedInstanceState.getLong(CURRENT_FOLDER_ID, HOME_FOLDER_ID)
 
             // Update the bookmarks list view after it has loaded.
             bookmarksListView.post {
@@ -618,7 +647,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         }
 
         // Store the variables in the saved instance state.
-        savedInstanceState.putString(CURRENT_FOLDER, currentFolder)
+        savedInstanceState.putLong(CURRENT_FOLDER_ID, currentFolderId)
         savedInstanceState.putIntegerArrayList(CHECKED_BOOKMARKS_ARRAY_LIST, checkedBookmarksArrayList)
     }
 
@@ -636,12 +665,12 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
 
         // 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.
+            if (currentFolderId == HOME_FOLDER_ID) {  // The current folder is the home folder.
                 // Prepare to finish the activity.
                 prepareFinish()
             } else {  // Currently in a subfolder.
                 // Set the former parent folder as the current folder.
-                currentFolder = bookmarksDatabaseHelper.getParentFolderName(currentFolder)
+                currentFolderId = bookmarksDatabaseHelper.getParentFolderId(currentFolderId)
 
                 // Load the new current folder.
                 loadFolder()
@@ -650,8 +679,16 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             // Get the total number of bookmarks.
             val numberOfBookmarks = bookmarksListView.count
 
+            // Set the checking many bookmarks flag.
+            checkingManyBookmarks = true
+
             // Select them all.
             for (i in 0 until numberOfBookmarks) {
+                // Reset the checking many bookmarks flag on the last bookmark so the UI is updated.
+                if (i == (numberOfBookmarks - 1))
+                    checkingManyBookmarks = false
+
+                // Check the bookmark.
                 bookmarksListView.setItemChecked(i, true)
             }
         } else if (menuItemId == R.id.bookmarks_database_view) {
@@ -670,17 +707,29 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         return true
     }
 
-    override fun createBookmark(dialogFragment: DialogFragment, favoriteIconBitmap: Bitmap) {
+    override fun createBookmark(dialogFragment: DialogFragment) {
         // Get the alert dialog from the fragment.
         val dialog = dialogFragment.dialog!!
 
-        // Get the views from the dialog fragment.
-        val createBookmarkNameEditText = dialog.findViewById<EditText>(R.id.create_bookmark_name_edittext)
-        val createBookmarkUrlEditText = dialog.findViewById<EditText>(R.id.create_bookmark_url_edittext)
+        // Get handles for the views from the dialog fragment.
+        val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+        val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+        val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
+        val bookmarkNameEditText = dialog.findViewById<EditText>(R.id.bookmark_name_edittext)
+        val bookmarkUrlEditText = dialog.findViewById<EditText>(R.id.bookmark_url_edittext)
+
+        // Get the strings from the edit texts.
+        val bookmarkNameString = bookmarkNameEditText.text.toString()
+        val bookmarkUrlString = bookmarkUrlEditText.text.toString()
+
+        // Get the selected favorite icon drawable.
+        val favoriteIconDrawable = if (webpageFavoriteIconRadioButton.isChecked)  // The webpage favorite icon is checked.
+            webpageFavoriteIconImageView.drawable
+        else  // The custom favorite icon is checked.
+            customIconImageView.drawable
 
-        // Extract the strings from the edit texts.
-        val bookmarkNameString = createBookmarkNameEditText.text.toString()
-        val bookmarkUrlString = createBookmarkUrlEditText.text.toString()
+        // Convert the favorite icon drawable to a bitmap.  Once the minimum API >= 33, this can use Bitmap.Config.RGBA_1010102.
+        val favoriteIconBitmap = favoriteIconDrawable.toBitmap(128, 128, Bitmap.Config.ARGB_8888)
 
         // Create a favorite icon byte array output stream.
         val favoriteIconByteArrayOutputStream = ByteArrayOutputStream()
@@ -695,10 +744,10 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         val newBookmarkDisplayOrder = bookmarksListView.count
 
         // Create the bookmark.
-        bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, currentFolder, newBookmarkDisplayOrder, favoriteIconByteArray)
+        bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, currentFolderId, newBookmarkDisplayOrder, favoriteIconByteArray)
 
         // Update the bookmarks cursor with the current contents of this folder.
-        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -707,32 +756,34 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         bookmarksListView.setSelection(newBookmarkDisplayOrder)
     }
 
-    override fun createBookmarkFolder(dialogFragment: DialogFragment, favoriteIconBitmap: Bitmap) {
+    override fun createBookmarkFolder(dialogFragment: DialogFragment) {
         // Get the dialog from the dialog fragment.
         val dialog = dialogFragment.dialog!!
 
         // Get handles for the views in the dialog fragment.
+        val defaultFolderIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_folder_icon_radiobutton)
+        val defaultFolderIconImageView = dialog.findViewById<ImageView>(R.id.default_folder_icon_imageview)
+        val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+        val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+        val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
         val folderNameEditText = dialog.findViewById<EditText>(R.id.folder_name_edittext)
-        val defaultIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_icon_radiobutton)
-        val defaultIconImageView = dialog.findViewById<ImageView>(R.id.default_icon_imageview)
 
-        // Get new folder name string.
+        // Get the folder name string.
         val folderNameString = folderNameEditText.text.toString()
 
-        // Set the folder icon bitmap according to the dialog.
-        val folderIconBitmap = if (defaultIconRadioButton.isChecked) {  // Use the default folder icon.
-            // Get the default folder icon drawable.
-            val folderIconDrawable = defaultIconImageView.drawable
+        // Get the selected folder icon drawable.
+        val folderIconDrawable = if (defaultFolderIconRadioButton.isChecked)  // Use the default folder icon.
+            defaultFolderIconImageView.drawable
+        else if (webpageFavoriteIconRadioButton.isChecked)  // Use the webpage favorite icon.
+            webpageFavoriteIconImageView.drawable
+        else  // Use the custom icon.
+            customIconImageView.drawable
 
-            // Convert the folder icon drawable to a bitmap drawable.
-            val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
+        // Cast the folder icon bitmap to a bitmap drawable.
+        val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
 
-            // Convert the folder icon bitmap drawable to a bitmap.
-            folderIconBitmapDrawable.bitmap
-        } else {  // Use the WebView favorite icon.
-            // Copy the favorite icon bitmap to the folder icon bitmap.
-            favoriteIconBitmap
-        }
+        // Convert the folder icon bitmap drawable to a bitmap.
+        val folderIconBitmap = folderIconBitmapDrawable.bitmap
 
         // Create a folder icon byte array output stream.
         val folderIconByteArrayOutputStream = ByteArrayOutputStream()
@@ -746,14 +797,14 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         // Move all the bookmarks down one in the display order.
         for (i in 0 until bookmarksListView.count) {
             val databaseId = bookmarksListView.getItemIdAtPosition(i).toInt()
-            bookmarksDatabaseHelper.updateDisplayOrder(databaseId, i + 1)
+            bookmarksDatabaseHelper.updateDisplayOrder(databaseId, displayOrder = i + 1)
         }
 
         // Create the folder, which will be placed at the top of the list view.
-        bookmarksDatabaseHelper.createFolder(folderNameString, currentFolder, folderIconByteArray)
+        bookmarksDatabaseHelper.createFolder(folderNameString, currentFolderId, displayOrder = 0, folderIconByteArray)
 
         // Update the bookmarks cursor with the contents of the current folder.
-        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -762,16 +813,19 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         bookmarksListView.setSelection(0)
     }
 
-    override fun onSaveBookmark(dialogFragment: DialogFragment, selectedBookmarkDatabaseId: Int, favoriteIconBitmap: Bitmap) {
+    override fun saveBookmark(dialogFragment: DialogFragment, selectedBookmarkDatabaseId: Int) {
         // Get the dialog from the dialog fragment.
         val dialog = dialogFragment.dialog!!
 
         // Get handles for the views from the dialog fragment.
+        val currentIconRadioButton = dialog.findViewById<RadioButton>(R.id.current_icon_radiobutton)
+        val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+        val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+        val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
         val bookmarkNameEditText = dialog.findViewById<EditText>(R.id.bookmark_name_edittext)
         val bookmarkUrlEditText = dialog.findViewById<EditText>(R.id.bookmark_url_edittext)
-        val currentIconRadioButton = dialog.findViewById<RadioButton>(R.id.current_icon_radiobutton)
 
-        // Get the bookmark strings.
+        // Get the strings from the edit texts.
         val bookmarkNameString = bookmarkNameEditText.text.toString()
         val bookmarkUrlString = bookmarkUrlEditText.text.toString()
 
@@ -779,6 +833,15 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         if (currentIconRadioButton.isChecked) {  // Update the bookmark without changing the favorite icon.
             bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString)
         } else {  // Update the bookmark using the WebView favorite icon.
+            // Get the selected favorite icon drawable.
+            val favoriteIconDrawable = if (webpageFavoriteIconRadioButton.isChecked)  // The webpage favorite icon is checked.
+                webpageFavoriteIconImageView.drawable
+            else  // The custom icon is checked.
+                customIconImageView.drawable
+
+            // Convert the favorite icon drawable to a bitmap.  Once the minimum API >= 33, this can use Bitmap.Config.RGBA_1010102.
+            val favoriteIconBitmap = favoriteIconDrawable.toBitmap(128, 128, Bitmap.Config.ARGB_8888)
+
             // Create a favorite icon byte array output stream.
             val newFavoriteIconByteArrayOutputStream = ByteArrayOutputStream()
 
@@ -796,46 +859,45 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         contextualActionMode?.finish()
 
         // Update the bookmarks cursor with the contents of the current folder.
-        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
     }
 
-    override fun onSaveBookmarkFolder(dialogFragment: DialogFragment, selectedFolderDatabaseId: Int, favoriteIconBitmap: Bitmap) {
+    override fun saveBookmarkFolder(dialogFragment: DialogFragment, selectedFolderDatabaseId: Int) {
         // Get the dialog from the dialog fragment.
         val dialog = dialogFragment.dialog!!
 
         // Get handles for the views from the dialog fragment.
         val currentFolderIconRadioButton = dialog.findViewById<RadioButton>(R.id.current_icon_radiobutton)
-        val defaultFolderIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_icon_radiobutton)
-        val defaultFolderIconImageView = dialog.findViewById<ImageView>(R.id.default_icon_imageview)
-        val editFolderNameEditText = dialog.findViewById<EditText>(R.id.folder_name_edittext)
+        val defaultFolderIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_folder_icon_radiobutton)
+        val defaultFolderIconImageView = dialog.findViewById<ImageView>(R.id.default_folder_icon_imageview)
+        val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+        val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+        val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
+        val folderNameEditText = dialog.findViewById<EditText>(R.id.folder_name_edittext)
 
         // Get the new folder name.
-        val newFolderNameString = editFolderNameEditText.text.toString()
+        val newFolderName = folderNameEditText.text.toString()
 
-        // Check if the favorite icon has changed.
+        // Check if the folder icon has changed.
         if (currentFolderIconRadioButton.isChecked) {  // Only the name has changed.
             // Update the name in the database.
-            bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString)
+            bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, newFolderName)
         } else {  // The icon has changed.
-            // Populate the new folder icon bitmap.
-            val folderIconBitmap: Bitmap = if (defaultFolderIconRadioButton.isChecked) {
-                // Get the default folder icon drawable.
-                val folderIconDrawable = defaultFolderIconImageView.drawable
-
-                // Convert the folder icon drawable to a bitmap drawable.
-                val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
-
-                // Convert the folder icon bitmap drawable to a bitmap.
-                folderIconBitmapDrawable.bitmap
-            } else {  // Use the WebView favorite icon.
-                // Copy the favorite icon bitmap to the folder icon bitmap.
-                favoriteIconBitmap
-            }
-
-            // Create a folder icon byte array output stream.
+            // Get the selected folder icon drawable.
+            val folderIconDrawable = if (defaultFolderIconRadioButton.isChecked)  // The default folder icon is checked.
+                defaultFolderIconImageView.drawable
+            else if (webpageFavoriteIconRadioButton.isChecked)  // The webpage favorite icon is checked.
+                webpageFavoriteIconImageView.drawable
+            else  // The custom icon is checked.
+                customIconImageView.drawable
+
+            // Convert the folder icon drawable to a bitmap.  Once the minimum API >= 33, this can use Bitmap.Config.RGBA_1010102.
+            val folderIconBitmap = folderIconDrawable.toBitmap(128, 128, Bitmap.Config.ARGB_8888)
+
+            // Create a new folder icon byte array output stream.
             val newFolderIconByteArrayOutputStream = ByteArrayOutputStream()
 
             // Convert the folder icon bitmap to a byte array.  `0` is for lossless compression (the only option for a PNG).
@@ -845,14 +907,11 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             val newFolderIconByteArray = newFolderIconByteArrayOutputStream.toByteArray()
 
             // Update the database.
-            if (!currentFolderIconRadioButton.isChecked && newFolderNameString == oldFolderNameString)  // Only the icon has changed.
-                bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, newFolderIconByteArray)
-            else  // The folder icon and the name have changed.
-                bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString, newFolderIconByteArray)
+            bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, newFolderName, newFolderIconByteArray)
         }
 
         // Update the bookmarks cursor with the current contents of this folder.
-        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -875,13 +934,12 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         val newFolderDatabaseId = newFolderLongArray[0].toInt()
 
         // Set the new folder name.
-        val newFolderName = if (newFolderDatabaseId == 0) {
-            // The new folder is the home folder, represented as `""` in the database.
-            ""
-        } else {
+        val newFolderId = if (newFolderDatabaseId == HOME_FOLDER_DATABASE_ID)
+            // The new folder is the home folder.
+            HOME_FOLDER_ID
+        else
             // Get the new folder name from the database.
-            bookmarksDatabaseHelper.getFolderName(newFolderDatabaseId)
-        }
+            bookmarksDatabaseHelper.getFolderId(newFolderDatabaseId)
 
         // Get a long array with the the database ID of the selected bookmarks.
         val selectedBookmarksLongArray = bookmarksListView.checkedItemIds
@@ -892,11 +950,11 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             val databaseIdInt = databaseIdLong.toInt()
 
             // Move the selected bookmark to the new folder.
-            bookmarksDatabaseHelper.moveToFolder(databaseIdInt, newFolderName)
+            bookmarksDatabaseHelper.moveToFolder(databaseIdInt, newFolderId)
         }
 
         // Update the bookmarks cursor with the current contents of this folder.
-        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
         // Update the list view.
         bookmarksCursorAdapter.changeCursor(bookmarksCursor)
@@ -906,11 +964,11 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
     }
 
     private fun countBookmarkFolderContents(folderDatabaseId: Int): Int {
-        // Get the name of the folder.
-        val folderName = bookmarksDatabaseHelper.getFolderName(folderDatabaseId)
+        // Get the folder ID.
+        val folderId = bookmarksDatabaseHelper.getFolderId(folderDatabaseId)
 
         // Get the contents of the folder.
-        val folderCursor = bookmarksDatabaseHelper.getBookmarkIds(folderName)
+        val folderCursor = bookmarksDatabaseHelper.getBookmarkAndFolderIds(folderId)
 
         // Initialize the bookmark counter.
         var bookmarkCounter = 0
@@ -921,7 +979,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             folderCursor.moveToPosition(i)
 
             // Get the database ID of the item.
-            val itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID))
+            val itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID))
 
             // If this is a folder, recursively count the contents first.
             if (bookmarksDatabaseHelper.isFolder(itemDatabaseId))
@@ -936,11 +994,11 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
     }
 
     private fun deleteBookmarkFolderContents(folderDatabaseId: Int) {
-        // Get the name of the folder.
-        val folderName = bookmarksDatabaseHelper.getFolderName(folderDatabaseId)
+        // Get the folder ID.
+        val folderId = bookmarksDatabaseHelper.getFolderId(folderDatabaseId)
 
         // Get the contents of the folder.
-        val folderCursor = bookmarksDatabaseHelper.getBookmarkIds(folderName)
+        val folderCursor = bookmarksDatabaseHelper.getBookmarkAndFolderIds(folderId)
 
         // Delete each of the bookmarks in the folder.
         for (i in 0 until folderCursor.count) {
@@ -948,7 +1006,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             folderCursor.moveToPosition(i)
 
             // Get the database ID of the item.
-            val itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.ID))
+            val itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID))
 
             // If this is a folder, recursively delete the contents first.
             if (bookmarksDatabaseHelper.isFolder(itemDatabaseId))
@@ -969,7 +1027,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
             bookmarksDeletedSnackbar!!.dismiss()
         } else {  // Go home immediately.
             // Update the bookmarks folder for the bookmarks drawer in the main WebView activity.
-            MainWebViewActivity.currentBookmarksFolder = currentFolder
+            MainWebViewActivity.currentBookmarksFolderId = currentFolderId
 
             // Close the bookmarks drawer and reload the bookmarks list view when returning to the main WebView activity.
             MainWebViewActivity.restartFromBookmarksActivity = true
@@ -1040,7 +1098,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
 
     private fun loadFolder() {
         // Update the bookmarks cursor with the contents of the bookmarks database for the current folder.
-        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder)
+        bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolderId)
 
         // Setup a cursor adapter.
         bookmarksCursorAdapter = object : CursorAdapter(this, bookmarksCursor, false) {
@@ -1055,7 +1113,7 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                 val bookmarkNameTextView = view.findViewById<TextView>(R.id.bookmark_name)
 
                 // Get the favorite icon byte array from the cursor.
-                val favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
+                val favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(FAVORITE_ICON))
 
                 // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
                 val favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.size)
@@ -1064,13 +1122,13 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
                 bookmarkFavoriteIconImageView.setImageBitmap(favoriteIconBitmap)
 
                 // Get the bookmark name from the cursor.
-                val bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+                val bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BOOKMARK_NAME))
 
                 // Display the bookmark name.
                 bookmarkNameTextView.text = bookmarkNameString
 
                 // Make the font bold for folders.
-                if (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1)
+                if (cursor.getInt(cursor.getColumnIndexOrThrow(IS_FOLDER)) == 1)
                     bookmarkNameTextView.typeface = Typeface.DEFAULT_BOLD
                 else  // Reset the font to default for normal bookmarks.
                     bookmarkNameTextView.typeface = Typeface.DEFAULT
@@ -1081,10 +1139,10 @@ class BookmarksActivity : AppCompatActivity(), CreateBookmarkListener, CreateBoo
         bookmarksListView.adapter = bookmarksCursorAdapter
 
         // Set the app bar title.
-        if (currentFolder.isEmpty())
+        if (currentFolderId == HOME_FOLDER_ID)  // The home folder is the current folder.
             appBar.setTitle(R.string.bookmarks)
         else
-            appBar.title = currentFolder
+            appBar.title = bookmarksDatabaseHelper.getFolderName(currentFolderId)
     }
 
     public override fun onDestroy() {