From 96c4a39fe61b2e8a47100fd0c27193847dc3c895 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Mon, 5 Dec 2022 15:25:35 -0700 Subject: [PATCH] Open all bookmarks in a folder on long-press. https://redmine.stoutner.com/issues/926 --- app/src/main/assets/de/guide_interface.html | 2 +- app/src/main/assets/en/guide_interface.html | 2 +- app/src/main/assets/es/guide_interface.html | 2 +- app/src/main/assets/fr/guide_interface.html | 2 +- app/src/main/assets/it/guide_interface.html | 2 +- .../main/assets/pt-rBR/guide_interface.html | 2 +- app/src/main/assets/ru/guide_interface.html | 2 +- app/src/main/assets/tr/guide_interface.html | 2 +- .../activities/MainWebViewActivity.java | 27 +- .../helpers/BookmarksDatabaseHelper.kt | 520 +++++++++--------- 10 files changed, 296 insertions(+), 267 deletions(-) diff --git a/app/src/main/assets/de/guide_interface.html b/app/src/main/assets/de/guide_interface.html index 3ac4cb98..95d00dda 100644 --- a/app/src/main/assets/de/guide_interface.html +++ b/app/src/main/assets/de/guide_interface.html @@ -36,7 +36,7 @@ bis das Menü angezeigt wird und wischen dann, um es zu öffnen. Auf manchen Geräten mit abgerundeten Kanten kann das Ausklappen des Menüs schwierig sein. Daher kann das Lesezeichen-Menü auch über das Options-Menü geöffnet werden.

-

Kurzes Antippen eines Lesezeichens öffnet dieses im aktuellen Tab, langes Drücken öffnet es in einem neuen Tab. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Durch Antippen des obersten Symbols im Lesezeichen-Menü können abgespeicherte Lesezeichen bearbeitet und umgeordnet werden.

diff --git a/app/src/main/assets/en/guide_interface.html b/app/src/main/assets/en/guide_interface.html index 0f3bf03c..7b417a81 100644 --- a/app/src/main/assets/en/guide_interface.html +++ b/app/src/main/assets/en/guide_interface.html @@ -34,7 +34,7 @@ the drawer may be opened by long-pressing on the edge of the screen until the drawer peaks out and then swiping it open. Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.

-

Tapping on a bookmark opens it in the current tab and long-pressing on a bookmark opens it in a new tab. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.

diff --git a/app/src/main/assets/es/guide_interface.html b/app/src/main/assets/es/guide_interface.html index 47dd1e8b..0cd63d48 100644 --- a/app/src/main/assets/es/guide_interface.html +++ b/app/src/main/assets/es/guide_interface.html @@ -37,7 +37,7 @@ A veces puede ser difícil conseguir que el cajón de marcadores llegue a su punto máximo de forma fiable en dispositivos con bordes curvos, por lo que también es posible abrir el cajón de marcadores desde el menú de opciones.

-

Al tocar un marcador se abre en la pestaña actual y al pulsar prolongadamente sobre un marcador se abre en una nueva pestaña. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Al tocar el botón de acción superior flotante en el cajón de marcadores se abre la actividad de marcadores, donde se pueden editar y reorganizar los marcadores.

diff --git a/app/src/main/assets/fr/guide_interface.html b/app/src/main/assets/fr/guide_interface.html index b2a61b7d..76625e1c 100644 --- a/app/src/main/assets/fr/guide_interface.html +++ b/app/src/main/assets/fr/guide_interface.html @@ -38,7 +38,7 @@ Il est parfois difficile de faire apparaître le gestionnaire de favoris de manière fiable sur les appareils aux bords incurvés, c'est pourquoi il est également possible d'ouvrir le gestionnaire de favoris à partir du menu des options.

-

Le fait d'appuyer sur un favori l'ouvre dans l'onglet actuel et le fait d'appuyer longuement sur un favori l'ouvre dans un nouvel onglet. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Si vous appuyez sur le bouton d'action flottant supérieur dans le gestionnaire de favoris, vous ouvrez un volet dans lequel vous pouvez modifier et réorganiser les favoris.

