From 871520acac2bd75f528e943c1b2a650017c852b9 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Fri, 22 Sep 2017 14:33:55 -0700 Subject: [PATCH] Disable the edit button in the edit bookmark folder dialog unless some informaiton has changed and the new folder name is valid. https://redmine.stoutner.com/issues/202. --- .../activities/BookmarksActivity.java | 120 +++++++++--------- .../dialogs/CreateBookmarkFolderDialog.java | 7 +- .../dialogs/EditBookmarkFolderDialog.java | 101 +++++++++++++-- .../helpers/BookmarksDatabaseHelper.java | 77 ++++++++--- .../layout/edit_bookmark_folder_dialog.xml | 5 +- app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values/strings.xml | 1 - 9 files changed, 219 insertions(+), 95 deletions(-) diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java index 8b248277..68830965 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java @@ -64,7 +64,7 @@ import java.io.ByteArrayOutputStream; public class BookmarksActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, EditBookmarkDialog.EditBookmarkListener, EditBookmarkFolderDialog.EditBookmarkFolderListener, MoveToFolderDialog.MoveToFolderListener { - // `bookmarksDatabaseHelper` is public static so it can be accessed from `EditBookmarkDialog` and `MoveToFolderDialog`. It is also used in `onCreate()`, + // `bookmarksDatabaseHelper` is public static so it can be accessed from `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog` and `MoveToFolderDialog`. It is also used in `onCreate()`, // `onCreateBookmarkCreate()`, `updateBookmarksListView()`, and `updateBookmarksListViewExcept()`. public static BookmarksDatabaseHelper bookmarksDatabaseHelper; @@ -318,18 +318,18 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Update the display order for the current bookmark. if (i == selectedBookmarkPosition) { // The current bookmark is the selected bookmark. // Move the current bookmark up one. - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i - 1); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i - 1); selectedBookmarkNewPosition = i - 1; } else if ((i + 1) == selectedBookmarkPosition){ // The current bookmark is immediately above the selected bookmark. // Move the current bookmark down one. - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i + 1); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i + 1); } else { // The current bookmark is not changing positions. // Move `bookmarksCursor` to the current bookmark position. bookmarksCursor.moveToPosition(i); // Update the display order only if it is not correct in the database. if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) { - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i); } } } @@ -363,18 +363,18 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Update the display order for the current bookmark. if (i == selectedBookmarkPosition) { // The current bookmark is the selected bookmark. // Move the current bookmark down one. - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i + 1); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i + 1); selectedBookmarkNewPosition = i + 1; } else if ((i - 1) == selectedBookmarkPosition) { // The current bookmark is immediately below the selected bookmark. // Move the bookmark below the selected bookmark up one. - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i - 1); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i - 1); } else { // The current bookmark is not changing positions. // Move `bookmarksCursor` to the current bookmark position. bookmarksCursor.moveToPosition(i); // Update the display order only if it is not correct in the database. if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) { - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i); } } } @@ -497,7 +497,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Update the display order only if it is not correct in the database. if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) { - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(currentBookmarkDatabaseId, i); + bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i); } } break; @@ -657,7 +657,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Move all the bookmarks down one in the display order. for (int i = 0; i < bookmarksListView.getCount(); i++) { int databaseId = (int) bookmarksListView.getItemIdAtPosition(i); - bookmarksDatabaseHelper.updateBookmarkDisplayOrder(databaseId, i + 1); + bookmarksDatabaseHelper.updateDisplayOrder(databaseId, i + 1); } // Create the folder, placing it at the top of the ListView @@ -702,63 +702,69 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma } @Override - public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment) { + public void onEditBookmarkFolder(AppCompatDialogFragment dialogFragment) { // Get the new folder name. EditText editFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext); String newFolderNameString = editFolderNameEditText.getText().toString(); - // Check to see if the new folder name is unique. - Cursor bookmarkFolderCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderNameString); - int existingFoldersWithNewName = bookmarkFolderCursor.getCount(); - bookmarkFolderCursor.close(); - if ( ((existingFoldersWithNewName == 0) || newFolderNameString.equals(oldFolderNameString)) && !newFolderNameString.isEmpty()) { - // Get a long array with the the database ID of the selected folder and convert it to an `int`. - long[] selectedFolderLongArray = bookmarksListView.getCheckedItemIds(); - int selectedFolderDatabaseId = (int) selectedFolderLongArray[0]; - - // Get the `RadioButtons` from the `Dialog`. - RadioButton currentFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton); - RadioButton defaultFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton); - - // Check if the favorite icon has changed. - if (currentFolderIconRadioButton.isChecked()) { - // Update the folder name if it has changed without modifying the favorite icon. - if (!newFolderNameString.equals(oldFolderNameString)) { - bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString); - - // Refresh the `ListView`. `setSelection` scrolls to the position of the folder that was edited. - updateBookmarksListView(currentFolder); - bookmarksListView.setSelection(selectedBookmarkPosition); - } - } else { // Update the folder icon. - // Get the new folder icon `Bitmap`. - Bitmap folderIconBitmap; - if (defaultFolderIconRadioButton.isChecked()) { - // Get the default folder icon `ImageView` from the `Drawable` and convert it to a `Bitmap`. - ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon); - Drawable folderIconDrawable = folderIconImageView.getDrawable(); - BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable; - folderIconBitmap = folderIconBitmapDrawable.getBitmap(); - } else { // Get the web page icon `ImageView` from the `Dialog`. - folderIconBitmap = MainWebViewActivity.favoriteIconBitmap; - } + // Get a long array with the the database ID of the selected folder and convert it to an `int`. + long[] selectedFolderLongArray = bookmarksListView.getCheckedItemIds(); + int selectedFolderDatabaseId = (int) selectedFolderLongArray[0]; + + // Get the `RadioButtons` from the `Dialog`. + RadioButton currentFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton); + RadioButton defaultFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton); + + // Check if the favorite icon has changed. + if (currentFolderIconRadioButton.isChecked()) { // Only the name has changed. + // Update the name in the database. + bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString); + } else if (!currentFolderIconRadioButton.isChecked() && newFolderNameString.equals(oldFolderNameString)) { // Only the icon has changed. + // Get the new folder icon `Bitmap`. + Bitmap folderIconBitmap; + if (defaultFolderIconRadioButton.isChecked()) { + // Get the default folder icon `ImageView` from the `Drawable` and convert it to a `Bitmap`. + ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon); + Drawable folderIconDrawable = folderIconImageView.getDrawable(); + BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable; + folderIconBitmap = folderIconBitmapDrawable.getBitmap(); + } else { // Get the web page icon `ImageView` from the `Dialog`. + folderIconBitmap = MainWebViewActivity.favoriteIconBitmap; + } - // Convert the folder `Bitmap` to a byte array. `0` is for lossless compression (the only option for a PNG). - ByteArrayOutputStream folderIconByteArrayOutputStream = new ByteArrayOutputStream(); - folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, folderIconByteArrayOutputStream); - byte[] folderIconByteArray = folderIconByteArrayOutputStream.toByteArray(); + // Convert the folder `Bitmap` to a byte array. `0` is for lossless compression (the only option for a PNG). + ByteArrayOutputStream folderIconByteArrayOutputStream = new ByteArrayOutputStream(); + folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, folderIconByteArrayOutputStream); + byte[] folderIconByteArray = folderIconByteArrayOutputStream.toByteArray(); + + // Update the folder icon in the database. + bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, folderIconByteArray); + } else { // The folder icon and the name have changed. + // Get the new folder icon `Bitmap`. + Bitmap folderIconBitmap; + if (defaultFolderIconRadioButton.isChecked()) { + // Get the default folder icon `ImageView` from the `Drawable` and convert it to a `Bitmap`. + ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon); + Drawable folderIconDrawable = folderIconImageView.getDrawable(); + BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable; + folderIconBitmap = folderIconBitmapDrawable.getBitmap(); + } else { // Get the web page icon `ImageView` from the `Dialog`. + folderIconBitmap = MainWebViewActivity.favoriteIconBitmap; + } - bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString, folderIconByteArray); + // Convert the folder `Bitmap` to a byte array. `0` is for lossless compression (the only option for a PNG). + ByteArrayOutputStream folderIconByteArrayOutputStream = new ByteArrayOutputStream(); + folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, folderIconByteArrayOutputStream); + byte[] folderIconByteArray = folderIconByteArrayOutputStream.toByteArray(); - // Refresh the `ListView`. `setSelection` scrolls to the position of the folder that was edited. - updateBookmarksListView(currentFolder); - bookmarksListView.setSelection(selectedBookmarkPosition); - } - } else { // Don't edit the folder because the new name is not unique. - String cannot_rename_folder = getResources().getString(R.string.cannot_save_folder) + " \"" + newFolderNameString + "\""; - Snackbar.make(findViewById(R.id.bookmarks_coordinatorlayout), cannot_rename_folder, Snackbar.LENGTH_INDEFINITE).show(); + // Update the folder name and icon in the database. + bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString, folderIconByteArray); } + // Refresh the `ListView`. `setSelection` scrolls to the position of the folder that was edited. + updateBookmarksListView(currentFolder); + bookmarksListView.setSelection(selectedBookmarkPosition - 5); + // Close the contextual action mode. contextualActionMode.finish(); } diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/CreateBookmarkFolderDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/CreateBookmarkFolderDialog.java index 2a324b5b..dfe6cbd8 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/CreateBookmarkFolderDialog.java +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/CreateBookmarkFolderDialog.java @@ -38,9 +38,9 @@ import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; +import com.stoutner.privacybrowser.activities.BookmarksActivity; import com.stoutner.privacybrowser.activities.MainWebViewActivity; import com.stoutner.privacybrowser.R; -import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper; public class CreateBookmarkFolderDialog extends AppCompatDialogFragment { // The public interface is used to send information back to the parent activity. @@ -113,9 +113,6 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment { // The `AlertDialog` must be shown before items in the alert dialog can be modified. alertDialog.show(); - // Initialize the database helper. The two `nulls` do not specify the database name or a `CursorFactory`. The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`. - final BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(getContext(), null, null, 0); - // Get a handle for the create button. final Button createButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); EditText folderNameEditText = (EditText) alertDialog.findViewById(R.id.create_folder_name_edittext); @@ -141,7 +138,7 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment { String folderName = s.toString(); // Check if a folder with the name already exists. - Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(folderName); + Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(folderName); // Enable the create button if the new folder name is not empty and doesn't already exist. createButton.setEnabled(!folderName.isEmpty() && (folderExistsCursor.getCount() == 0)); diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java index ae561354..2a84014e 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java @@ -1,5 +1,5 @@ /* - * Copyright © 2016 Soren Stoutner . + * Copyright © 2016-2017 Soren Stoutner . * * This file is part of Privacy Browser . * @@ -28,14 +28,20 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; +import android.support.annotation.IdRes; import android.support.annotation.NonNull; // We have to use `AppCompatDialogFragment` instead of `DialogFragment` or an error is produced on API <=22. import android.support.v7.app.AppCompatDialogFragment; +import android.text.Editable; +import android.text.TextWatcher; import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; +import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.RadioGroup; import com.stoutner.privacybrowser.activities.BookmarksActivity; import com.stoutner.privacybrowser.activities.MainWebViewActivity; @@ -45,7 +51,7 @@ import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper; public class EditBookmarkFolderDialog extends AppCompatDialogFragment { // The public interface is used to send information back to the parent activity. public interface EditBookmarkFolderListener { - void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment); + void onEditBookmarkFolder(AppCompatDialogFragment dialogFragment); } // `editFolderListener` is used in `onAttach()` and `onCreateDialog`. @@ -104,7 +110,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { @Override public void onClick(DialogInterface dialog, int which) { // Return the `DialogFragment` to the parent activity on save. - editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this); + editBookmarkFolderListener.onEditBookmarkFolder(EditBookmarkFolderDialog.this); } }); @@ -118,9 +124,17 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { // Show the keyboard when the `Dialog` is displayed on the screen. alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); - // We need to show the `AlertDialog` before we can modify items in the layout. + // The `AlertDialog` must be shown before items in the layout can be modified. alertDialog.show(); + // Get handles for layout items in the `AlertDialog`. + final Button editButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); + final RadioButton currentIconRadioButton = (RadioButton) alertDialog.findViewById(R.id.edit_folder_current_icon_radiobutton); + RadioGroup iconRadioGroup = (RadioGroup) alertDialog.findViewById(R.id.edit_folder_icon_radio_group); + + // Initially disable the edit button. + editButton.setEnabled(false); + // Get the current favorite icon byte array from the `Cursor`. byte[] currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)); // Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last. @@ -133,22 +147,89 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { ImageView webPageFavoriteIconImageView = (ImageView) alertDialog.findViewById(R.id.edit_folder_web_page_favorite_icon); webPageFavoriteIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap); - // Load the text for `edit_folder_name_edittext`. - EditText folderNameEditText = (EditText) alertDialog.findViewById(R.id.edit_folder_name_edittext); - folderNameEditText.setText(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))); + // Get the current folder name. + final String currentFolderName = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)); + + // Display the current folder name in `edit_folder_name_edittext`. + final EditText folderNameEditText = (EditText) alertDialog.findViewById(R.id.edit_folder_name_edittext); + folderNameEditText.setText(currentFolderName); + + // Update the status of the edit button when the folder name is changed. + folderNameEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // Do nothing. + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // Do nothing. + } + + @Override + public void afterTextChanged(Editable s) { + // Convert the current text to a string. + String newFolderName = s.toString(); + + // Get a cursor for the new folder name if it exists. + Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(newFolderName); + + // Is the new folder name empty? + boolean folderNameEmpty = newFolderName.isEmpty(); + + // Does the folder name already exist? + boolean folderNameAlreadyExists = (!newFolderName.equals(currentFolderName) && (folderExistsCursor.getCount() > 0)); + + // Has the folder been renamed? + boolean folderRenamed = (!newFolderName.equals(currentFolderName) && !folderNameAlreadyExists); + + // Has the favorite icon changed? + boolean iconChanged = (!currentIconRadioButton.isChecked() && !folderNameAlreadyExists); + + // Enable the create button if something has been edited and the new folder name is valid. + editButton.setEnabled(!folderNameEmpty && (folderRenamed || iconChanged)); + } + }); + + // Update the status of the edit button when the icon is changed. + iconRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { + // Get the new folder name. + String newFolderName = folderNameEditText.getText().toString(); + + // Get a cursor for the new folder name if it exists. + Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(newFolderName); + + // Is the new folder name empty? + boolean folderNameEmpty = newFolderName.isEmpty(); + + // Does the folder name already exist? + boolean folderNameAlreadyExists = (!newFolderName.equals(currentFolderName) && (folderExistsCursor.getCount() > 0)); + + // Has the folder been renamed? + boolean folderRenamed = (!newFolderName.equals(currentFolderName) && !folderNameAlreadyExists); + + // Has the favorite icon changed? + boolean iconChanged = (!currentIconRadioButton.isChecked() && !folderNameAlreadyExists); + + // Enable the create button if something has been edited and the new folder name is valid. + editButton.setEnabled(!folderNameEmpty && (folderRenamed || iconChanged)); + } + }); // Allow the `enter` key on the keyboard to save the bookmark from `edit_bookmark_name_edittext`. folderNameEditText.setOnKeyListener(new View.OnKeyListener() { public boolean onKey(View v, int keyCode, KeyEvent event) { // If the event is a key-down on the "enter" button, select the PositiveButton `Save`. - if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { + if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled. // Trigger `editBookmarkListener` and return the DialogFragment to the parent activity. - editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this); + editBookmarkFolderListener.onEditBookmarkFolder(EditBookmarkFolderDialog.this); // Manually dismiss the `AlertDialog`. alertDialog.dismiss(); // Consume the event. return true; - } else { // If any other key was pressed, do not consume the event. + } else { // If any other key was pressed, or if the edit button is currently disabled, do not consume the event. return false; } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java index 55cc346b..84481518 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java @@ -56,7 +56,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { IS_FOLDER + " boolean, " + FAVORITE_ICON + " blob);"; - // Create the `bookmarks` table if it doesn't exist. + // Create the `bookmarks` table. bookmarksDatabase.execSQL(CREATE_BOOKMARKS_TABLE); } @@ -65,6 +65,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { // Code for upgrading the database will be added here when the schema version > 1. } + // Create a bookmark. public void createBookmark(String bookmarkName, String bookmarkURL, int displayOrder, String parentFolder, byte[] favoriteIcon) { // We need to store the bookmark data in a `ContentValues`. ContentValues bookmarkContentValues = new ContentValues(); @@ -87,6 +88,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { bookmarksDatabase.close(); } + // Create a folder. public void createFolder(String folderName, int displayOrder, String parentFolder, byte[] favoriteIcon) { ContentValues bookmarkContentValues = new ContentValues(); @@ -107,6 +109,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { bookmarksDatabase.close(); } + // Get a `Cursor` for the bookmark with the specified database ID. public Cursor getBookmarkCursor(int databaseId) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -119,6 +122,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_ONE_BOOKMARK, null); } + // Get the folder name for the specified database ID. public String getFolderName (int databaseId) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -142,6 +146,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return folderName; } + // Get a `Cursor` for the specified folder name. public Cursor getFolderCursor(String folderName) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -159,6 +164,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_FOLDER, null); } + // Get a `Cursor` of all the folders except those specified. public Cursor getFoldersCursorExcept(String exceptFolders) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -174,6 +180,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_FOLDERS_EXCEPT, null); } + // Get a `Cursor` with all the subfolders of the specified folder. public Cursor getSubfoldersCursor(String currentFolder) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -191,6 +198,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_SUBFOLDERS, null); } + // Get a `String` with the name of the parent folder. public String getParentFolder(String currentFolder) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -216,6 +224,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return parentFolder; } + // Get a `Cursor` of all the folders. public Cursor getAllFoldersCursor() { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -229,6 +238,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_ALL_FOLDERS, null); } + // Get a `Cursor` for all bookmarks and folders. public Cursor getAllBookmarksCursor() { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -241,6 +251,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_ALL_BOOKMARKS, null); } + // Get a `Cursor` for all bookmarks and folders in the specified folder ordered by display order. public Cursor getAllBookmarksCursorByDisplayOrder(String folderName) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -257,6 +268,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_ALL_BOOKMARKS, null); } + // Get a `Cursor` for all bookmarks and folders in the specified folder except for a specific list of IDs. public Cursor getBookmarksCursorExcept(long[] exceptIdLongArray, String folderName) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -287,6 +299,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return bookmarksDatabase.rawQuery(GET_All_BOOKMARKS_EXCEPT_SPECIFIED, null); } + // Check if a database ID is a folder. public boolean isFolder(int databaseId) { // Get a readable database handle. SQLiteDatabase bookmarksDatabase = this.getReadableDatabase(); @@ -309,6 +322,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { return isFolder; } + // Update the bookmark name and URL. public void updateBookmark(int databaseId, String bookmarkName, String bookmarkUrl) { // Store the updated values in `bookmarkContentValues`. ContentValues bookmarkContentValues = new ContentValues(); @@ -326,6 +340,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { bookmarksDatabase.close(); } + // Update the bookmark name, URL, and favorite icon. public void updateBookmark(int databaseId, String bookmarkName, String bookmarkUrl, byte[] favoriteIcon) { // Store the updated values in `bookmarkContentValues`. ContentValues bookmarkContentValues = new ContentValues(); @@ -344,64 +359,77 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { bookmarksDatabase.close(); } + // Update the folder name. public void updateFolder(int databaseId, String oldFolderName, String newFolderName) { // Get a writable database handle. SQLiteDatabase bookmarksDatabase = this.getWritableDatabase(); - // Update the folder first. Store the updated values in `folderContentValues`. + // Update the folder first. Store the new folder name in `folderContentValues`. ContentValues folderContentValues = new ContentValues(); - folderContentValues.put(BOOKMARK_NAME, newFolderName); // Run the update on the folder. The last argument is `null` because there are no `whereArgs`. bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, _ID + " = " + databaseId, null); - - // Update the bookmarks inside the folder with the new parent folder name. + // Update the bookmarks inside the folder. Store the new parent folder name in `bookmarkContentValues`. ContentValues bookmarkContentValues = new ContentValues(); - bookmarkContentValues.put(PARENT_FOLDER, newFolderName); // SQL escape `oldFolderName`. oldFolderName = DatabaseUtils.sqlEscapeString(oldFolderName); - // Run the update on the bookmarks. The last argument is `null` because there are no `whereArgs`. + // Run the update on all the bookmarks that currently list `oldFolderName` as their parent folder. The last argument is `null` because there are no `whereArgs`. bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, PARENT_FOLDER + " = " + oldFolderName, null); // Close the database handle. bookmarksDatabase.close(); } + // Update the folder icon. + public void updateFolder(int databaseId, byte[] folderIcon) { + // Get a writable database handle. + SQLiteDatabase bookmarksDatabase = this.getWritableDatabase(); + + // Store the updated icon in `folderContentValues`. + ContentValues folderContentValues = new ContentValues(); + folderContentValues.put(FAVORITE_ICON, folderIcon); + + // Run the update on the folder. The last argument is `null` because there are no `whereArgs`. + bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, _ID + " = " + databaseId, null); + + // Close the database handle. + bookmarksDatabase.close(); + } + + // Update the folder name and icon. public void updateFolder(int databaseId, String oldFolderName, String newFolderName, byte[] folderIcon) { // Get a writable database handle. SQLiteDatabase bookmarksDatabase = this.getWritableDatabase(); // Update the folder first. Store the updated values in `folderContentValues`. ContentValues folderContentValues = new ContentValues(); - folderContentValues.put(BOOKMARK_NAME, newFolderName); folderContentValues.put(FAVORITE_ICON, folderIcon); // Run the update on the folder. The last argument is `null` because there are no `whereArgs`. bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, _ID + " = " + databaseId, null); - - // Update the bookmarks inside the folder with the new parent folder name. + // Update the bookmarks inside the folder. Store the new parent folder name in `bookmarkContentValues`. ContentValues bookmarkContentValues = new ContentValues(); - bookmarkContentValues.put(PARENT_FOLDER, newFolderName); // SQL escape `oldFolderName`. oldFolderName = DatabaseUtils.sqlEscapeString(oldFolderName); - // Run the update on the bookmarks. The last argument is `null` because there are no `whereArgs`. + // Run the update on all the bookmarks that currently list `oldFolderName` as their parent folder. The last argument is `null` because there are no `whereArgs`. bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, PARENT_FOLDER + " = " + oldFolderName, null); // Close the database handle. bookmarksDatabase.close(); } - public void updateBookmarkDisplayOrder(int databaseId, int displayOrder) { + // Update the display order for one bookmark or folder. + public void updateDisplayOrder(int databaseId, int displayOrder) { // Get a writable database handle. SQLiteDatabase bookmarksDatabase = this.getWritableDatabase(); @@ -416,24 +444,38 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { bookmarksDatabase.close(); } + // Move one bookmark or folder to a new folder. public void moveToFolder(int databaseId, String newFolder) { // Get a writable database handle. SQLiteDatabase bookmarksDatabase = this.getWritableDatabase(); - // Get the highest `DISPLAY_ORDER` in the new folder + // SQL escape the new folder name. String newFolderSqlEscaped = DatabaseUtils.sqlEscapeString(newFolder); + + // Prepare a SQL query to select all the bookmarks in the new folder. final String NEW_FOLDER = "SELECT * FROM " + BOOKMARKS_TABLE + " WHERE " + PARENT_FOLDER + " = " + newFolderSqlEscaped + " ORDER BY " + DISPLAY_ORDER + " ASC"; - // The second argument is `null` because there are no `selectionArgs`. + + // Get a cursor for all the bookmarks in the new folder. The second argument is `null` because there are no `selectionArgs`. Cursor newFolderCursor = bookmarksDatabase.rawQuery(NEW_FOLDER, null); + + // Instantiate a variable to store the display order after the move. int displayOrder; - if (newFolderCursor.getCount() > 0) { + + // Set the new display order. + if (newFolderCursor.getCount() > 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. displayOrder = newFolderCursor.getInt(newFolderCursor.getColumnIndex(DISPLAY_ORDER)) + 1; - } else { + } else { // There are no bookmarks in the new folder. + // Set the display order to be `0`. displayOrder = 0; } + + // Close the new folder `Cursor`. newFolderCursor.close(); // Store the new values in `bookmarkContentValues`. @@ -448,6 +490,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper { bookmarksDatabase.close(); } + // Delete one bookmark. public void deleteBookmark(int databaseId) { // Get a writable database handle. SQLiteDatabase bookmarksDatabase = this.getWritableDatabase(); diff --git a/app/src/main/res/layout/edit_bookmark_folder_dialog.xml b/app/src/main/res/layout/edit_bookmark_folder_dialog.xml index f7d69b65..0ac31586 100644 --- a/app/src/main/res/layout/edit_bookmark_folder_dialog.xml +++ b/app/src/main/res/layout/edit_bookmark_folder_dialog.xml @@ -75,6 +75,7 @@ @@ -112,7 +113,6 @@ android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_marginTop="6dp" - android:layout_marginBottom="12dp" android:layout_marginStart="4dp" android:layout_marginEnd="4dp" > @@ -124,7 +124,8 @@ android:layout_width="match_parent" android:hint="@string/folder_name" android:imeOptions="actionGo" - android:inputType="textUri" /> + android:inputType="textUri" + android:selectAllOnFocus="true" /> Name des Ordners URL für das Lesezeichen Ordnernamen müssen einmalig sein - Kann diesen Ordner nicht umbenennen, da der neue Name bereits existiert: Lesezeichen Bearbeiten Ordner Bearbeiten In Ordner verschieben diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 894bd333..6b25f87a 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -170,7 +170,6 @@ Nombre de carpeta Marcador URL Los nombres de carpetas deben ser únicos - No se guardó la carpeta porque el nuevo nombre no fue único: Editar marcador Editar carpeta Mover a carpeta diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 7fdaa3e2..ddb3d4e5 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -172,7 +172,6 @@ Nome Cartella URL Segnalibro I nomi delle cartelle devono essere unici - Non è possibile salvare la cartella perché già esistente: Modifica Segnalibro Modifica Cartella Sposta nella Cartella diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 863b9670..42310bb4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -175,7 +175,6 @@ Folder name Bookmark URL Folder names must be unique - Cannot save the folder because the new name is not unique: Edit Bookmark Edit Folder Move to Folder -- 2.43.0