From 65ff2d87f3a8fd1c26a26678498a7451e76ebb16 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Fri, 6 Oct 2017 17:41:31 -0700 Subject: [PATCH] Finish creating the bookmark drawer. https://redmine.stoutner.com/issues/132 --- .../activities/BookmarksActivity.java | 67 ++-- .../activities/MainWebViewActivity.java | 319 ++++++++++++++++-- .../dialogs/CreateBookmarkFolderDialog.java | 13 +- .../dialogs/EditBookmarkDialog.java | 63 ++-- .../dialogs/EditBookmarkFolderDialog.java | 62 +++- .../fragments/AboutTabFragment.java | 23 +- .../fragments/GuideTabFragment.java | 21 +- .../res/drawable/block_ads_disabled_dark.xml | 2 +- .../res/drawable/block_ads_disabled_light.xml | 2 +- .../res/drawable/block_ads_enabled_dark.xml | 2 +- .../res/drawable/block_ads_enabled_light.xml | 2 +- .../{bookmarks.xml => bookmarks_dark.xml} | 6 +- app/src/main/res/drawable/bookmarks_light.xml | 13 + app/src/main/res/layout/main_drawerlayout.xml | 8 + .../main/res/menu/webview_navigation_menu.xml | 31 +- 15 files changed, 488 insertions(+), 146 deletions(-) rename app/src/main/res/drawable/{bookmarks.xml => bookmarks_dark.xml} (54%) create mode 100644 app/src/main/res/drawable/bookmarks_light.xml 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 6ea013c9..97b4f3a6 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java @@ -64,16 +64,15 @@ 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 `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog` and `MoveToFolderDialog`. It is also used in `onCreate()`, `onOptionsItemSelected()`, - // `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`, and `loadFolder(). + // `bookmarksDatabaseHelper` is public static so it can be accessed from `MoveToFolderDialog`. It is also used in `onCreate()`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, + // `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`, and `loadFolder(). public static BookmarksDatabaseHelper bookmarksDatabaseHelper; // `currentFolder` is public static so it can be accessed from `MoveToFolderDialog`. // It is used in `onCreate`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `loadFolder()`. public static String currentFolder; - // `checkedItemIds` is public static so it can be accessed from `EditBookmarkDialog`, `EditBookmarkFolderDialog`, and `MoveToFolderDialog`. - // It is also used in `onCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `updateMoveIcons()`. + // `checkedItemIds` is public static so it can be accessed from `MoveToFolderDialog`. It is also used in `onCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `updateMoveIcons()`. public static long[] checkedItemIds; @@ -114,6 +113,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Run the default commands. super.onCreate(savedInstanceState); + // Get the intent that launched the activity. + Intent launchingIntent = getIntent(); + + // Get the current folder from the `Intent`. + currentFolder = launchingIntent.getStringExtra("Current Folder"); + // Set the content view. setContentView(R.layout.bookmarks_coordinatorlayout); @@ -136,9 +141,6 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`. bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this, null, null, 0); - // Set currentFolder to the home folder, which is `""` in the database. - currentFolder = ""; - // Load the home folder. loadFolder(); @@ -164,6 +166,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Get the bookmark URL and assign it to `formattedUrlString`. `mainWebView` will automatically reload when `BookmarksActivity` closes. MainWebViewActivity.formattedUrlString = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)); + // Update the bookmarks folder for the bookmarks drawer in `MainWebViewActivity`. + MainWebViewActivity.currentBookmarksFolder = currentFolder; + + // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`. + MainWebViewActivity.restartFromBookmarksActivity = true; + // Return to `MainWebViewActivity`. NavUtils.navigateUpFromSameTask(bookmarksActivity); } @@ -380,23 +388,23 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Get the position of the selected bookmark. Only one bookmark is selected when `edit_bookmark_down` is enabled. selectedBookmarkPosition = selectedBookmarksPositionsSparseBooleanArray.keyAt(0); - // Move to the selected database ID and find out if it is a folder. + // Move to the selected position and find out if it is a folder. bookmarksCursor.moveToPosition(selectedBookmarkPosition); boolean isFolder = (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1); - // Store `checkedItemIds` for use by the `AlertDialog`. - checkedItemIds = bookmarksListView.getCheckedItemIds(); + // Get the selected bookmark database ID. + int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper._ID)); if (isFolder) { // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`. oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)); - // Show the `EditBookmarkFolderDialog` `AlertDialog` and name the instance `@string/edit_folder`. - AppCompatDialogFragment editFolderDialog = new EditBookmarkFolderDialog(); + // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`. + AppCompatDialogFragment editFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId); editFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder)); } else { - // Show the `EditBookmarkDialog` `AlertDialog` and name the instance `@string/edit_bookmark`. - AppCompatDialogFragment editBookmarkDialog = new EditBookmarkDialog(); + // Show the edit bookmark `AlertDialog` and name the instance `@string/edit_bookmark`. + AppCompatDialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId); editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark)); } break; @@ -553,6 +561,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma switch (menuItemId) { case android.R.id.home: // The home arrow is identified as `android.R.id.home`, not just `R.id.home`. if (currentFolder.isEmpty()) { // Currently in the home folder. + // Update the bookmarks folder for the bookmarks drawer in `MainWebViewActivity`. + MainWebViewActivity.currentBookmarksFolder = ""; + + // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`. + MainWebViewActivity.restartFromBookmarksActivity = true; + // Return to `MainWebViewActivity`. NavUtils.navigateUpFromSameTask(this); } else { // Currently in a subfolder. @@ -586,6 +600,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma @Override public void onBackPressed() { if (currentFolder.isEmpty()) { // Currently in the home folder. + // Update the bookmarks folder for the bookmarks drawer in `MainWebViewActivity`. + MainWebViewActivity.currentBookmarksFolder = ""; + + // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`. + MainWebViewActivity.restartFromBookmarksActivity = true; + // Exit `BookmarksActivity`. super.onBackPressed(); } else { // Currently in a subfolder. @@ -607,9 +627,8 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma String bookmarkNameString = createBookmarkNameEditText.getText().toString(); String bookmarkUrlString = createBookmarkUrlEditText.getText().toString(); - // Convert the favoriteIcon Bitmap to a byte array. + // Convert the favoriteIcon Bitmap to a byte array. `0` is for lossless compression (the only option for a PNG). ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream(); - // `0` is for lossless compression (the only option for a PNG). MainWebViewActivity.favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream); byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray(); @@ -675,7 +694,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma } @Override - public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment) { + public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) { // Get handles for the views from `dialogFragment`. EditText editBookmarkNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext); EditText editBookmarkUrlEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext); @@ -685,12 +704,6 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma String bookmarkNameString = editBookmarkNameEditText.getText().toString(); String bookmarkUrlString = editBookmarkUrlEditText.getText().toString(); - // Get an array of the selected row IDs. - long[] selectedBookmarksLongArray = bookmarksListView.getCheckedItemIds(); - - // Get the database ID of the selected bookmark. Editing a bookmark is only possible where only one item is selected. - int selectedBookmarkDatabaseId = (int) selectedBookmarksLongArray[0]; - // Update the bookmark. if (currentBookmarkIconRadioButton.isChecked()) { // Update the bookmark without changing the favorite icon. bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString); @@ -715,7 +728,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma } @Override - public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment) { + public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId) { // Get handles for the views from `dialogFragment`. EditText editFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext); RadioButton currentFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton); @@ -725,12 +738,6 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma // Get the new folder name. String newFolderNameString = editFolderNameEditText.getText().toString(); - // Get an array of the selected row IDs. - long[] selectedBookmarksLongArray = bookmarksListView.getCheckedItemIds(); - - // Get the database ID of the selected bookmark. Editing a folder is only possible where only one item is selected. - int selectedFolderDatabaseId = (int) selectedBookmarksLongArray[0]; - // Check if the favorite icon has changed. if (currentFolderIconRadioButton.isChecked()) { // Only the name has changed. // Update the name in the database. 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 6bc302ad..bb7ae1de 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -97,14 +97,19 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; +import android.widget.RadioButton; import android.widget.RelativeLayout; import android.widget.TextView; import com.stoutner.privacybrowser.BannerAd; import com.stoutner.privacybrowser.BuildConfig; import com.stoutner.privacybrowser.R; +import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog; +import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog; import com.stoutner.privacybrowser.dialogs.CreateHomeScreenShortcutDialog; import com.stoutner.privacybrowser.dialogs.DownloadImageDialog; +import com.stoutner.privacybrowser.dialogs.EditBookmarkDialog; +import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDialog; import com.stoutner.privacybrowser.dialogs.HttpAuthenticationDialog; import com.stoutner.privacybrowser.dialogs.PinnedSslCertificateMismatchDialog; import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog; @@ -117,6 +122,7 @@ import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog; import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; @@ -132,9 +138,9 @@ import java.util.Map; import java.util.Set; // We need to use AppCompatActivity from android.support.v7.app.AppCompatActivity to have access to the SupportActionBar until the minimum API is >= 21. -public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener, - HttpAuthenticationDialog.HttpAuthenticationListener, PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, DownloadFileDialog.DownloadFileListener, - DownloadImageDialog.DownloadImageListener, UrlHistoryDialog.UrlHistoryListener { +public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener, + DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, EditBookmarkDialog.EditBookmarkListener, EditBookmarkFolderDialog.EditBookmarkFolderListener, HttpAuthenticationDialog.HttpAuthenticationListener, + NavigationView.OnNavigationItemSelectedListener, PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener { // `darkTheme` is public static so it can be accessed from `AboutActivity`, `GuideActivity`, `AddDomainDialog`, `SettingsActivity`, `DomainsActivity`, `DomainsListFragment`, `BookmarksActivity`, `BookmarksDatabaseViewActivity`, // `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `DownloadFileDialog`, `DownloadImageDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `HttpAuthenticationDialog`, `MoveToFolderDialog`, `SslCertificateErrorDialog`, `UrlHistoryDialog`, @@ -142,7 +148,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation public static boolean darkTheme; // `favoriteIconBitmap` is public static so it can be accessed from `CreateHomeScreenShortcutDialog`, `BookmarksActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, - // and `ViewSslCertificateDialog`. It is also used in `onCreate()`, `onCreateHomeScreenShortcutCreate()`, and `applyDomainSettings`. + // and `ViewSslCertificateDialog`. It is also used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onCreateHomeScreenShortcutCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `applyDomainSettings()`. public static Bitmap favoriteIconBitmap; // `formattedUrlString` is public static so it can be accessed from `BookmarksActivity`, `CreateBookmarkDialog`, and `AddDomainDialog`. @@ -167,6 +173,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // `reloadUrlOnRestart` is public static so it can be accessed from `SettingsFragment`. It is also used in `onRestart()`. public static boolean loadUrlOnRestart; + // `restartFromBookmarksActivity` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onRestart()`. + public static boolean restartFromBookmarksActivity; + + // `currentBookmarksFolder` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onCreate()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and + // `loadBookmarksFolder()`. + public static String currentBookmarksFolder; + // The pinned domain SSL Certificate variables are public static so they can be accessed from `PinnedSslCertificateMismatchDialog`. They are also used in `onCreate()` and `applyDomainSettings()`. public static int domainSettingsDatabaseId; public static String pinnedDomainSslIssuedToCNameString; @@ -188,7 +201,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // `favoriteIconDefaultBitmap` is used in `onCreate()` and `applyDomainSettings`. private Bitmap favoriteIconDefaultBitmap; - // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`. + // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, `onBackPressed()`, and `onRestart()`. private DrawerLayout drawerLayout; // `rootCoordinatorLayout` is used in `onCreate()` and `applyAppSettings()`. @@ -336,18 +349,24 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // `pinnedDomainSslCertificate` is used in `onCreate()` and `applyDomainSettings()`. private boolean pinnedDomainSslCertificate; - // `bookmarksDatabaseHelper` is used in `onCreate()` and `loadBookmarksFolder()`. + // `bookmarksDatabaseHelper` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`. private BookmarksDatabaseHelper bookmarksDatabaseHelper; - // `bookmarksListView` is used in `onCreate()` and `loadBookmarksFolder()`. + // `bookmarksListView` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, and `loadBookmarksFolder()`. private ListView bookmarksListView; - // `currentBookmarksFolder` is used in `onCreate()`, `onBackPressed()`, and `loadBookmarksFolder()`. - private String currentBookmarksFolder; - // `bookmarksTitleTextView` is used in `onCreate()` and `loadBookmarksFolder()`. private TextView bookmarksTitleTextView; + // `bookmarksCursor` is used in `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`. + private Cursor bookmarksCursor; + + // `bookmarksCursorAdapter` is used in `onCreateBookmark()`, `onCreateBookmarkFolder()` `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`. + private CursorAdapter bookmarksCursorAdapter; + + // `oldFolderNameString` is used in `onCreate()` and `onSaveEditBookmarkFolder()`. + private String oldFolderNameString; + @Override // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled. The whole premise of Privacy Browser is built around an understanding of these dangers. @SuppressLint("SetJavaScriptEnabled") @@ -467,7 +486,8 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout); bookmarksListView = (ListView) findViewById(R.id.bookmarks_drawer_listview); bookmarksTitleTextView = (TextView) findViewById(R.id.bookmarks_title_textview); - FloatingActionButton createBookmarksFolderFab = (FloatingActionButton) findViewById(R.id.create_bookmark_folder_fab); + FloatingActionButton launchBookmarksActivityFab = (FloatingActionButton) findViewById(R.id.launch_bookmarks_activity_fab); + FloatingActionButton createBookmarkFolderFab = (FloatingActionButton) findViewById(R.id.create_bookmark_folder_fab); FloatingActionButton createBookmarkFab = (FloatingActionButton) findViewById(R.id.create_bookmark_fab); mainWebViewRelativeLayout = (RelativeLayout) findViewById(R.id.main_webview_relativelayout); mainWebView = (WebView) findViewById(R.id.main_webview); @@ -479,15 +499,52 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Set the bookmarks drawer resources according to the theme. This can't be done in the layout due to compatibility issues with the `DrawerLayout` support widget. if (darkTheme) { - createBookmarksFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_dark)); + launchBookmarksActivityFab.setImageDrawable(getResources().getDrawable(R.drawable.bookmarks_dark)); + createBookmarkFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_dark)); createBookmarkFab.setImageDrawable(getResources().getDrawable(R.drawable.create_bookmark_dark)); bookmarksListView.setBackgroundColor(getResources().getColor(R.color.gray_850)); } else { - createBookmarksFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_light)); + launchBookmarksActivityFab.setImageDrawable(getResources().getDrawable(R.drawable.bookmarks_light)); + createBookmarkFolderFab.setImageDrawable(getResources().getDrawable(R.drawable.create_folder_light)); createBookmarkFab.setImageDrawable(getResources().getDrawable(R.drawable.create_bookmark_light)); bookmarksListView.setBackgroundColor(getResources().getColor(R.color.white)); } + // Set the launch bookmarks activity FAB to launch the bookmarks activity. + launchBookmarksActivityFab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // Create an intent to launch the bookmarks activity. + Intent bookmarksIntent = new Intent(getApplicationContext(), BookmarksActivity.class); + + // Include the current folder with the `Intent`. + bookmarksIntent.putExtra("Current Folder", currentBookmarksFolder); + + // Make it so. + startActivity(bookmarksIntent); + } + }); + + // Set the create new bookmark folder FAB to display the `AlertDialog`. + createBookmarkFolderFab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // Show the `CreateBookmarkFolderDialog` `AlertDialog` and name the instance `@string/create_folder`. + AppCompatDialogFragment createBookmarkFolderDialog = new CreateBookmarkFolderDialog(); + createBookmarkFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.create_folder)); + } + }); + + // Set the create new bookmark FAB to display the `AlertDialog`. + createBookmarkFab.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + // Show the `CreateBookmarkDialog` `AlertDialog` and name the instance `@string/create_bookmark`. + AppCompatDialogFragment createBookmarkDialog = new CreateBookmarkDialog(); + createBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.create_bookmark)); + } + }); + // Create a double-tap listener to toggle full-screen mode. final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { // Override `onDoubleTap()`. All other events are handled using the default settings. @@ -694,6 +751,33 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } }); + bookmarksListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + // Convert the database ID from `long` to `int`. + int databaseId = (int) id; + + // Find out if the selected bookmark is a folder. + boolean isFolder = bookmarksDatabaseHelper.isFolder(databaseId); + + if (isFolder) { + // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`. + oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)); + + // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`. + AppCompatDialogFragment editFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId); + editFolderDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder)); + } else { + // Show the edit bookmark `AlertDialog` and name the instance `@string/edit_bookmark`. + AppCompatDialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId); + editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark)); + } + + // Consume the event. + return true; + } + }); + // The `DrawerListener` allows us to update the Navigation Menu. drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() { @Override @@ -1284,6 +1368,18 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Reset `loadUrlOnRestart. loadUrlOnRestart = false; } + + // + if (restartFromBookmarksActivity) { + // Close the bookmarks drawer. + drawerLayout.closeDrawer(GravityCompat.END); + + // Reload the bookmarks drawer. + loadBookmarksFolder(); + + // Reset `restartFromBookmarksActivity`. + restartFromBookmarksActivity = false; + } } // `onResume()` runs after `onStart()`, which runs after `onCreate()` and `onRestart()`. @@ -1847,12 +1943,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation urlHistoryDialogFragment.show(getSupportFragmentManager(), getString(R.string.history)); break; - case R.id.bookmarks: - // Launch BookmarksActivity. - Intent bookmarksIntent = new Intent(this, BookmarksActivity.class); - startActivity(bookmarksIntent); - break; - case R.id.downloads: // Launch the system Download Manager. Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS); @@ -1863,22 +1953,22 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation startActivity(downloadManagerIntent); break; - case R.id.settings: + case R.id.domains: // Reset `currentDomainName` so that domain settings are reapplied after returning to `MainWebViewActivity`. currentDomainName = ""; - // Launch `SettingsActivity`. - Intent settingsIntent = new Intent(this, SettingsActivity.class); - startActivity(settingsIntent); + // Launch `DomainsActivity`. + Intent domainsIntent = new Intent(this, DomainsActivity.class); + startActivity(domainsIntent); break; - case R.id.domains: + case R.id.settings: // Reset `currentDomainName` so that domain settings are reapplied after returning to `MainWebViewActivity`. currentDomainName = ""; - // Launch `DomainsActivity`. - Intent domainsIntent = new Intent(this, DomainsActivity.class); - startActivity(domainsIntent); + // Launch `SettingsActivity`. + Intent settingsIntent = new Intent(this, SettingsActivity.class); + startActivity(settingsIntent); break; case R.id.guide: @@ -2224,6 +2314,82 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } } + @Override + public void onCreateBookmark(AppCompatDialogFragment dialogFragment) { + // Get the `EditTexts` from the `dialogFragment`. + EditText createBookmarkNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.create_bookmark_name_edittext); + EditText createBookmarkUrlEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.create_bookmark_url_edittext); + + // Extract the strings from the `EditTexts`. + String bookmarkNameString = createBookmarkNameEditText.getText().toString(); + String bookmarkUrlString = createBookmarkUrlEditText.getText().toString(); + + // Convert the favoriteIcon Bitmap to a byte array. `0` is for lossless compression (the only option for a PNG). + ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream(); + favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream); + byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray(); + + // Display the new bookmark below the current items in the (0 indexed) list. + int newBookmarkDisplayOrder = bookmarksListView.getCount(); + + // Create the bookmark. + bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, newBookmarkDisplayOrder, currentBookmarksFolder, favoriteIconByteArray); + + // Update `bookmarksCursor` with the current contents of this folder. + bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder); + + // Update the `ListView`. + bookmarksCursorAdapter.changeCursor(bookmarksCursor); + + // Scroll to the new bookmark. + bookmarksListView.setSelection(newBookmarkDisplayOrder); + } + + @Override + public void onCreateBookmarkFolder(AppCompatDialogFragment dialogFragment) { + // Get handles for the views in `dialogFragment`. + EditText createFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.create_folder_name_edittext); + RadioButton defaultFolderIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon_radiobutton); + ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon); + + // Get new folder name string. + String folderNameString = createFolderNameEditText.getText().toString(); + + // Get the new folder icon `Bitmap`. + Bitmap folderIconBitmap; + if (defaultFolderIconRadioButton.isChecked()) { // Use the default folder icon. + // Get the default folder icon and convert it to a `Bitmap`. + Drawable folderIconDrawable = folderIconImageView.getDrawable(); + BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable; + folderIconBitmap = folderIconBitmapDrawable.getBitmap(); + } else { // Use the `WebView` favorite icon. + folderIconBitmap = favoriteIconBitmap; + } + + // Convert `folderIconBitmap` 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(); + + // 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.updateDisplayOrder(databaseId, i + 1); + } + + // Create the folder, placing it at the top of the ListView + bookmarksDatabaseHelper.createFolder(folderNameString, 0, currentBookmarksFolder, folderIconByteArray); + + // Update `bookmarksCursor` with the current contents of this folder. + bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder); + + // Update the `ListView`. + bookmarksCursorAdapter.changeCursor(bookmarksCursor); + + // Scroll to the new folder. + bookmarksListView.setSelection(0); + } + @Override public void onCreateHomeScreenShortcut(AppCompatDialogFragment dialogFragment) { // Get shortcutNameEditText from the alert dialog. @@ -2338,6 +2504,99 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } } + @Override + public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) { + // Get handles for the views from `dialogFragment`. + EditText editBookmarkNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext); + EditText editBookmarkUrlEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext); + RadioButton currentBookmarkIconRadioButton = (RadioButton) dialogFragment.getDialog().findViewById(R.id.edit_bookmark_current_icon_radiobutton); + + // Store the bookmark strings. + String bookmarkNameString = editBookmarkNameEditText.getText().toString(); + String bookmarkUrlString = editBookmarkUrlEditText.getText().toString(); + + // Update the bookmark. + if (currentBookmarkIconRadioButton.isChecked()) { // Update the bookmark without changing the favorite icon. + bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString); + } else { // Update the bookmark using the `WebView` favorite icon. + // Convert the favorite icon to a byte array. `0` is for lossless compression (the only option for a PNG). + ByteArrayOutputStream newFavoriteIconByteArrayOutputStream = new ByteArrayOutputStream(); + favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, newFavoriteIconByteArrayOutputStream); + byte[] newFavoriteIconByteArray = newFavoriteIconByteArrayOutputStream.toByteArray(); + + // Update the bookmark and the favorite icon. + bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString, newFavoriteIconByteArray); + } + + // Update `bookmarksCursor` with the current contents of this folder. + bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder); + + // Update the `ListView`. + bookmarksCursorAdapter.changeCursor(bookmarksCursor); + } + + @Override + public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId) { + // Get handles for the views from `dialogFragment`. + EditText editFolderNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext); + 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); + ImageView folderIconImageView = (ImageView) dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon); + + // Get the new folder name. + String newFolderNameString = editFolderNameEditText.getText().toString(); + + // 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 and convert it to a `Bitmap`. + Drawable folderIconDrawable = folderIconImageView.getDrawable(); + BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable; + folderIconBitmap = folderIconBitmapDrawable.getBitmap(); + } else { // Use the `WebView` favorite icon. + folderIconBitmap = 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(); + + // 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 and convert it to a `Bitmap`. + Drawable folderIconDrawable = folderIconImageView.getDrawable(); + BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable; + folderIconBitmap = folderIconBitmapDrawable.getBitmap(); + } else { // Use the `WebView` favorite icon. + 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(); + + // Update the folder name and icon in the database. + bookmarksDatabaseHelper.updateFolder(selectedFolderDatabaseId, oldFolderNameString, newFolderNameString, folderIconByteArray); + } + + // Update `bookmarksCursor` with the current contents of this folder. + bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder); + + // Update the `ListView`. + bookmarksCursorAdapter.changeCursor(bookmarksCursor); + } + @Override public void onHttpAuthenticationCancel() { // Cancel the `HttpAuthHandler`. @@ -3060,10 +3319,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation private void loadBookmarksFolder() { // Update `bookmarksCursor` with the contents of the bookmarks database for the current folder. - Cursor bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder); + bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder); - // Setup a `CursorAdapter`. `this` specifies the `Context`. `false` disables `autoRequery`. - CursorAdapter bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) { + // Populate the bookmarks cursor adapter. `this` specifies the `Context`. `false` disables `autoRequery`. + bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) { @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { // Inflate the individual item layout. `false` does not attach it to the root. 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 dfe6cbd8..7954478e 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.activities.MainWebViewActivity; +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,13 +113,17 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment { // The `AlertDialog` must be shown before items in the alert dialog can be modified. alertDialog.show(); - // Get a handle for the create button. + // Get handles for the views in the dialog. final Button createButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); EditText folderNameEditText = (EditText) alertDialog.findViewById(R.id.create_folder_name_edittext); + ImageView webPageIconImageView = (ImageView) alertDialog.findViewById(R.id.create_folder_web_page_icon); // Initially disable the create button. createButton.setEnabled(false); + // 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); + // Enable the create button if the new folder name is unique. folderNameEditText.addTextChangedListener(new TextWatcher() { @Override @@ -138,7 +142,7 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment { String folderName = s.toString(); // Check if a folder with the name already exists. - Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(folderName); + Cursor folderExistsCursor = 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)); @@ -163,7 +167,6 @@ public class CreateBookmarkFolderDialog extends AppCompatDialogFragment { }); // Display the current favorite icon. - ImageView webPageIconImageView = (ImageView) alertDialog.findViewById(R.id.create_folder_web_page_icon); webPageIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap); // `onCreateDialog()` requires the return of an `AlertDialog`. diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.java index ab3a8a3b..a25864ba 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.java +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.java @@ -30,7 +30,7 @@ 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. +// `AppCompatDialogFragment` is required 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; @@ -43,21 +43,28 @@ import android.widget.ImageView; import android.widget.RadioButton; import android.widget.RadioGroup; -import com.stoutner.privacybrowser.activities.BookmarksActivity; -import com.stoutner.privacybrowser.activities.MainWebViewActivity; import com.stoutner.privacybrowser.R; +import com.stoutner.privacybrowser.activities.MainWebViewActivity; import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper; public class EditBookmarkDialog extends AppCompatDialogFragment { // The public interface is used to send information back to the parent activity. public interface EditBookmarkListener { - void onSaveEditBookmark(AppCompatDialogFragment dialogFragment); + void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId); } - // `editBookmarkListener` is used in `onAttach()` and `onCreateDialog()` + // Instantiate the class variables. private EditBookmarkListener editBookmarkListener; + private int selectedBookmarkDatabaseId; + private EditText nameEditText; + private EditText urlEditText; + private RadioButton newIconRadioButton; + private Button editButton; + private String currentName; + private String currentUrl; public void onAttach(Context context) { + // Run the default commands. super.onAttach(context); // Get a handle for `EditBookmarkListener` from `context`. @@ -68,25 +75,41 @@ public class EditBookmarkDialog extends AppCompatDialogFragment { } } - // Instantiate the class variables. - EditText nameEditText; - EditText urlEditText; - RadioButton newIconRadioButton; - Button editButton; - String currentName; - String currentUrl; + // Store the database ID in the arguments bundle. + public static EditBookmarkDialog bookmarkDatabaseId(int databaseId) { + // Create a bundle. + Bundle bundle = new Bundle(); + + // Store the bookmark database ID in the bundle. + bundle.putInt("Database ID", databaseId); + + // Add the bundle to the dialog. + EditBookmarkDialog editBookmarkDialog = new EditBookmarkDialog(); + editBookmarkDialog.setArguments(bundle); + + // Return the new dialog. + return editBookmarkDialog; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + // Run the default commands. + super.onCreate(savedInstanceState); + + // Store the bookmark database ID in the class variable. + selectedBookmarkDatabaseId = getArguments().getInt("Database ID"); + } // `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`. @SuppressLint("InflateParams") @Override @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { - // Get a long array with the the databaseId of the selected bookmark and convert it to an `int`. - long[] selectedBookmarkLongArray = BookmarksActivity.checkedItemIds; - int selectedBookmarkDatabaseId = (int) selectedBookmarkLongArray[0]; + // 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`. + BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(getContext(), null, null, 0); - // Get a `Cursor` with the specified bookmark and move it to the first position. - Cursor bookmarkCursor = BookmarksActivity.bookmarksDatabaseHelper.getBookmarkCursor(selectedBookmarkDatabaseId); + // Get a `Cursor` with the selected bookmark and move it to the first position. + Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(selectedBookmarkDatabaseId); bookmarkCursor.moveToFirst(); // Use `AlertDialog.Builder` to create the `AlertDialog`. @@ -118,7 +141,7 @@ public class EditBookmarkDialog extends AppCompatDialogFragment { @Override public void onClick(DialogInterface dialog, int which) { // Return the `DialogFragment` to the parent activity on save. - editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this); + editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId); } }); @@ -220,7 +243,7 @@ public class EditBookmarkDialog extends AppCompatDialogFragment { // If the event is an `ACTION_DOWN` on the `enter` key, save the bookmark. if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled. // Trigger `onSaveEditBookmark()` and return the `DialogFragment` to the parent activity. - editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this); + editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId); // Manually dismiss `alertDialog`. alertDialog.dismiss(); // Consume the event. @@ -237,7 +260,7 @@ public class EditBookmarkDialog extends AppCompatDialogFragment { // 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) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled. // Trigger `editBookmarkListener` and return the DialogFragment to the parent activity. - editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this); + editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId); // Manually dismiss the `AlertDialog`. alertDialog.dismiss(); // Consume the event. 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 f7022934..4bd1a689 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.java @@ -30,7 +30,7 @@ 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. +// `AppCompatDialogFragment` is required 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; @@ -43,21 +43,22 @@ import android.widget.ImageView; import android.widget.RadioButton; import android.widget.RadioGroup; -import com.stoutner.privacybrowser.activities.BookmarksActivity; -import com.stoutner.privacybrowser.activities.MainWebViewActivity; import com.stoutner.privacybrowser.R; +import com.stoutner.privacybrowser.activities.MainWebViewActivity; 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 onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId); } - // `editFolderListener` is used in `onAttach()` and `onCreateDialog`. + // Instantiate the class variables. private EditBookmarkFolderListener editBookmarkFolderListener; + private int selectedFolderDatabaseId; public void onAttach(Context context) { + // Run the default commands. super.onAttach(context); // Get a handle for `EditFolderListener` from `parentActivity`. @@ -68,18 +69,42 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { } } + // Store the database ID in the arguments bundle. + public static EditBookmarkFolderDialog folderDatabaseId(int databaseId) { + // Create a bundle + Bundle bundle = new Bundle(); + + // Store the folder database ID in the bundle. + bundle.putInt("Database ID", databaseId); + + // Add the bundle to the dialog. + EditBookmarkFolderDialog editBookmarkFolderDialog = new EditBookmarkFolderDialog(); + editBookmarkFolderDialog.setArguments(bundle); + + // Return the new dialog. + return editBookmarkFolderDialog; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + // Run the default commands. + super.onCreate(savedInstanceState); + + // Store the folder database ID in the class variable. + selectedFolderDatabaseId = getArguments().getInt("Database ID"); + } + // `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`. @SuppressLint("InflateParams") @Override @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) { - // Get a long array with the the databaseId of the selected bookmark and convert it to an `int`. - long[] selectedBookmarkLongArray = BookmarksActivity.checkedItemIds; - int selectedBookmarkDatabaseId = (int) selectedBookmarkLongArray[0]; + // 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 `Cursor` with the specified bookmark and move it to the first position. - Cursor bookmarkCursor = BookmarksActivity.bookmarksDatabaseHelper.getBookmarkCursor(selectedBookmarkDatabaseId); - bookmarkCursor.moveToFirst(); + // Get a `Cursor` with the selected folder and move it to the first position. + Cursor folderCursor = bookmarksDatabaseHelper.getBookmarkCursor(selectedFolderDatabaseId); + folderCursor.moveToFirst(); // Use `AlertDialog.Builder` to create the `AlertDialog`. AlertDialog.Builder dialogBuilder; @@ -110,11 +135,10 @@ 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.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this, selectedFolderDatabaseId); } }); - // Create an `AlertDialog` from the `AlertDialog.Builder`. final AlertDialog alertDialog = dialogBuilder.create(); @@ -136,7 +160,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { editButton.setEnabled(false); // Get the current favorite icon byte array from the `Cursor`. - byte[] currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)); + byte[] currentIconByteArray = folderCursor.getBlob(folderCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)); // Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last. Bitmap currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.length); // Display `currentIconBitmap` in `edit_folder_current_icon`. @@ -148,7 +172,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { webPageFavoriteIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap); // Get the current folder name. - final String currentFolderName = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)); + final String currentFolderName = folderCursor.getString(folderCursor.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); @@ -172,7 +196,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { String newFolderName = s.toString(); // Get a cursor for the new folder name if it exists. - Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(newFolderName); + Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName); // Is the new folder name empty? boolean folderNameEmpty = newFolderName.isEmpty(); @@ -199,7 +223,7 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { String newFolderName = folderNameEditText.getText().toString(); // Get a cursor for the new folder name if it exists. - Cursor folderExistsCursor = BookmarksActivity.bookmarksDatabaseHelper.getFolderCursor(newFolderName); + Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName); // Is the new folder name empty? boolean folderNameEmpty = newFolderName.isEmpty(); @@ -224,9 +248,11 @@ public class EditBookmarkFolderDialog extends AppCompatDialogFragment { // 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) && 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.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this, selectedFolderDatabaseId); + // Manually dismiss the `AlertDialog`. alertDialog.dismiss(); + // Consume the event. return true; } else { // If any other key was pressed, or if the edit button is currently disabled, do not consume the event. diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java index 35522154..4c7a0f4e 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutTabFragment.java @@ -22,8 +22,6 @@ package com.stoutner.privacybrowser.fragments; import android.annotation.SuppressLint; import android.content.pm.PackageManager; import android.content.pm.Signature; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Paint; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -53,21 +51,28 @@ import java.util.Date; public class AboutTabFragment extends Fragment { private int tabNumber; - // `AboutTabFragment.createTab` stores the tab number in the bundle arguments so it can be referenced from `onCreate()`. + // Store the tab number in the arguments bundle. public static AboutTabFragment createTab(int tab) { - Bundle thisTabArguments = new Bundle(); - thisTabArguments.putInt("Tab", tab); + // Create a bundle. + Bundle bundle = new Bundle(); - AboutTabFragment thisTab = new AboutTabFragment(); - thisTab.setArguments(thisTabArguments); - return thisTab; + // Store the tab number in the bundle. + bundle.putInt("Tab", tab); + + // Add the bundle to the fragment. + AboutTabFragment aboutTabFragment = new AboutTabFragment(); + aboutTabFragment.setArguments(bundle); + + // Return the new fragment. + return aboutTabFragment; } @Override public void onCreate(Bundle savedInstanceState) { + // Run the default commands. super.onCreate(savedInstanceState); - // Store the tab number in `tabNumber`. + // Store the tab number in a class variable. tabNumber = getArguments().getInt("Tab"); } diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/GuideTabFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/GuideTabFragment.java index 9e5f568d..a89ced02 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/GuideTabFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/GuideTabFragment.java @@ -34,21 +34,28 @@ public class GuideTabFragment extends Fragment { // `tabNumber` is used in `onCreate()` and `onCreateView()`. private int tabNumber; - // GuideTabFragment.createTab stores the tab number in the bundle arguments so it can be referenced from onCreate(). + // Store the tab number in the arguments bundle. public static GuideTabFragment createTab (int tab) { - Bundle thisTabArguments = new Bundle(); - thisTabArguments.putInt("Tab", tab); + // Create a bundle. + Bundle bundle = new Bundle(); - GuideTabFragment thisTab = new GuideTabFragment(); - thisTab.setArguments(thisTabArguments); - return thisTab; + // Store the tab number in the bundle. + bundle.putInt("Tab", tab); + + // Add the bundle to the fragment. + GuideTabFragment guideTabFragment = new GuideTabFragment(); + guideTabFragment.setArguments(bundle); + + // Return the new fragment. + return guideTabFragment; } @Override public void onCreate(Bundle savedInstanceState) { + // Run the default commands. super.onCreate(savedInstanceState); - // Store the tab number in `tabNumber`. + // Store the tab number in a class variable. tabNumber = getArguments().getInt("Tab"); } diff --git a/app/src/main/res/drawable/block_ads_disabled_dark.xml b/app/src/main/res/drawable/block_ads_disabled_dark.xml index f01efad9..a3f2b659 100644 --- a/app/src/main/res/drawable/block_ads_disabled_dark.xml +++ b/app/src/main/res/drawable/block_ads_disabled_dark.xml @@ -5,7 +5,7 @@ android:viewportHeight="24.0" android:viewportWidth="24.0" > - + diff --git a/app/src/main/res/drawable/block_ads_disabled_light.xml b/app/src/main/res/drawable/block_ads_disabled_light.xml index d60cbcab..d6f72691 100644 --- a/app/src/main/res/drawable/block_ads_disabled_light.xml +++ b/app/src/main/res/drawable/block_ads_disabled_light.xml @@ -5,7 +5,7 @@ android:viewportHeight="24.0" android:viewportWidth="24.0" > - + diff --git a/app/src/main/res/drawable/block_ads_enabled_dark.xml b/app/src/main/res/drawable/block_ads_enabled_dark.xml index a75ee708..92fc78d6 100644 --- a/app/src/main/res/drawable/block_ads_enabled_dark.xml +++ b/app/src/main/res/drawable/block_ads_enabled_dark.xml @@ -5,7 +5,7 @@ android:viewportHeight="24.0" android:viewportWidth="24.0" > - + diff --git a/app/src/main/res/drawable/block_ads_enabled_light.xml b/app/src/main/res/drawable/block_ads_enabled_light.xml index ca8ae425..73639aa5 100644 --- a/app/src/main/res/drawable/block_ads_enabled_light.xml +++ b/app/src/main/res/drawable/block_ads_enabled_light.xml @@ -5,7 +5,7 @@ android:viewportHeight="24.0" android:viewportWidth="24.0" > - + diff --git a/app/src/main/res/drawable/bookmarks.xml b/app/src/main/res/drawable/bookmarks_dark.xml similarity index 54% rename from app/src/main/res/drawable/bookmarks.xml rename to app/src/main/res/drawable/bookmarks_dark.xml index d2825600..a29fe719 100644 --- a/app/src/main/res/drawable/bookmarks.xml +++ b/app/src/main/res/drawable/bookmarks_dark.xml @@ -1,4 +1,4 @@ - + - + diff --git a/app/src/main/res/drawable/bookmarks_light.xml b/app/src/main/res/drawable/bookmarks_light.xml new file mode 100644 index 00000000..79475626 --- /dev/null +++ b/app/src/main/res/drawable/bookmarks_light.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/layout/main_drawerlayout.xml b/app/src/main/res/layout/main_drawerlayout.xml index 6339a310..5a52bcdc 100644 --- a/app/src/main/res/layout/main_drawerlayout.xml +++ b/app/src/main/res/layout/main_drawerlayout.xml @@ -136,6 +136,14 @@ android:dividerHeight="0dp" /> + + - + + - - - - - + android:id="@+id/navigationGroup2" > + android:orderInCategory="80" /> + android:orderInCategory="90" /> + android:id="@+id/navigationGroup3" > + android:orderInCategory="100" /> \ No newline at end of file -- 2.45.2