diff --git a/app/src/main/assets/it/guide_interface.html b/app/src/main/assets/it/guide_interface.html index b3bfab9c..f6c736c9 100644 --- a/app/src/main/assets/it/guide_interface.html +++ b/app/src/main/assets/it/guide_interface.html @@ -36,7 +36,7 @@ il cassetto può essere aperto anche tenendo premuto il bordo dello schermo finchè appare il cassetto e quindi scorrendo per aprirlo. A volte può risultare difficile fare in modo che il cassetto dei segnalibri appaia sui dispositivi con i bordi incurvati per cui è possibile aprirlo anche dal menù delle opzioni.

-

Selezionando un segnalibro, viene aperto nella scheda corrente, mentre tenendolo premuto si apre in una nuova scheda. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Se si tocca il pulsante flottante più in alto nel cassetto dei segnalibri viene aperta la scheda dei segnalibri dove è possibile modificarli e riordinarli.

diff --git a/app/src/main/assets/pt-rBR/guide_interface.html b/app/src/main/assets/pt-rBR/guide_interface.html index 3afad7b1..094c0c7c 100644 --- a/app/src/main/assets/pt-rBR/guide_interface.html +++ b/app/src/main/assets/pt-rBR/guide_interface.html @@ -36,7 +36,7 @@ the drawer may be opened by long-pressing on the edge of the screen until the drawer peaks out and then swiping it open. Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.

-

Tapping on a bookmark opens it in the current tab and long-pressing on a bookmark opens it in a new tab. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.

diff --git a/app/src/main/assets/ru/guide_interface.html b/app/src/main/assets/ru/guide_interface.html index 4c7104f8..eaaf3e8e 100644 --- a/app/src/main/assets/ru/guide_interface.html +++ b/app/src/main/assets/ru/guide_interface.html @@ -34,7 +34,7 @@ панель можно открыть длительным нажатием на край экрана до ее появления, а затем смахнув. На устройствах с изогнутыми краями иногда бывает непросто добиться появления панели закладок, поэтому можно открыть ее из меню параметров.

-

При нажатии на закладку она открывается на текущей вкладке, а при длительном нажатии - на новой вкладке. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. При нажатии верхней кнопки действия в панели закладок открывается страница действий с закладками, где их можно редактировать и упорядочивать.

diff --git a/app/src/main/assets/tr/guide_interface.html b/app/src/main/assets/tr/guide_interface.html index 0f3bf03c..7b417a81 100644 --- a/app/src/main/assets/tr/guide_interface.html +++ b/app/src/main/assets/tr/guide_interface.html @@ -34,7 +34,7 @@ the drawer may be opened by long-pressing on the edge of the screen until the drawer peaks out and then swiping it open. Sometimes it can be difficult to get the bookmarks drawer to reliably peak on devices with curved edges, so it is also possible to open the bookmarks drawer from the options menu.

-

Tapping on a bookmark opens it in the current tab and long-pressing on a bookmark opens it in a new tab. +

Tapping on a bookmark opens it in the current tab. Long-pressing on a bookmark opens it in a new tab and long-pressing on a folder opens all the bookmarks it directly contains in new tabs. Tapping the top floating action button in the bookmarks drawer opens the bookmarks activity, where bookmarks can be edited and reorganized.

diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index c0812d0c..3d0013e4 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -3425,14 +3425,26 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Check to see if the bookmark is a folder. if (isFolder) { // The bookmark is a folder. - // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`. - oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME)); + // Get a cursor of all the bookmarks in the folder. + Cursor bookmarksCursor = bookmarksDatabaseHelper.getFolderBookmarks(databaseId); - // Instantiate the edit folder bookmark dialog. - DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon()); + // Move to the first entry in the cursor. + bookmarksCursor.moveToFirst(); - // Show the edit folder bookmark dialog. - editBookmarkFolderDialog.show(getSupportFragmentManager(), getString(R.string.edit_folder)); + // Open each bookmark + for (int i = 0; i < bookmarksCursor.getCount(); i++) { + // Load the bookmark in a new tab, moving to the tab for the first bookmark (i == 0). + addNewTab(bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), (i == 0)); + + // Move to the next bookmark. + bookmarksCursor.moveToNext(); + } + + // Close the cursor. + bookmarksCursor.close(); + + // Close the bookmarks drawer. + drawerLayout.closeDrawer(GravityCompat.END); } else { // The bookmark is not a folder. // Get the bookmark cursor for this ID. Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseId); @@ -3443,6 +3455,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Load the bookmark in a new tab. addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), true); + // Close the cursor. + bookmarkCursor.close(); + // Close the bookmarks drawer. drawerLayout.closeDrawer(GravityCompat.END); } diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.kt index 8804e997..bd90abce 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2022 Soren Stoutner . + * Copyright 2016-2022 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -65,6 +65,36 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK // Code for upgrading the database will be added here when the schema version > 1. } + // Get a cursor of all the folders. + val allFolders: Cursor + get() { + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase + + // Return the cursor with the all the folders. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 ORDER BY $BOOKMARK_NAME ASC", null) + } + + // Get a cursor for all bookmarks and folders. + val allBookmarks: Cursor + get() { + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase + + // Return a cursor with the entire contents of the bookmarks table. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE", null) + } + + // Get a cursor for all bookmarks and folders ordered by display order. + val allBookmarksByDisplayOrder: Cursor + get() { + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase + + // Return a cursor with the entire contents of the bookmarks table ordered by the display order. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE ORDER BY $DISPLAY_ORDER ASC", null) + } + // Create a bookmark. fun createBookmark(bookmarkName: String, bookmarkURL: String, parentFolder: String, displayOrder: Int, favoriteIcon: ByteArray) { // Store the bookmark data in a content values. @@ -122,6 +152,18 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK bookmarksDatabase.close() } + // Delete one bookmark. + fun deleteBookmark(databaseId: Int) { + // Get a writable database handle. + val bookmarksDatabase = this.writableDatabase + + // Deletes the row with the given database ID. + bookmarksDatabase.delete(BOOKMARKS_TABLE, "$ID = $databaseId", null) + + // Close the database handle. + bookmarksDatabase.close() + } + // Get a cursor for the bookmark with the specified database ID. fun getBookmark(databaseId: Int): Cursor { // Get a readable database handle. @@ -131,165 +173,92 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null) } - // Get the folder name for the specified database ID. - fun getFolderName(databaseId: Int): String { + // Get a cursor for all bookmarks and folders by display order except those with the specified IDs. + fun getAllBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase - // Get the cursor for the folder with the specified database ID. - val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null) - - // Move to the first record. - folderCursor.moveToFirst() + // Prepare a string builder to contain the comma-separated list of IDs not to get. + val idsNotToGetStringBuilder = StringBuilder() - // Get the folder name. - val folderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BOOKMARK_NAME)) + // Extract the array of IDs not to get to the string builder. + for (databaseIdLong in exceptIdLongArray) { + // Check to see if there is already a number in the builder. + if (idsNotToGetStringBuilder.isNotEmpty()) { + // This is not the first number, so place a `,` before the new number. + idsNotToGetStringBuilder.append(",") + } - // Close the cursor and the database handle. - folderCursor.close() - bookmarksDatabase.close() + // Add the new number to the builder. + idsNotToGetStringBuilder.append(databaseIdLong) + } - // Return the folder name. - return folderName + // Return a cursor with all the bookmarks except those specified ordered by display order. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", null) } - // Get the database ID for the specified folder name. - fun getFolderDatabaseId(folderName: String): Int { + // Get a cursor for all bookmarks and folders except those with the specified IDs. + fun getAllBookmarksExcept(exceptIdLongArray: LongArray): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase - // SQL escape the folder name. - val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - - // Get the cursor for the folder with the specified name. - val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null) - - // Move to the first record. - folderCursor.moveToFirst() + // Prepare a string builder to contain the comma-separated list of IDs not to get. + val idsNotToGetStringBuilder = StringBuilder() - // Get the database ID. - val databaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID)) + // Extract the array of IDs not to get to the string builder. + for (databaseIdLong in exceptIdLongArray) { + // Check to see if there is already a number in the builder. + if (idsNotToGetStringBuilder.isNotEmpty()) { + // This is not the first number, so place a `,` before the new number. + idsNotToGetStringBuilder.append(",") + } - // Close the cursor and the database handle. - folderCursor.close() - bookmarksDatabase.close() + // Add the new number to the builder. + idsNotToGetStringBuilder.append(databaseIdLong) + } - // Return the database ID. - return databaseId + // Return a cursor with all the bookmarks except those specified. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder)", null) } - // Get a cursor for the specified folder name. - fun getFolder(folderName: String): Cursor { + // Get a cursor with just database ID of bookmarks and folders in the specified folder. This is useful for deleting folders with bookmarks that have favorite icons too large to fit in a cursor. + fun getBookmarkIds(folderName: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase // SQL escape the folder name. val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - // Return the cursor for the specified folder. The cursor can't be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null) - } - - // Get a cursor of all the folders except those specified. - fun getFoldersExcept(exceptFolders: String): Cursor { - // Get a readable database handle. - val bookmarksDatabase = this.readableDatabase - - // Return the cursor of all folders except those specified. Each individual folder in the list has already been SQL escaped. The cursor can't be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME NOT IN ($exceptFolders) ORDER BY $BOOKMARK_NAME ASC", null) - } - - // Get a cursor with all the subfolders of the specified folder. - fun getSubfolders(currentFolder: String): Cursor { - // Get a readable database handle. - val bookmarksDatabase = this.readableDatabase - - // SQL escape the current folder. - val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder) - - // Return the cursor with the subfolders. The cursor can't be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedCurrentFolder AND $IS_FOLDER = 1", null) + // Return a cursor with all the database IDs. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT $ID FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null) } - // Get the name of the parent folder. - fun getParentFolderName(currentFolder: String): String { + // Get a cursor for bookmarks and folders in the specified folder. + fun getBookmarks(folderName: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase - // SQL escape the current folder. - val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder) - - // Get a cursor for the current folder. - val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME = $sqlEscapedCurrentFolder", null) - - // Move to the first record. - bookmarkCursor.moveToFirst() - - // Store the name of the parent folder. - val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER)) - - // Close the cursor and the database. - bookmarkCursor.close() - bookmarksDatabase.close() + // SQL escape the folder name. + val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - // Return the parent folder string. - return parentFolder + // Return a cursor with all the bookmarks in a specified folder. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null) } - // Get the name of the parent folder. - fun getParentFolderName(databaseId: Int): String { + // Get a cursor for bookmarks and folders in the specified folder ordered by display order. + fun getBookmarksByDisplayOrder(folderName: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase - // Get a cursor for the specified database ID. - val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null) - - // Move to the first record. - bookmarkCursor.moveToFirst() - - // Store the name of the parent folder. - val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER)) - - // Close the cursor and the database. - bookmarkCursor.close() - bookmarksDatabase.close() + // SQL escape the folder name. + val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - // Return the parent folder string. - return parentFolder + // Return a cursor with all the bookmarks in the specified folder ordered by display order. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName ORDER BY $DISPLAY_ORDER ASC", null) } - // Get a cursor of all the folders. - val allFolders: Cursor - get() { - // Get a readable database handle. - val bookmarksDatabase = this.readableDatabase - - // Return the cursor with the all the folders. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 ORDER BY $BOOKMARK_NAME ASC", null) - } - - // Get a cursor for all bookmarks and folders. - val allBookmarks: Cursor - get() { - // Get a readable database handle. - val bookmarksDatabase = this.readableDatabase - - // Return a cursor with the entire contents of the bookmarks table. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE", null) - } - - // Get a cursor for all bookmarks and folders ordered by display order. - val allBookmarksByDisplayOrder: Cursor - get() { - // Get a readable database handle. - val bookmarksDatabase = this.readableDatabase - - // Return a cursor with the entire contents of the bookmarks table ordered by the display order. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE ORDER BY $DISPLAY_ORDER ASC", null) - } - - // Get a cursor for all bookmarks and folders except those with the specified IDs. - fun getAllBookmarksExcept(exceptIdLongArray: LongArray): Cursor { + // Get a cursor for bookmarks and folders in the specified folder by display order except those with the specified IDs. + fun getBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray, folderName: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase @@ -308,12 +277,17 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK idsNotToGetStringBuilder.append(databaseIdLong) } - // Return a cursor with all the bookmarks except those specified. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder)", null) + // SQL escape the folder name. + val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) + + // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified ordered by display order. + // The cursor cannot be closed because it will be used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", + null) } - // Get a cursor for all bookmarks and folders by display order except those with the specified IDs. - fun getAllBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray): Cursor { + // Get a cursor for bookmarks and folders in the specified folder except those with the specified IDs. + fun getBookmarksExcept(exceptIdLongArray: LongArray, folderName: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase @@ -332,100 +306,152 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK idsNotToGetStringBuilder.append(databaseIdLong) } - // Return a cursor with all the bookmarks except those specified ordered by display order. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", null) + // SQL escape the folder name. + val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) + + // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder)", null) } - // Get a cursor for bookmarks and folders in the specified folder. - fun getBookmarks(folderName: String): Cursor { + // Get a cursor for the specified folder name. + fun getFolder(folderName: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase // SQL escape the folder name. val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - // Return a cursor with all the bookmarks in a specified folder. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null) + // Return the cursor for the specified folder. The cursor can't be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null) } - // Get a cursor for bookmarks and folders in the specified folder ordered by display order. - fun getBookmarksByDisplayOrder(folderName: String): Cursor { - // Get a readable database handle. - val bookmarksDatabase = this.readableDatabase + fun getFolderBookmarks(folderDatabaseId: Int): Cursor { + // Get the folder name. + val folderName = getFolderName(folderDatabaseId) // SQL escape the folder name. val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - // Return a cursor with all the bookmarks in the specified folder ordered by display order. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName ORDER BY $DISPLAY_ORDER ASC", null) + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase + + // Return a cursor with all the bookmarks in the folder. The cursor cannot be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $IS_FOLDER = 0 ORDER BY $DISPLAY_ORDER ASC", null) } - // Get a cursor with just database ID of bookmarks and folders in the specified folder. This is useful for deleting folders with bookmarks that have favorite icons too large to fit in a cursor. - fun getBookmarkIds(folderName: String): Cursor { + // Get the database ID for the specified folder name. + fun getFolderDatabaseId(folderName: String): Int { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase // SQL escape the folder name. val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) - // Return a cursor with all the database IDs. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT $ID FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName", null) + // Get the cursor for the folder with the specified name. + val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null) + + // Move to the first record. + folderCursor.moveToFirst() + + // Get the database ID. + val databaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(ID)) + + // Close the cursor and the database handle. + folderCursor.close() + bookmarksDatabase.close() + + // Return the database ID. + return databaseId } - // Get a cursor for bookmarks and folders in the specified folder except those with the specified IDs. - fun getBookmarksExcept(exceptIdLongArray: LongArray, folderName: String): Cursor { + // Get the folder name for the specified database ID. + fun getFolderName(databaseId: Int): String { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase - // Prepare a string builder to contain the comma-separated list of IDs not to get. - val idsNotToGetStringBuilder = StringBuilder() + // Get the cursor for the folder with the specified database ID. + val folderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null) - // Extract the array of IDs not to get to the string builder. - for (databaseIdLong in exceptIdLongArray) { - // Check to see if there is already a number in the builder. - if (idsNotToGetStringBuilder.isNotEmpty()) { - // This is not the first number, so place a `,` before the new number. - idsNotToGetStringBuilder.append(",") - } + // Move to the first record. + folderCursor.moveToFirst() - // Add the new number to the builder. - idsNotToGetStringBuilder.append(databaseIdLong) - } + // Get the folder name. + val folderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BOOKMARK_NAME)) - // SQL escape the folder name. - val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) + // Close the cursor and the database handle. + folderCursor.close() + bookmarksDatabase.close() - // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified. The cursor cannot be closed because it is used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder)", null) + // Return the folder name. + return folderName } - // Get a cursor for bookmarks and folders in the specified folder by display order except those with the specified IDs. - fun getBookmarksByDisplayOrderExcept(exceptIdLongArray: LongArray, folderName: String): Cursor { + // Get a cursor of all the folders except those specified. + fun getFoldersExcept(exceptFolders: String): Cursor { // Get a readable database handle. val bookmarksDatabase = this.readableDatabase - // Prepare a string builder to contain the comma-separated list of IDs not to get. - val idsNotToGetStringBuilder = StringBuilder() + // Return the cursor of all folders except those specified. Each individual folder in the list has already been SQL escaped. The cursor can't be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME NOT IN ($exceptFolders) ORDER BY $BOOKMARK_NAME ASC", null) + } - // Extract the array of IDs not to get to the string builder. - for (databaseIdLong in exceptIdLongArray) { - // Check to see if there is already a number in the builder. - if (idsNotToGetStringBuilder.isNotEmpty()) { - // This is not the first number, so place a `,` before the new number. - idsNotToGetStringBuilder.append(",") - } + // Get the name of the parent folder. + fun getParentFolderName(currentFolder: String): String { + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase - // Add the new number to the builder. - idsNotToGetStringBuilder.append(databaseIdLong) - } + // SQL escape the current folder. + val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder) - // SQL escape the folder name. - val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(folderName) + // Get a cursor for the current folder. + val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1 AND $BOOKMARK_NAME = $sqlEscapedCurrentFolder", null) - // Return a cursor with all the bookmarks in the specified folder except for those database IDs specified ordered by display order. - // The cursor cannot be closed because it will be used in the parent activity. - return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedFolderName AND $ID NOT IN ($idsNotToGetStringBuilder) ORDER BY $DISPLAY_ORDER ASC", - null) + // Move to the first record. + bookmarkCursor.moveToFirst() + + // Store the name of the parent folder. + val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER)) + + // Close the cursor and the database. + bookmarkCursor.close() + bookmarksDatabase.close() + + // Return the parent folder string. + return parentFolder + } + + // Get the name of the parent folder. + fun getParentFolderName(databaseId: Int): String { + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase + + // Get a cursor for the specified database ID. + val bookmarkCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $ID = $databaseId", null) + + // Move to the first record. + bookmarkCursor.moveToFirst() + + // Store the name of the parent folder. + val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER)) + + // Close the cursor and the database. + bookmarkCursor.close() + bookmarksDatabase.close() + + // Return the parent folder string. + return parentFolder + } + + // Get a cursor with all the subfolders of the specified folder. + fun getSubfolders(currentFolder: String): Cursor { + // Get a readable database handle. + val bookmarksDatabase = this.readableDatabase + + // SQL escape the current folder. + val sqlEscapedCurrentFolder = DatabaseUtils.sqlEscapeString(currentFolder) + + // Return the cursor with the subfolders. The cursor can't be closed because it is used in the parent activity. + return bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedCurrentFolder AND $IS_FOLDER = 1", null) } // Check if a database ID is a folder. @@ -450,6 +476,46 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK return isFolder } + // Move one bookmark or folder to a new folder. + fun moveToFolder(databaseId: Int, newFolder: String) { + // Get a writable database handle. + val bookmarksDatabase = this.writableDatabase + + // SQL escape the new folder name. + val sqlEscapedNewFolder = DatabaseUtils.sqlEscapeString(newFolder) + + // Get a cursor for all the bookmarks in the new folder ordered by display order. + val newFolderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedNewFolder ORDER BY $DISPLAY_ORDER ASC", null) + + // Set the new display order. + val displayOrder: Int = if (newFolderCursor.count > 0) { // There are already bookmarks in the folder. + // Move to the last bookmark. + newFolderCursor.moveToLast() + + // Set the display order to be one greater that the last bookmark. + newFolderCursor.getInt(newFolderCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) + 1 + } else { // There are no bookmarks in the new folder. + // Set the display order to be `0`. + 0 + } + + // Close the cursor. + newFolderCursor.close() + + // Create a content values. + val bookmarkContentValues = ContentValues() + + // Store the new values. + bookmarkContentValues.put(DISPLAY_ORDER, displayOrder) + bookmarkContentValues.put(PARENT_FOLDER, newFolder) + + // Update the database. + bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null) + + // Close the database handle. + bookmarksDatabase.close() + } + // Update the bookmark name and URL. fun updateBookmark(databaseId: Int, bookmarkName: String, bookmarkUrl: String) { // Initialize a content values. @@ -532,6 +598,24 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK bookmarksDatabase.close() } + // Update the display order for one bookmark or folder. + fun updateDisplayOrder(databaseId: Int, displayOrder: Int) { + // Get a writable database handle. + val bookmarksDatabase = this.writableDatabase + + // Create a content values. + val bookmarkContentValues = ContentValues() + + // Store the new display order. + bookmarkContentValues.put(DISPLAY_ORDER, displayOrder) + + // Update the database. + bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null) + + // Close the database handle. + bookmarksDatabase.close() + } + // Update the folder name. fun updateFolder(databaseId: Int, oldFolderName: String, newFolderName: String) { // Get a writable database handle. @@ -675,74 +759,4 @@ class BookmarksDatabaseHelper(context: Context) : SQLiteOpenHelper(context, BOOK // Close the database handle. bookmarksDatabase.close() } - - // Update the display order for one bookmark or folder. - fun updateDisplayOrder(databaseId: Int, displayOrder: Int) { - // Get a writable database handle. - val bookmarksDatabase = this.writableDatabase - - // Create a content values. - val bookmarkContentValues = ContentValues() - - // Store the new display order. - bookmarkContentValues.put(DISPLAY_ORDER, displayOrder) - - // Update the database. - bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null) - - // Close the database handle. - bookmarksDatabase.close() - } - - // Move one bookmark or folder to a new folder. - fun moveToFolder(databaseId: Int, newFolder: String) { - // Get a writable database handle. - val bookmarksDatabase = this.writableDatabase - - // SQL escape the new folder name. - val sqlEscapedNewFolder = DatabaseUtils.sqlEscapeString(newFolder) - - // Get a cursor for all the bookmarks in the new folder ordered by display order. - val newFolderCursor = bookmarksDatabase.rawQuery("SELECT * FROM $BOOKMARKS_TABLE WHERE $PARENT_FOLDER = $sqlEscapedNewFolder ORDER BY $DISPLAY_ORDER ASC", null) - - // Set the new display order. - val displayOrder: Int = if (newFolderCursor.count > 0) { // There are already bookmarks in the folder. - // Move to the last bookmark. - newFolderCursor.moveToLast() - - // Set the display order to be one greater that the last bookmark. - newFolderCursor.getInt(newFolderCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) + 1 - } else { // There are no bookmarks in the new folder. - // Set the display order to be `0`. - 0 - } - - // Close the cursor. - newFolderCursor.close() - - // Create a content values. - val bookmarkContentValues = ContentValues() - - // Store the new values. - bookmarkContentValues.put(DISPLAY_ORDER, displayOrder) - bookmarkContentValues.put(PARENT_FOLDER, newFolder) - - // Update the database. - bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null) - - // Close the database handle. - bookmarksDatabase.close() - } - - // Delete one bookmark. - fun deleteBookmark(databaseId: Int) { - // Get a writable database handle. - val bookmarksDatabase = this.writableDatabase - - // Deletes the row with the given database ID. - bookmarksDatabase.delete(BOOKMARKS_TABLE, "$ID = $databaseId", null) - - // Close the database handle. - bookmarksDatabase.close() - } -} \ No newline at end of file +} -- 2.43.0