<w>anonymized</w>
<w>appbarlayout</w>
<w>aren</w>
+ <w>autoselected</w>
<w>bebdb</w>
<w>becerra</w>
<w>beeb</w>
<w>commitdiff</w>
<w>coordinatorlayout</w>
<w>customuseragent</w>
+ <w>databaseview</w>
<w>deeplinks</w>
<w>didn</w>
<w>displayimages</w>
</value>
</option>
</component>
- <component name="ProjectLevelVcsManager" settingsEditedManually="false">
- <OptionsSetting value="true" id="Add" />
- <OptionsSetting value="true" id="Remove" />
- <OptionsSetting value="true" id="Checkout" />
- <OptionsSetting value="true" id="Update" />
- <OptionsSetting value="true" id="Status" />
- <OptionsSetting value="true" id="Edit" />
- <ConfirmationsSetting value="0" id="Add" />
- <ConfirmationsSetting value="0" id="Remove" />
- </component>
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
+ compileSdkVersion 26
+ buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 19
- targetSdkVersion 25
+ targetSdkVersion 26
versionCode 26
versionName "2.6"
}
}
}
+ // Gradle requires a `flavorDimension`, but it isn't used for anything in Privacy Browser.
+ flavorDimensions "basic"
+
productFlavors {
standard {
applicationId "com.stoutner.privacybrowser.standard"
+ dimension "basic"
}
free {
applicationId "com.stoutner.privacybrowser.free"
+ dimension "basic"
}
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
dependencies {
- compile fileTree(include: ['*.jar'], dir: 'libs')
- compile 'com.android.support:design:25.4.0'
-
+ implementation fileTree(include: ['*.jar'], dir: 'libs')
+ implementation 'com.android.support:design:26.1.0'
// Only compile `com.google.firebase:firebase-ads:9.8.0` for the free flavor.
- freeCompile 'com.google.firebase:firebase-ads:11.0.4'
+ freeImplementation 'com.google.firebase:firebase-ads:11.4.2'
}
// Google's documentation says the following line is required for `firebase-ads` but things work correctly without it. I have no interest in applying the Google Mobile Services plugin in the standard flavor if I don't have to.
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
import android.support.v7.app.AppCompatDialogFragment;
import android.support.v7.widget.Toolbar;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
-import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ImageView;
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 `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()`.
+ // It is used in `onCreate`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`, and `loadFolder()`.
public static String currentFolder;
- // `checkedItemIds` is public static so it can be accessed from `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()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`, and `updateMoveIcons()`.
public static long[] checkedItemIds;
- // `bookmarksListView` is used in `onCreate()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, `updateMoveIcons()`, `scrollBookmarks()`,
+ // `bookmarksDatabaseHelper` is used in `onCreate()`, `onOptionsItemSelected()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`,
+ // and `loadFolder().
+ private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+
+ // `bookmarksListView` is used in `onCreate()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`, `updateMoveIcons()`, `scrollBookmarks()`,
// and `loadFolder()`.
private ListView bookmarksListView;
- // `bookmarksCursor` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`, and `loadFolder()`.
+ // `bookmarksCursor` is used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`, `deleteBookmarkFolderContents()`, and `loadFolder()`.
private Cursor bookmarksCursor;
- // `bookmarksCursorAdapter` is used in `onCreate(), `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, `onMoveToFolder()`, and `onLoadFolder()`.
+ // `bookmarksCursorAdapter` is used in `onCreate(), `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`, `onMoveToFolder()`, and `onLoadFolder()`.
private CursorAdapter bookmarksCursorAdapter;
// `contextualActionMode` is used in `onCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()` and `onMoveToFolder()`.
// `appBar` is used in `onCreate()` and `loadFolder()`.
private ActionBar appBar;
- // `oldFolderName` is used in `onCreate()` and `onSaveEditBookmarkFolder()`.
+ // `oldFolderName` is used in `onCreate()` and `onSaveBookmarkFolder()`.
private String oldFolderNameString;
// `moveBookmarkUpMenuItem` is used in `onCreate()` and `updateMoveIcons`.
setContentView(R.layout.bookmarks_coordinatorlayout);
// Use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
- final Toolbar bookmarksAppBar = (Toolbar) findViewById(R.id.bookmarks_toolbar);
+ final Toolbar bookmarksAppBar = findViewById(R.id.bookmarks_toolbar);
setSupportActionBar(bookmarksAppBar);
// Get a handle for the activity, the app bar, and the `ListView`.
final Activity bookmarksActivity = this;
appBar = getSupportActionBar();
- bookmarksListView = (ListView) findViewById(R.id.bookmarks_listview);
+ bookmarksListView = findViewById(R.id.bookmarks_listview);
// This assert removes the incorrect warning in Android Studio on the following line that `appBar` might be null.
assert appBar != null;
loadFolder();
// Set a listener so that tapping a list item loads the URL or folder.
- bookmarksListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- // Convert the id from long to int to match the format of the bookmarks database.
- int databaseID = (int) id;
+ bookmarksListView.setOnItemClickListener((parent, view, position, id) -> {
+ // Convert the id from long to int to match the format of the bookmarks database.
+ int databaseID = (int) id;
- // Get the bookmark `Cursor` for this ID and move it to the first row.
- Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(databaseID);
- bookmarkCursor.moveToFirst();
+ // Get the bookmark `Cursor` for this ID and move it to the first row.
+ Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(databaseID);
+ bookmarkCursor.moveToFirst();
- // Act upon the bookmark according to the type.
- if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) { // The selected bookmark is a folder.
- // Update `currentFolder`.
- currentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+ // Act upon the bookmark according to the type.
+ if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) { // The selected bookmark is a folder.
+ // Update `currentFolder`.
+ currentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- // Load the new folder.
- loadFolder();
- } else { // The selected bookmark is not a folder.
- // 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));
+ // Load the new folder.
+ loadFolder();
+ } else { // The selected bookmark is not a folder.
+ // 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;
+ // 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);
- }
+ // Close the bookmarks drawer and reload the bookmarks `ListView` when returning to `MainWebViewActivity`.
+ MainWebViewActivity.restartFromBookmarksActivity = true;
- // Close the `Cursor`.
- bookmarkCursor.close();
+ // Return to `MainWebViewActivity`.
+ NavUtils.navigateUpFromSameTask(bookmarksActivity);
}
+
+ // Close the `Cursor`.
+ bookmarkCursor.close();
});
// `MultiChoiceModeListener` handles long clicks.
// 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 position and find out if it is a folder.
+ // Move the `Cursor` 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);
// Get the selected bookmark database ID.
int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper._ID));
+ // Show the edit bookmark or edit bookmark folder dialog.
if (isFolder) {
- // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
+ // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`.
+ // Show the edit bookmark folder dialog.
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`.
+ // Show the edit bookmark dialog.
AppCompatDialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId);
editBookmarkDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
}
// Show a SnackBar.
Snackbar.make(findViewById(R.id.bookmarks_coordinatorlayout), snackbarMessage, Snackbar.LENGTH_LONG)
- .setAction(R.string.undo, new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Do nothing because everything will be handled by `onDismissed()` below.
- }
+ .setAction(R.string.undo, view -> {
+ // Do nothing because everything will be handled by `onDismissed()` below.
})
.addCallback(new Snackbar.Callback() {
@Override
});
// Get handles for the `FloatingActionButtons`.
- FloatingActionButton createBookmarkFolderFab = (FloatingActionButton) findViewById(R.id.create_bookmark_folder_fab);
- FloatingActionButton createBookmarkFab = (FloatingActionButton) findViewById(R.id.create_bookmark_fab);
+ FloatingActionButton createBookmarkFolderFab = findViewById(R.id.create_bookmark_folder_fab);
+ FloatingActionButton createBookmarkFab = findViewById(R.id.create_bookmark_fab);
// 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));
- }
+ createBookmarkFolderFab.setOnClickListener(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));
- }
+ createBookmarkFab.setOnClickListener(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));
});
}
@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);
+ EditText createBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_name_edittext);
+ EditText createBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_url_edittext);
// Extract the strings from the `EditTexts`.
String bookmarkNameString = createBookmarkNameEditText.getText().toString();
int newBookmarkDisplayOrder = bookmarksListView.getCount();
// Create the bookmark.
- bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, newBookmarkDisplayOrder, currentFolder, favoriteIconByteArray);
+ bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, currentFolder, newBookmarkDisplayOrder, favoriteIconByteArray);
// Update `bookmarksCursor` with the current contents of this folder.
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentFolder);
@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);
+ EditText createFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.create_folder_name_edittext);
+ RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon_radiobutton);
+ ImageView folderIconImageView = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon);
// Get new folder name string.
String folderNameString = createFolderNameEditText.getText().toString();
bookmarksDatabaseHelper.updateDisplayOrder(databaseId, i + 1);
}
- // Create the folder, placing it at the top of the ListView
- bookmarksDatabaseHelper.createFolder(folderNameString, 0, currentFolder, folderIconByteArray);
+ // Create the folder, which will be placed at the top of the `ListView`.
+ bookmarksDatabaseHelper.createFolder(folderNameString, currentFolder, folderIconByteArray);
// Update `bookmarksCursor` with the current contents of this folder.
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentFolder);
}
@Override
- public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
+ public void onSaveBookmark(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);
+ EditText editBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext);
+ EditText editBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext);
+ RadioButton currentBookmarkIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_current_icon_radiobutton);
// Store the bookmark strings.
String bookmarkNameString = editBookmarkNameEditText.getText().toString();
// Close the contextual action mode.
contextualActionMode.finish();
- // Update `bookmarksCursor` with the current contents of this folder.
+ // Update `bookmarksCursor` with the contents of the current folder.
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentFolder);
// Update the `ListView`.
}
@Override
- public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId) {
+ public void onSaveBookmarkFolder(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);
+ RadioButton currentFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton);
+ RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton);
+ ImageView defaultFolderIconImageView = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_imageview);
+ EditText editFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext);
// Get the new folder name.
String newFolderNameString = editFolderNameEditText.getText().toString();
Bitmap folderIconBitmap;
if (defaultFolderIconRadioButton.isChecked()) {
// Get the default folder icon and convert it to a `Bitmap`.
- Drawable folderIconDrawable = folderIconImageView.getDrawable();
+ Drawable folderIconDrawable = defaultFolderIconImageView.getDrawable();
BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable;
folderIconBitmap = folderIconBitmapDrawable.getBitmap();
} else { // Use the `WebView` favorite icon.
// 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`.
+ // Instantiate the new folder icon `Bitmap`.
Bitmap folderIconBitmap;
+
+ // Populate the new folder icon bitmap.
if (defaultFolderIconRadioButton.isChecked()) {
// Get the default folder icon and convert it to a `Bitmap`.
- Drawable folderIconDrawable = folderIconImageView.getDrawable();
+ Drawable folderIconDrawable = defaultFolderIconImageView.getDrawable();
BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable;
folderIconBitmap = folderIconBitmapDrawable.getBitmap();
} else { // Use the `WebView` favorite icon.
@Override
public void onMoveToFolder(AppCompatDialogFragment dialogFragment) {
// Get a handle for the `ListView` from `dialogFragment`.
- ListView folderListView = (ListView) dialogFragment.getDialog().findViewById(R.id.move_to_folder_listview);
+ ListView folderListView = dialogFragment.getDialog().findViewById(R.id.move_to_folder_listview);
// Store a long array of the selected folders.
long[] newFolderLongArray = folderListView.getCheckedItemIds();
@Override
public void bindView(View view, Context context, Cursor cursor) {
// Get handles for the views.
- ImageView bookmarkFavoriteIcon = (ImageView) view.findViewById(R.id.bookmark_favorite_icon);
- TextView bookmarkNameTextView = (TextView) view.findViewById(R.id.bookmark_name);
+ ImageView bookmarkFavoriteIcon = view.findViewById(R.id.bookmark_favorite_icon);
+ TextView bookmarkNameTextView = view.findViewById(R.id.bookmark_name);
// Get the favorite icon byte array from the `Cursor`.
byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.ResourceCursorAdapter;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
+import android.support.v7.app.AppCompatDialogFragment;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
+import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.dialogs.EditBookmarkDatabaseViewDialog;
+import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDatabaseViewDialog;
import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
-public class BookmarksDatabaseViewActivity extends AppCompatActivity {
+import java.io.ByteArrayOutputStream;
+
+public class BookmarksDatabaseViewActivity extends AppCompatActivity implements EditBookmarkDatabaseViewDialog.EditBookmarkDatabaseViewListener, EditBookmarkFolderDatabaseViewDialog.EditBookmarkFolderDatabaseViewListener {
+ // Instantiate the constants.
+ private static final int ALL_FOLDERS_DATABASE_ID = -2;
+ private static final int HOME_FOLDER_DATABASE_ID = -1;
+
// `bookmarksDatabaseHelper` is used in `onCreate()` and `updateBookmarksListView()`.
private BookmarksDatabaseHelper bookmarksDatabaseHelper;
- // `bookmarksListView` is used in `onCreate()` and `updateBookmarksListView()`.
- private ListView bookmarksListView;
+ // `bookmarksCursor` is used in `onCreate()`, `updateBookmarksListView()`, `onSaveBookmark()`, and `onSaveBookmarkFolder()`.
+ private Cursor bookmarksCursor;
- // `bookmarksCursorAdapter` is used in `onCreate()` and `updateBookmarksListView()`.
+ // `bookmarksCursorAdapter` is used in `onCreate()`, `onSaveBookmark()`, `onSaveBookmarkFolder()`.
private CursorAdapter bookmarksCursorAdapter;
+ // `oldFolderNameString` is used in `onCreate()` and `onSaveBookmarkFolder()`.
+ private String oldFolderNameString;
+
+ // `currentFolderDatabaseId` is used in `onCreate()`, `onSaveBookmark()`, and `onSaveBookmarkFolder()`.
+ private int currentFolderDatabaseId;
+
+ // `currentFolder` is used in `onCreate()`, `onSaveBookmark()`, and `onSaveBookmarkFolder()`.
+ private String currentFolderName;
+
@Override
public void onCreate(Bundle savedInstanceState) {
// Set the activity theme.
setTheme(R.style.PrivacyBrowserLight_SecondaryActivity);
}
+ // Run the default commands.
super.onCreate(savedInstanceState);
+
+ // Set the content view.
setContentView(R.layout.bookmarks_databaseview_coordinatorlayout);
- // We need to use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
- final Toolbar bookmarksDatabaseViewAppBar = (Toolbar) findViewById(R.id.bookmarks_database_view_toolbar);
+ // The `SupportActionBar` from `android.support.v7.app.ActionBar` must be used until the minimum API is >= 21.
+ final Toolbar bookmarksDatabaseViewAppBar = findViewById(R.id.bookmarks_databaseview_toolbar);
setSupportActionBar(bookmarksDatabaseViewAppBar);
// Get a handle for the `AppBar`.
// Setup a `MatrixCursor` for "All Folders" and "Home Folder".
String[] matrixCursorColumnNames = {BookmarksDatabaseHelper._ID, BookmarksDatabaseHelper.BOOKMARK_NAME};
MatrixCursor matrixCursor = new MatrixCursor(matrixCursorColumnNames);
- matrixCursor.addRow(new Object[]{-2, getString(R.string.all_folders)});
- matrixCursor.addRow(new Object[]{-1, getString(R.string.home_folder)});
+ matrixCursor.addRow(new Object[]{ALL_FOLDERS_DATABASE_ID, getString(R.string.all_folders)});
+ matrixCursor.addRow(new Object[]{HOME_FOLDER_DATABASE_ID, getString(R.string.home_folder)});
// Get a `Cursor` with the list of all the folders.
Cursor foldersCursor = bookmarksDatabaseHelper.getAllFoldersCursor();
// Combine `matrixCursor` and `foldersCursor`.
MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{matrixCursor, foldersCursor});
- // Create a `ResourceCursorAdapter` for the spinner with `this` context. `0` specifies no flags.;
+ // Create a `ResourceCursorAdapter` for the `Spinner` with `this` context. `0` specifies no flags.;
ResourceCursorAdapter foldersCursorAdapter = new ResourceCursorAdapter(this, R.layout.bookmarks_databaseview_spinner_item, foldersMergeCursor, 0) {
@Override
public void bindView(View view, Context context, Cursor cursor) {
- // Get a handle for the spinner item `TextView`.
- TextView spinnerItemTextView = (TextView) view.findViewById(R.id.spinner_item_textview);
+ // Get a handle for the `Spinner` item `TextView`.
+ TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
// Set the `TextView` to display the folder name.
spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
foldersCursorAdapter.setDropDownViewResource(R.layout.bookmarks_databaseview_spinner_dropdown_item);
// Get a handle for the folder `Spinner`.
- Spinner folderSpinner = (Spinner) findViewById(R.id.bookmarks_database_view_spinner);
+ Spinner folderSpinner = findViewById(R.id.bookmarks_databaseview_spinner);
// Set the adapter for the folder `Spinner`.
folderSpinner.setAdapter(foldersCursorAdapter);
// Convert the database ID to an `int`.
int databaseId = (int) id;
- // Instantiate the bookmarks `Cursor`.
- Cursor bookmarksCursor;
+ // Store the current folder database ID.
+ currentFolderDatabaseId = databaseId;
// Populate the bookmarks `ListView` based on the `Spinner` selection.
switch (databaseId) {
- // Display all the folders.
- case -2:
- // Get a cursor with all the folders.
+ // Get a cursor with all the folders.
+ case ALL_FOLDERS_DATABASE_ID:
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
break;
- // Display the home folder.
- case -1:
- // Get a cursor for the home folder.
+ // Get a cursor for the home folder.
+ case HOME_FOLDER_DATABASE_ID:
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor("");
break;
// Display the selected folder.
default:
// Get a handle for the selected view.
- TextView selectedFolderTextView = (TextView) view.findViewById(R.id.spinner_item_textview);
+ TextView selectedFolderTextView = view.findViewById(R.id.spinner_item_textview);
// Extract the name of the selected folder.
String folderName = selectedFolderTextView.getText().toString();
// Get a cursor for the selected folder.
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor(folderName);
+
+ // Store the current folder name.
+ currentFolderName = folderName;
}
// Update the `ListView`.
});
// Get a handle for the bookmarks `ListView`.
- bookmarksListView = (ListView) findViewById(R.id.bookmarks_database_view_listview);
+ ListView bookmarksListView = findViewById(R.id.bookmarks_databaseview_listview);
- // Display the bookmarks in the `ListView`.
- updateBookmarksListView();
- }
-
- private void updateBookmarksListView() {
// Get a `Cursor` with the current contents of the bookmarks database.
- final Cursor bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
- // Setup `bookmarksCursorAdapter` with `this` context. The `false` disables autoRequery.
+ // Setup a `CursorAdapter` with `this` context. `false` disables autoRequery.
bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// Get the database ID from the `Cursor` and display it in `bookmarkDatabaseIdTextView`.
int bookmarkDatabaseId = cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper._ID));
- TextView bookmarkDatabaseIdTextView = (TextView) view.findViewById(R.id.bookmarks_database_view_database_id);
+ TextView bookmarkDatabaseIdTextView = view.findViewById(R.id.bookmarks_databaseview_database_id);
bookmarkDatabaseIdTextView.setText(String.valueOf(bookmarkDatabaseId));
// Get the favorite icon byte array from the `Cursor`.
// Convert the byte array to a `Bitmap` beginning at the beginning at the first byte and ending at the last.
Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
// Display the bitmap in `bookmarkFavoriteIcon`.
- ImageView bookmarkFavoriteIcon = (ImageView) view.findViewById(R.id.bookmarks_database_view_favorite_icon);
+ ImageView bookmarkFavoriteIcon = view.findViewById(R.id.bookmarks_databaseview_favorite_icon);
bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
// Get the bookmark name from the `Cursor` and display it in `bookmarkNameTextView`.
String bookmarkNameString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- TextView bookmarkNameTextView = (TextView) view.findViewById(R.id.bookmarks_database_view_bookmark_name);
+ TextView bookmarkNameTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_name);
bookmarkNameTextView.setText(bookmarkNameString);
+
// Make the font bold for folders.
if (isFolder) {
- // The first argument is `null` because we don't want to change the font.
+ // The first argument is `null` prevent changing of the font.
bookmarkNameTextView.setTypeface(null, Typeface.BOLD);
} else { // Reset the font to default.
bookmarkNameTextView.setTypeface(Typeface.DEFAULT);
}
+ // Get the bookmark URL form the `Cursor` and display it in `bookmarkUrlTextView`.
+ String bookmarkUrlString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
+ TextView bookmarkUrlTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_url);
+ bookmarkUrlTextView.setText(bookmarkUrlString);
+
+ // Hide the URL if the bookmark is a folder.
+ if (isFolder) {
+ bookmarkUrlTextView.setVisibility(View.GONE);
+ } else {
+ bookmarkUrlTextView.setVisibility(View.VISIBLE);
+ }
+
// Get the display order from the `Cursor` and display it in `bookmarkDisplayOrderTextView`.
int bookmarkDisplayOrder = cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER));
- TextView bookmarkDisplayOrderTextView = (TextView) view.findViewById(R.id.bookmarks_database_view_display_order);
+ TextView bookmarkDisplayOrderTextView = view.findViewById(R.id.bookmarks_databaseview_display_order);
bookmarkDisplayOrderTextView.setText(String.valueOf(bookmarkDisplayOrder));
// Get the parent folder from the `Cursor` and display it in `bookmarkParentFolder`.
String bookmarkParentFolder = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER));
- ImageView parentFolderImageView = (ImageView) view.findViewById(R.id.bookmarks_database_view_parent_folder_icon);
- TextView bookmarkParentFolderTextView = (TextView) view.findViewById(R.id.bookmarks_database_view_parent_folder);
+ ImageView parentFolderImageView = view.findViewById(R.id.bookmarks_databaseview_parent_folder_icon);
+ TextView bookmarkParentFolderTextView = view.findViewById(R.id.bookmarks_databaseview_parent_folder);
+
// Make the folder name gray if it is the home folder.
if (bookmarkParentFolder.isEmpty()) {
parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_gray));
bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black));
}
}
-
- // Get the bookmark URL form the `Cursor` and display it in `bookmarkUrlTextView`.
- String bookmarkUrlString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
- TextView bookmarkUrlTextView = (TextView) view.findViewById(R.id.bookmarks_database_view_bookmark_url);
- bookmarkUrlTextView.setText(bookmarkUrlString);
- if (isFolder) {
- bookmarkUrlTextView.setVisibility(View.GONE);
- } else {
- bookmarkUrlTextView.setVisibility(View.VISIBLE);
- }
}
};
// Update the ListView.
bookmarksListView.setAdapter(bookmarksCursorAdapter);
+
+ // Set the current folder database ID.
+ currentFolderDatabaseId = ALL_FOLDERS_DATABASE_ID;
+
+ // Set a listener to edit a bookmark when it is tapped.
+ bookmarksListView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
+ // Convert the database ID to an `int`.
+ int databaseId = (int) id;
+
+ // Show the edit bookmark or edit bookmark folder dialog.
+ if (bookmarksDatabaseHelper.isFolder(databaseId)) {
+ // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
+ oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+
+ // Show the edit bookmark folder dialog.
+ AppCompatDialogFragment editBookmarkFolderDatabaseViewDialog = EditBookmarkFolderDatabaseViewDialog.folderDatabaseId(databaseId);
+ editBookmarkFolderDatabaseViewDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_folder));
+ } else {
+ // Show the edit bookmark dialog.
+ AppCompatDialogFragment editBookmarkDatabaseViewDialog = EditBookmarkDatabaseViewDialog.bookmarkDatabaseId(databaseId);
+ editBookmarkDatabaseViewDialog.show(getSupportFragmentManager(), getResources().getString(R.string.edit_bookmark));
+ }
+ });
+ }
+
+ @Override
+ public void onSaveBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
+ // Get handles for the views from dialog fragment.
+ RadioButton currentBookmarkIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_current_icon_radiobutton);
+ EditText editBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext);
+ EditText editBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext);
+ Spinner folderSpinner = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_folder_spinner);
+ EditText displayOrderEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_display_order_edittext);
+
+ // Extract the bookmark information.
+ String bookmarkNameString = editBookmarkNameEditText.getText().toString();
+ String bookmarkUrlString = editBookmarkUrlEditText.getText().toString();
+ int folderDatabaseId = (int) folderSpinner.getSelectedItemId();
+ int displayOrderInt = Integer.valueOf(displayOrderEditText.getText().toString());
+
+ // Instantiate the parent folder name `String`.
+ String parentFolderNameString;
+
+ // Set the parent folder name.
+ if (folderDatabaseId == EditBookmarkDatabaseViewDialog.HOME_FOLDER_DATABASE_ID) { // The home folder is selected. Use `""`.
+ parentFolderNameString = "";
+ } else { // Get the parent folder name from the database.
+ parentFolderNameString = bookmarksDatabaseHelper.getFolderName(folderDatabaseId);
+ }
+
+ // Update the bookmark.
+ if (currentBookmarkIconRadioButton.isChecked()) { // Update the bookmark without changing the favorite icon.
+ bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString, parentFolderNameString, displayOrderInt);
+ } 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();
+ MainWebViewActivity.favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, newFavoriteIconByteArrayOutputStream);
+ byte[] newFavoriteIconByteArray = newFavoriteIconByteArrayOutputStream.toByteArray();
+
+ // Update the bookmark and the favorite icon.
+ bookmarksDatabaseHelper.updateBookmark(selectedBookmarkDatabaseId, bookmarkNameString, bookmarkUrlString, parentFolderNameString, displayOrderInt, newFavoriteIconByteArray);
+ }
+
+ // Update `bookmarksCursor` with the contents of the current folder.
+ switch (currentFolderDatabaseId) {
+ case ALL_FOLDERS_DATABASE_ID:
+ // Get a cursor with all the bookmarks.
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
+ break;
+
+ case HOME_FOLDER_DATABASE_ID:
+ // Get a cursor with all the bookmarks in the home folder.
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor("");
+ break;
+
+ default:
+ // Get a cursor with all the bookmarks in the current folder.
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor(currentFolderName);
+ }
+
+ // Update the `ListView`.
+ bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+ }
+
+ @Override
+ public void onSaveBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
+ // Get handles for the views from dialog fragment.
+ RadioButton currentBookmarkIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton);
+ RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton);
+ ImageView defaultFolderIconImageView = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_imageview);
+ EditText editBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext);
+ Spinner parentFolderSpinner = dialogFragment.getDialog().findViewById(R.id.edit_folder_parent_folder_spinner);
+ EditText displayOrderEditText = dialogFragment.getDialog().findViewById(R.id.edit_folder_display_order_edittext);
+
+ // Extract the folder information.
+ String newFolderNameString = editBookmarkNameEditText.getText().toString();
+ int parentFolderDatabaseId = (int) parentFolderSpinner.getSelectedItemId();
+ int displayOrderInt = Integer.valueOf(displayOrderEditText.getText().toString());
+
+ // Instantiate the parent folder name `String`.
+ String parentFolderNameString;
+
+ // Set the parent folder name.
+ if (parentFolderDatabaseId == EditBookmarkFolderDatabaseViewDialog.HOME_FOLDER_DATABASE_ID) { // The home folder is selected. Use `""`.
+ parentFolderNameString = "";
+ } else { // Get the parent folder name from the database.
+ parentFolderNameString = bookmarksDatabaseHelper.getFolderName(parentFolderDatabaseId);
+ }
+
+ // Update the folder.
+ if (currentBookmarkIconRadioButton.isChecked()) { // Update the folder without changing the favorite icon.
+ bookmarksDatabaseHelper.updateFolder(selectedBookmarkDatabaseId, oldFolderNameString, newFolderNameString, parentFolderNameString, displayOrderInt);
+ } else { // Update the folder and the icon.
+ // Instantiate the new folder icon `Bitmap`.
+ Bitmap folderIconBitmap;
+
+ // Populate the new folder icon bitmap.
+ if (defaultFolderIconRadioButton.isChecked()) {
+ // Get the default folder icon and convert it to a `Bitmap`.
+ Drawable folderIconDrawable = defaultFolderIconImageView.getDrawable();
+ BitmapDrawable folderIconBitmapDrawable = (BitmapDrawable) folderIconDrawable;
+ folderIconBitmap = folderIconBitmapDrawable.getBitmap();
+ } else { // Use the `WebView` favorite icon.
+ folderIconBitmap = MainWebViewActivity.favoriteIconBitmap;
+ }
+
+ // Convert the folder icon to a byte array. `0` is for lossless compression (the only option for a PNG).
+ ByteArrayOutputStream newFolderIconByteArrayOutputStream = new ByteArrayOutputStream();
+ folderIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, newFolderIconByteArrayOutputStream);
+ byte[] newFolderIconByteArray = newFolderIconByteArrayOutputStream.toByteArray();
+
+ // Update the folder and the icon.
+ bookmarksDatabaseHelper.updateFolder(selectedBookmarkDatabaseId, oldFolderNameString, newFolderNameString, parentFolderNameString, displayOrderInt, newFolderIconByteArray);
+ }
+
+ // Update `bookmarksCursor` with the contents of the current folder.
+ switch (currentFolderDatabaseId) {
+ case ALL_FOLDERS_DATABASE_ID:
+ // Get a cursor with all the bookmarks.
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
+ break;
+
+ case HOME_FOLDER_DATABASE_ID:
+ // Get a cursor with all the bookmarks in the home folder.
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor("");
+ break;
+
+ default:
+ // Get a cursor with all the bookmarks in the current folder.
+ bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor(currentFolderName);
+ }
+
+ // Update the `ListView`.
+ bookmarksCursorAdapter.changeCursor(bookmarksCursor);
}
}
\ No newline at end of file
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieManager;
-import android.webkit.DownloadListener;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
-import android.webkit.ValueCallback;
import android.webkit.WebBackForwardList;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebViewDatabase;
-import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.FrameLayout;
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`,
- // `ViewSslCertificateDialog`, `CreateHomeScreenShortcutDialog`, and `OrbotProxyHelper`. It is also used in `onCreate()`, `applyAppSettings()`, `applyDomainSettings()`, and `updatePrivacyIcons()`.
+ // `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `DownloadFileDialog`, `DownloadImageDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `EditBookmarkDatabaseViewDialog`, `HttpAuthenticationDialog`, `MoveToFolderDialog`,
+ // `SslCertificateErrorDialog`, `UrlHistoryDialog`, `ViewSslCertificateDialog`, `CreateHomeScreenShortcutDialog`, and `OrbotProxyHelper`. It is also used in `onCreate()`, `applyAppSettings()`, `applyDomainSettings()`, and `updatePrivacyIcons()`.
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()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onCreateHomeScreenShortcutCreate()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `applyDomainSettings()`.
+ // `favoriteIconBitmap` is public static so it can be accessed from `CreateHomeScreenShortcutDialog`, `BookmarksActivity`, `BookmarksDatabaseViewActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `EditBookmarkDialog`,
+ // `EditBookmarkFolderDialog`, `EditBookmarkDatabaseViewDialog`, 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`.
@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")
+ @SuppressLint({"SetJavaScriptEnabled"})
// Remove Android Studio's warning about deprecations. We have to use the deprecated `getColor()` until API >= 23.
@SuppressWarnings("deprecation")
protected void onCreate(Bundle savedInstanceState) {
inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
// `SupportActionBar` from `android.support.v7.app.ActionBar` must be used until the minimum API is >= 21.
- supportAppBar = (Toolbar) findViewById(R.id.app_bar);
+ supportAppBar = findViewById(R.id.app_bar);
setSupportActionBar(supportAppBar);
appBar = getSupportActionBar();
finalGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500));
// Get a handle for `urlTextBox`.
- urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.url_edittext);
+ urlTextBox = appBar.getCustomView().findViewById(R.id.url_edittext);
// Remove the formatting from `urlTextBar` when the user is editing the text.
- urlTextBox.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (hasFocus) { // The user is editing `urlTextBox`.
- // Remove the highlighting.
- urlTextBox.getText().removeSpan(redColorSpan);
- urlTextBox.getText().removeSpan(initialGrayColorSpan);
- urlTextBox.getText().removeSpan(finalGrayColorSpan);
- } else { // The user has stopped editing `urlTextBox`.
- // Reapply the highlighting.
- highlightUrlText();
- }
+ urlTextBox.setOnFocusChangeListener((v, hasFocus) -> {
+ if (hasFocus) { // The user is editing `urlTextBox`.
+ // Remove the highlighting.
+ urlTextBox.getText().removeSpan(redColorSpan);
+ urlTextBox.getText().removeSpan(initialGrayColorSpan);
+ urlTextBox.getText().removeSpan(finalGrayColorSpan);
+ } else { // The user has stopped editing `urlTextBox`.
+ // Reapply the highlighting.
+ highlightUrlText();
}
});
// Set the `Go` button on the keyboard to load the URL in `urlTextBox`.
- urlTextBox.setOnKeyListener(new View.OnKeyListener() {
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- // If the event is a key-down event on the `enter` button, load the URL.
- if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
- // Load the URL into the mainWebView and consume the event.
- try {
- loadUrlFromTextBox();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- // If the enter key was pressed, consume the event.
- return true;
- } else {
- // If any other key was pressed, do not consume the event.
- return false;
+ urlTextBox.setOnKeyListener((v, keyCode, event) -> {
+ // If the event is a key-down event on the `enter` button, load the URL.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+ // Load the URL into the mainWebView and consume the event.
+ try {
+ loadUrlFromTextBox();
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
}
+ // If the enter key was pressed, consume the event.
+ return true;
+ } else {
+ // If any other key was pressed, do not consume the event.
+ return false;
}
});
this.registerReceiver(orbotStatusBroadcastReceiver, new IntentFilter("org.torproject.android.intent.action.STATUS"));
// Get handles for views that need to be accessed.
- drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout);
- rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout);
- bookmarksListView = (ListView) findViewById(R.id.bookmarks_drawer_listview);
- bookmarksTitleTextView = (TextView) findViewById(R.id.bookmarks_title_textview);
- 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);
- findOnPageLinearLayout = (LinearLayout) findViewById(R.id.find_on_page_linearlayout);
- findOnPageEditText = (EditText) findViewById(R.id.find_on_page_edittext);
- fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout);
- urlAppBarRelativeLayout = (RelativeLayout) findViewById(R.id.url_app_bar_relativelayout);
- favoriteIconImageView = (ImageView) findViewById(R.id.favorite_icon);
+ drawerLayout = findViewById(R.id.drawerlayout);
+ rootCoordinatorLayout = findViewById(R.id.root_coordinatorlayout);
+ bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
+ bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview);
+ FloatingActionButton launchBookmarksActivityFab = findViewById(R.id.launch_bookmarks_activity_fab);
+ FloatingActionButton createBookmarkFolderFab = findViewById(R.id.create_bookmark_folder_fab);
+ FloatingActionButton createBookmarkFab = findViewById(R.id.create_bookmark_fab);
+ mainWebViewRelativeLayout = findViewById(R.id.main_webview_relativelayout);
+ mainWebView = findViewById(R.id.main_webview);
+ findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
+ findOnPageEditText = findViewById(R.id.find_on_page_edittext);
+ fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout);
+ urlAppBarRelativeLayout = findViewById(R.id.url_app_bar_relativelayout);
+ favoriteIconImageView = findViewById(R.id.favorite_icon);
// 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) {
}
// 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);
+ launchBookmarksActivityFab.setOnClickListener(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);
+ // Include the current folder with the `Intent`.
+ bookmarksIntent.putExtra("Current Folder", currentBookmarksFolder);
- // Make it so.
- startActivity(bookmarksIntent);
- }
+ // 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));
- }
+ createBookmarkFolderFab.setOnClickListener(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));
- }
+ createBookmarkFab.setOnClickListener(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.
});
// Pass all touch events on `mainWebView` through `gestureDetector` to check for double-taps.
- mainWebView.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- // Send the `event` to `gestureDetector`.
- return gestureDetector.onTouchEvent(event);
- }
+ mainWebView.setOnTouchListener((View v, MotionEvent event) -> {
+ // Call `performClick()` on the view, which is required for accessibility.
+ v.performClick();
+
+ // Send the `event` to `gestureDetector`.
+ return gestureDetector.onTouchEvent(event);
});
// Update `findOnPageCountTextView`.
// `activeMatchOrdinal` is zero-based.
int activeMatch = activeMatchOrdinal + 1;
+ // Build the match string.
+ String matchString = activeMatch + "/" + numberOfMatches;
+
// Set `findOnPageCountTextView`.
- findOnPageCountTextView.setText(activeMatch + "/" + numberOfMatches);
+ findOnPageCountTextView.setText(matchString);
}
}
});
});
// Set the `check mark` button for the `findOnPageEditText` keyboard to close the soft keyboard.
- findOnPageEditText.setOnKeyListener(new View.OnKeyListener() {
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { // The `enter` key was pressed.
- // Hide the soft keyboard. `0` indicates no additional flags.
- inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
+ findOnPageEditText.setOnKeyListener((v, keyCode, event) -> {
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { // The `enter` key was pressed.
+ // Hide the soft keyboard. `0` indicates no additional flags.
+ inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
- // Consume the event.
- return true;
- } else { // A different key was pressed.
- // Do not consume the event.
- return false;
- }
+ // Consume the event.
+ return true;
+ } else { // A different key was pressed.
+ // Do not consume the event.
+ return false;
}
});
// Implement swipe to refresh
- swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refreshlayout);
+ swipeRefreshLayout = findViewById(R.id.swipe_refreshlayout);
swipeRefreshLayout.setColorSchemeResources(R.color.blue_700);
- swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
- @Override
- public void onRefresh() {
- mainWebView.reload();
- }
- });
+ swipeRefreshLayout.setOnRefreshListener(() -> mainWebView.reload());
// `DrawerTitle` identifies the `DrawerLayouts` in accessibility mode.
drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
drawerLayout.setDrawerTitle(GravityCompat.END, getString(R.string.bookmarks));
// Listen for touches on the navigation menu.
- final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationview);
+ final NavigationView navigationView = findViewById(R.id.navigationview);
navigationView.setNavigationItemSelectedListener(this);
// Get handles for `navigationMenu` and the back and forward menu items. The menu is zero-based, so items 1, 2, and 3 are the second, third, and fourth entries in the menu.
// Load the home folder, which is `""` in the database.
loadBookmarksFolder();
- bookmarksListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- // Convert the id from long to int to match the format of the bookmarks database.
- int databaseID = (int) id;
-
- // Get the bookmark `Cursor` for this ID and move it to the first row.
- Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(databaseID);
- bookmarkCursor.moveToFirst();
-
- // Act upon the bookmark according to the type.
- if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) { // The selected bookmark is a folder.
- // Store the new folder name in `currentBookmarksFolder`.
- currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
-
- // Load the new folder.
- loadBookmarksFolder();
- } else { // The selected bookmark is not a folder.
- // Load the bookmark URL.
- loadUrl(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
-
- // Close the bookmarks drawer.
- drawerLayout.closeDrawer(GravityCompat.END);
- }
+ bookmarksListView.setOnItemClickListener((parent, view, position, id) -> {
+ // Convert the id from long to int to match the format of the bookmarks database.
+ int databaseID = (int) id;
+
+ // Get the bookmark `Cursor` for this ID and move it to the first row.
+ Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(databaseID);
+ bookmarkCursor.moveToFirst();
- // Close the `Cursor`.
- bookmarkCursor.close();
+ // Act upon the bookmark according to the type.
+ if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) { // The selected bookmark is a folder.
+ // Store the new folder name in `currentBookmarksFolder`.
+ currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+
+ // Load the new folder.
+ loadBookmarksFolder();
+ } else { // The selected bookmark is not a folder.
+ // Load the bookmark URL.
+ loadUrl(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
+
+ // Close the bookmarks drawer.
+ drawerLayout.closeDrawer(GravityCompat.END);
}
- });
- 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;
+ // Close the `Cursor`.
+ bookmarkCursor.close();
+ });
- // Find out if the selected bookmark is a folder.
- boolean isFolder = bookmarksDatabaseHelper.isFolder(databaseId);
+ bookmarksListView.setOnItemLongClickListener((parent, view, position, id) -> {
+ // Convert the database ID from `long` to `int`.
+ int databaseId = (int) id;
- if (isFolder) {
- // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
- oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+ // Find out if the selected bookmark is a folder.
+ boolean isFolder = bookmarksDatabaseHelper.isFolder(databaseId);
- // 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));
- }
+ if (isFolder) {
+ // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
+ oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- // Consume the event.
- return true;
+ // 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.
});
// Get a handle for the progress bar.
- final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ final ProgressBar progressBar = findViewById(R.id.progress_bar);
mainWebView.setWebChromeClient(new WebChromeClient() {
// Update the progress bar when a page is loading.
mainWebView.evaluateJavascript("(function() {var parent = document.getElementsByTagName('head').item(0); var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = '" +
"* {background-color: #212121 !important; color: #BDBDBD !important; box-shadow: none !important; text-decoration: none !important; text-shadow: none !important; border: none !important;}" +
"a {color: #1565C0 !important;}" +
- "'; parent.appendChild(style)})()", new ValueCallback<String>() {
- @Override
- public void onReceiveValue(String value) {
- // Initialize a `Handler` to display `mainWebView`.
- Handler displayWebViewHandler = new Handler();
-
- // Setup a `Runnable` to display `mainWebView` after a delay to allow the CSS to be applied.
- Runnable displayWebViewRunnable = new Runnable() {
- public void run() {
+ "'; parent.appendChild(style)})()", value -> {
+ // Initialize a `Handler` to display `mainWebView`.
+ Handler displayWebViewHandler = new Handler();
+
+ // Setup a `Runnable` to display `mainWebView` after a delay to allow the CSS to be applied.
+ Runnable displayWebViewRunnable = () -> {
// Only display `mainWebView` if the progress bar is one. This prevents the display of the `WebView` while it is still loading.
if (progressBar.getVisibility() == View.GONE) {
mainWebView.setVisibility(View.VISIBLE);
}
- }
- };
+ };
- // Use `displayWebViewHandler` to delay the displaying of `mainWebView` for 500 milliseconds.
- displayWebViewHandler.postDelayed(displayWebViewRunnable, 500);
- }
- });
+ // Use `displayWebViewHandler` to delay the displaying of `mainWebView` for 500 milliseconds.
+ displayWebViewHandler.postDelayed(displayWebViewRunnable, 500);
+ });
}
progressBar.setProgress(progress);
registerForContextMenu(mainWebView);
// Allow the downloading of files.
- mainWebView.setDownloadListener(new DownloadListener() {
- @Override
- public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
- // Show the `DownloadFileDialog` `AlertDialog` and name this instance `@string/download`.
- AppCompatDialogFragment downloadFileDialogFragment = DownloadFileDialog.fromUrl(url, contentDisposition, contentLength);
- downloadFileDialogFragment.show(getSupportFragmentManager(), getString(R.string.download));
- }
+ mainWebView.setDownloadListener((url, userAgent, contentDisposition, mimetype, contentLength) -> {
+ // Show the `DownloadFileDialog` `AlertDialog` and name this instance `@string/download`.
+ AppCompatDialogFragment downloadFileDialogFragment = DownloadFileDialog.fromUrl(url, contentDisposition, contentLength);
+ downloadFileDialogFragment.show(getSupportFragmentManager(), getString(R.string.download));
});
// Allow pinch to zoom.
case R.id.clear_cookies:
Snackbar.make(findViewById(R.id.main_webview), R.string.cookies_deleted, Snackbar.LENGTH_LONG)
- .setAction(R.string.undo, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Do nothing because everything will be handled by `onDismissed()` below.
- }
+ .setAction(R.string.undo, v -> {
+ // Do nothing because everything will be handled by `onDismissed()` below.
})
.addCallback(new Snackbar.Callback() {
@Override
case R.id.clear_dom_storage:
Snackbar.make(findViewById(R.id.main_webview), R.string.dom_storage_deleted, Snackbar.LENGTH_LONG)
- .setAction(R.string.undo, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Do nothing because everything will be handled by `onDismissed()` below.
- }
+ .setAction(R.string.undo, v -> {
+ // Do nothing because everything will be handled by `onDismissed()` below.
})
.addCallback(new Snackbar.Callback() {
@Override
case R.id.clear_form_data:
Snackbar.make(findViewById(R.id.main_webview), R.string.form_data_deleted, Snackbar.LENGTH_LONG)
- .setAction(R.string.undo, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Do nothing because everything will be handled by `onDismissed()` below.
- }
+ .setAction(R.string.undo, v -> {
+ // Do nothing because everything will be handled by `onDismissed()` below.
})
.addCallback(new Snackbar.Callback() {
@Override
findOnPageLinearLayout.setVisibility(View.VISIBLE);
// Display the keyboard. We have to wait 200 ms before running the command to work around a bug in Android. http://stackoverflow.com/questions/5520085/android-show-softkeyboard-with-showsoftinput-is-not-working
- findOnPageEditText.postDelayed(new Runnable() {
- @Override
- public void run()
- {
- // Set the focus on `findOnPageEditText`.
- findOnPageEditText.requestFocus();
-
- // Display the keyboard. `0` sets no input flags.
- inputMethodManager.showSoftInput(findOnPageEditText, 0);
- }
+ findOnPageEditText.postDelayed(() -> {
+ // Set the focus on `findOnPageEditText`.
+ findOnPageEditText.requestFocus();
+
+ // Display the keyboard. `0` sets no input flags.
+ inputMethodManager.showSoftInput(findOnPageEditText, 0);
}, 200);
return true;
// Convert `mainWebView` to `printDocumentAdapter`.
PrintDocumentAdapter printDocumentAdapter = mainWebView.createPrintDocumentAdapter();
+ // Remove the lint error below that `printManager` might be `null`.
+ assert printManager != null;
+
// Print the document. The print attributes are `null`.
printManager.print(getString(R.string.privacy_browser_web_page), printDocumentAdapter, null);
return true;
// Get a handle for the `ClipboardManager`.
final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+ // Remove the lint errors below that `clipboardManager` might be `null`.
+ assert clipboardManager != null;
+
switch (hitTestResult.getType()) {
// `SRC_ANCHOR_TYPE` is a link.
case WebView.HitTestResult.SRC_ANCHOR_TYPE:
menu.setHeaderTitle(linkUrl);
// Add a `Load URL` entry.
- menu.add(R.string.load_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- loadUrl(linkUrl);
- return false;
- }
+ menu.add(R.string.load_url).setOnMenuItemClickListener(item -> {
+ loadUrl(linkUrl);
+ return false;
});
// Add a `Copy URL` entry.
- menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Save the link URL in a `ClipData`.
- ClipData srcAnchorTypeClipData = ClipData.newPlainText(getString(R.string.url), linkUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcAnchorTypeClipData);
- return false;
- }
+ menu.add(R.string.copy_url).setOnMenuItemClickListener(item -> {
+ // Save the link URL in a `ClipData`.
+ ClipData srcAnchorTypeClipData = ClipData.newPlainText(getString(R.string.url), linkUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcAnchorTypeClipData);
+ return false;
});
// Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.setHeaderTitle(linkUrl);
// Add a `Write Email` entry.
- menu.add(R.string.write_email).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // We use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
- Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
+ menu.add(R.string.write_email).setOnMenuItemClickListener(item -> {
+ // We use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
+ Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
- // Parse the url and set it as the data for the `Intent`.
- emailIntent.setData(Uri.parse("mailto:" + linkUrl));
+ // Parse the url and set it as the data for the `Intent`.
+ emailIntent.setData(Uri.parse("mailto:" + linkUrl));
- // `FLAG_ACTIVITY_NEW_TASK` opens the email program in a new task instead as part of Privacy Browser.
- emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ // `FLAG_ACTIVITY_NEW_TASK` opens the email program in a new task instead as part of Privacy Browser.
+ emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- // Make it so.
- startActivity(emailIntent);
- return false;
- }
+ // Make it so.
+ startActivity(emailIntent);
+ return false;
});
// Add a `Copy Email Address` entry.
- menu.add(R.string.copy_email_address).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Save the email address in a `ClipData`.
- ClipData srcEmailTypeClipData = ClipData.newPlainText(getString(R.string.email_address), linkUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcEmailTypeClipData);
- return false;
- }
+ menu.add(R.string.copy_email_address).setOnMenuItemClickListener(item -> {
+ // Save the email address in a `ClipData`.
+ ClipData srcEmailTypeClipData = ClipData.newPlainText(getString(R.string.email_address), linkUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcEmailTypeClipData);
+ return false;
});
// Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.setHeaderTitle(imageUrl);
// Add a `View Image` entry.
- menu.add(R.string.view_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- loadUrl(imageUrl);
- return false;
- }
+ menu.add(R.string.view_image).setOnMenuItemClickListener(item -> {
+ loadUrl(imageUrl);
+ return false;
});
// Add a `Download Image` entry.
- menu.add(R.string.download_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Show the `DownloadImageDialog` `AlertDialog` and name this instance `@string/download`.
- AppCompatDialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl);
- downloadImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.download));
- return false;
- }
+ menu.add(R.string.download_image).setOnMenuItemClickListener(item -> {
+ // Show the `DownloadImageDialog` `AlertDialog` and name this instance `@string/download`.
+ AppCompatDialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl);
+ downloadImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.download));
+ return false;
});
// Add a `Copy URL` entry.
- menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Save the image URL in a `ClipData`.
- ClipData srcImageTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcImageTypeClipData);
- return false;
- }
+ menu.add(R.string.copy_url).setOnMenuItemClickListener(item -> {
+ // Save the image URL in a `ClipData`.
+ ClipData srcImageTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcImageTypeClipData);
+ return false;
});
// Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.setHeaderTitle(imageUrl);
// Add a `View Image` entry.
- menu.add(R.string.view_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- loadUrl(imageUrl);
- return false;
- }
+ menu.add(R.string.view_image).setOnMenuItemClickListener(item -> {
+ loadUrl(imageUrl);
+ return false;
});
// Add a `Download Image` entry.
- menu.add(R.string.download_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Show the `DownloadImageDialog` `AlertDialog` and name this instance `@string/download`.
- AppCompatDialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl);
- downloadImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.download));
- return false;
- }
+ menu.add(R.string.download_image).setOnMenuItemClickListener(item -> {
+ // Show the `DownloadImageDialog` `AlertDialog` and name this instance `@string/download`.
+ AppCompatDialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl);
+ downloadImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.download));
+ return false;
});
// Add a `Copy URL` entry.
- menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Save the image URL in a `ClipData`.
- ClipData srcImageAnchorTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
-
- // Set the `ClipData` as the clipboard's primary clip.
- clipboardManager.setPrimaryClip(srcImageAnchorTypeClipData);
- return false;
- }
+ menu.add(R.string.copy_url).setOnMenuItemClickListener(item -> {
+ // Save the image URL in a `ClipData`.
+ ClipData srcImageAnchorTypeClipData = ClipData.newPlainText(getString(R.string.url), imageUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcImageAnchorTypeClipData);
+ return false;
});
// Add a `Cancel` entry, which by default closes the `ContextMenu`.
@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);
+ EditText createBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_name_edittext);
+ EditText createBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_url_edittext);
// Extract the strings from the `EditTexts`.
String bookmarkNameString = createBookmarkNameEditText.getText().toString();
int newBookmarkDisplayOrder = bookmarksListView.getCount();
// Create the bookmark.
- bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, newBookmarkDisplayOrder, currentBookmarksFolder, favoriteIconByteArray);
+ bookmarksDatabaseHelper.createBookmark(bookmarkNameString, bookmarkUrlString, currentBookmarksFolder, newBookmarkDisplayOrder, favoriteIconByteArray);
// Update `bookmarksCursor` with the current contents of this folder.
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
@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);
+ EditText createFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.create_folder_name_edittext);
+ RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon_radiobutton);
+ ImageView folderIconImageView = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon);
// Get new folder name string.
String folderNameString = createFolderNameEditText.getText().toString();
bookmarksDatabaseHelper.updateDisplayOrder(databaseId, i + 1);
}
- // Create the folder, placing it at the top of the ListView
- bookmarksDatabaseHelper.createFolder(folderNameString, 0, currentBookmarksFolder, folderIconByteArray);
+ // Create the folder, which will be placed at the top of the `ListView`.
+ bookmarksDatabaseHelper.createFolder(folderNameString, currentBookmarksFolder, folderIconByteArray);
// Update `bookmarksCursor` with the current contents of this folder.
bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursorByDisplayOrder(currentBookmarksFolder);
@Override
public void onCreateHomeScreenShortcut(AppCompatDialogFragment dialogFragment) {
// Get shortcutNameEditText from the alert dialog.
- EditText shortcutNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.shortcut_name_edittext);
+ EditText shortcutNameEditText = dialogFragment.getDialog().findViewById(R.id.shortcut_name_edittext);
// Create the bookmark shortcut based on formattedUrlString.
Intent bookmarkShortcut = new Intent();
}
// Get the file name from `dialogFragment`.
- EditText downloadImageNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.download_image_name);
+ EditText downloadImageNameEditText = dialogFragment.getDialog().findViewById(R.id.download_image_name);
String imageName = downloadImageNameEditText.getText().toString();
// Once we have `WRITE_EXTERNAL_STORAGE` permissions we can use `setDestinationInExternalPublicDir`.
// Show the download notification after the download is completed.
downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ // Remove the lint warning below that `downloadManager` might be `null`.
+ assert downloadManager != null;
+
// Initiate the download.
downloadManager.enqueue(downloadRequest);
} else { // The image is not an HTTP or HTTPS URI.
}
// Get the file name from `dialogFragment`.
- EditText downloadFileNameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.download_file_name);
+ EditText downloadFileNameEditText = dialogFragment.getDialog().findViewById(R.id.download_file_name);
String fileName = downloadFileNameEditText.getText().toString();
// Once we have `WRITE_EXTERNAL_STORAGE` permissions we can use `setDestinationInExternalPublicDir`.
// Show the download notification after the download is completed.
downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ // Remove the lint warning below that `downloadManager` might be `null`.
+ assert downloadManager != null;
+
// Initiate the download.
downloadManager.enqueue(downloadRequest);
} else { // The download is not an HTTP or HTTPS URI.
}
@Override
- public void onSaveEditBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId) {
+ public void onSaveBookmark(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);
+ EditText editBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext);
+ EditText editBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext);
+ RadioButton currentBookmarkIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_current_icon_radiobutton);
// Store the bookmark strings.
String bookmarkNameString = editBookmarkNameEditText.getText().toString();
}
@Override
- public void onSaveEditBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId) {
+ public void onSaveBookmarkFolder(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);
+ EditText editFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext);
+ RadioButton currentFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton);
+ RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton);
+ ImageView folderIconImageView = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_imageview);
// Get the new folder name.
String newFolderNameString = editFolderNameEditText.getText().toString();
@Override
public void onHttpAuthenticationProceed(AppCompatDialogFragment dialogFragment) {
// Get handles for the `EditTexts`.
- EditText usernameEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.http_authentication_username);
- EditText passwordEditText = (EditText) dialogFragment.getDialog().findViewById(R.id.http_authentication_password);
+ EditText usernameEditText = dialogFragment.getDialog().findViewById(R.id.http_authentication_username);
+ EditText passwordEditText = dialogFragment.getDialog().findViewById(R.id.http_authentication_password);
// Proceed with the HTTP authentication.
httpAuthHandler.proceed(usernameEditText.getText().toString(), passwordEditText.getText().toString());
@Override
public void bindView(View view, Context context, Cursor cursor) {
// Get handles for the views.
- ImageView bookmarkFavoriteIcon = (ImageView) view.findViewById(R.id.bookmark_favorite_icon);
- TextView bookmarkNameTextView = (TextView) view.findViewById(R.id.bookmark_name);
+ ImageView bookmarkFavoriteIcon = view.findViewById(R.id.bookmark_favorite_icon);
+ TextView bookmarkNameTextView = view.findViewById(R.id.bookmark_name);
// Get the favorite icon byte array from the `Cursor`.
byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
--- /dev/null
+/*
+ * Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+ *
+ * Privacy Browser is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacybrowser.dialogs;
+
+import android.annotation.SuppressLint;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
+import android.support.v4.widget.ResourceCursorAdapter;
+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.AdapterView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
+
+public class EditBookmarkDatabaseViewDialog extends AppCompatDialogFragment {
+ // Instantiate the constants.
+ public static final int HOME_FOLDER_DATABASE_ID = -1;
+
+ // Instantiate the class variables.
+ private EditBookmarkDatabaseViewListener editBookmarkDatabaseViewListener;
+ private int bookmarkDatabaseId;
+ private String currentBookmarkName;
+ private String currentUrl;
+ private int currentFolderDatabaseId;
+ private String currentDisplayOrder;
+ private RadioButton newIconRadioButton;
+ private EditText nameEditText;
+ private EditText urlEditText;
+ private Spinner folderSpinner;
+ private EditText displayOrderEditText;
+ private Button editButton;
+
+ // The public interface is used to send information back to the parent activity.
+ public interface EditBookmarkDatabaseViewListener {
+ void onSaveBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId);
+ }
+
+ public void onAttach(Context context) {
+ // Run the default commands.
+ super.onAttach(context);
+
+ // Get a handle for `EditBookmarkDatabaseViewListener` from `context`.
+ try {
+ editBookmarkDatabaseViewListener = (EditBookmarkDatabaseViewListener) context;
+ } catch(ClassCastException exception) {
+ throw new ClassCastException(context.toString() + " must implement EditBookmarkDatabaseViewListener.");
+ }
+ }
+
+ // Store the database ID in the arguments bundle.
+ public static EditBookmarkDatabaseViewDialog 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.
+ EditBookmarkDatabaseViewDialog editBookmarkDatabaseViewDialog = new EditBookmarkDatabaseViewDialog();
+ editBookmarkDatabaseViewDialog.setArguments(bundle);
+
+ // Return the new dialog.
+ return editBookmarkDatabaseViewDialog;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ // Run the default commands.
+ super.onCreate(savedInstanceState);
+
+ // Store the bookmark database ID in the class variable.
+ bookmarkDatabaseId = 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) {
+ // 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 selected bookmark and move it to the first position.
+ Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmarkCursor(bookmarkDatabaseId);
+ bookmarkCursor.moveToFirst();
+
+ // Use `AlertDialog.Builder` to create the `AlertDialog`.
+ AlertDialog.Builder dialogBuilder;
+
+ // Set the style according to the theme.
+ if (MainWebViewActivity.darkTheme) {
+ dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark);
+ } else {
+ dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogLight);
+ }
+
+ // Set the title.
+ dialogBuilder.setTitle(R.string.edit_bookmark);
+
+ // Set the view. The parent view is `null` because it will be assigned by `AlertDialog`.
+ dialogBuilder.setView(getActivity().getLayoutInflater().inflate(R.layout.edit_bookmark_databaseview_dialog, null));
+
+ // Set an `onClick()` listener for the negative button.
+ dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
+ // Do nothing. The `AlertDialog` will close automatically.
+ });
+
+ // Set the `onClick()` listener fo the positive button.
+ dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
+ // Return the `DialogFragment` to the parent activity on save.
+ editBookmarkDatabaseViewListener.onSaveBookmark(EditBookmarkDatabaseViewDialog.this, bookmarkDatabaseId);
+ });
+
+ // Create an `AlertDialog` from the `AlertDialog.Builder`.
+ final AlertDialog alertDialog = dialogBuilder.create();
+
+ // Remove the warning below that `setSoftInputMode` might produce `java.lang.NullPointerException`.
+ assert alertDialog.getWindow() != null;
+
+ // Set the keyboard to be hidden when the `AlertDialog` is first shown. If this is not set, the `AlertDialog` will not shrink when the keyboard is displayed.
+ alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
+
+ // The `AlertDialog` must be shown before items in the layout can be modified.
+ alertDialog.show();
+
+ // Get handles for the layout items.
+ TextView databaseIdTextView = alertDialog.findViewById(R.id.edit_bookmark_database_id_textview);
+ RadioGroup iconRadioGroup = alertDialog.findViewById(R.id.edit_bookmark_icon_radiogroup);
+ ImageView currentIconImageView = alertDialog.findViewById(R.id.edit_bookmark_current_icon);
+ ImageView newFavoriteIconImageView = alertDialog.findViewById(R.id.edit_bookmark_webpage_favorite_icon);
+ newIconRadioButton = alertDialog.findViewById(R.id.edit_bookmark_webpage_favorite_icon_radiobutton);
+ nameEditText = alertDialog.findViewById(R.id.edit_bookmark_name_edittext);
+ urlEditText = alertDialog.findViewById(R.id.edit_bookmark_url_edittext);
+ folderSpinner = alertDialog.findViewById(R.id.edit_bookmark_folder_spinner);
+ displayOrderEditText = alertDialog.findViewById(R.id.edit_bookmark_display_order_edittext);
+ editButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ // Store the current bookmark values.
+ currentBookmarkName = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+ currentUrl = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
+ currentDisplayOrder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER));
+
+ // Set the database ID.
+ databaseIdTextView.setText(String.valueOf(bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper._ID))));
+
+ // 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.
+ Bitmap currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.length);
+
+ // Display `currentIconBitmap` in `edit_bookmark_current_icon`.
+ currentIconImageView.setImageBitmap(currentIconBitmap);
+
+ // Get a `Bitmap` of the favorite icon from `MainWebViewActivity` and display it in `edit_bookmark_web_page_favorite_icon`.
+ newFavoriteIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap);
+
+ // Populate the bookmark name and URL `EditTexts`.
+ nameEditText.setText(currentBookmarkName);
+ urlEditText.setText(currentUrl);
+
+ // Setup a `MatrixCursor` "Home Folder".
+ String[] matrixCursorColumnNames = {BookmarksDatabaseHelper._ID, BookmarksDatabaseHelper.BOOKMARK_NAME};
+ MatrixCursor matrixCursor = new MatrixCursor(matrixCursorColumnNames);
+ matrixCursor.addRow(new Object[]{HOME_FOLDER_DATABASE_ID, getString(R.string.home_folder)});
+
+ // Get a `Cursor` with the list of all the folders.
+ Cursor foldersCursor = bookmarksDatabaseHelper.getAllFoldersCursor();
+
+ // Combine `matrixCursor` and `foldersCursor`.
+ MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{matrixCursor, foldersCursor});
+
+ // Create a `ResourceCursorAdapter` for the `Spinner`. `0` specifies no flags.;
+ ResourceCursorAdapter foldersCursorAdapter = new ResourceCursorAdapter(getContext(), R.layout.edit_bookmark_databaseview_spinner_item, foldersMergeCursor, 0) {
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ // Get a handle for the `Spinner` item `TextView`.
+ TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
+
+ // Set the `TextView` to display the folder name.
+ spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+ }
+ };
+
+ // Set the `ResourceCursorAdapter` drop drown view resource.
+ foldersCursorAdapter.setDropDownViewResource(R.layout.edit_bookmark_databaseview_spinner_dropdown_item);
+
+ // Set the adapter for the folder `Spinner`.
+ folderSpinner.setAdapter(foldersCursorAdapter);
+
+ // Get the parent folder name.
+ String parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER));
+
+ // Select the current folder in the `Spinner` if the bookmark isn't in the "Home Folder".
+ if (!parentFolder.equals("")) {
+ // Get the database ID of the parent folder.
+ int folderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)));
+
+ // Initialize `parentFolderPosition` and the iteration variable.
+ int parentFolderPosition = 0;
+ int i = 0;
+
+ // Find the parent folder position in folders `ResourceCursorAdapter`.
+ do {
+ if (foldersCursorAdapter.getItemId(i) == folderDatabaseId) {
+ // Store the current position for the parent folder.
+ parentFolderPosition = i;
+ } else {
+ // Try the next entry.
+ i++;
+ }
+ // Stop when the parent folder position is found or all the items in the `ResourceCursorAdapter` have been checked.
+ } while ((parentFolderPosition == 0) && (i < foldersCursorAdapter.getCount()));
+
+ // Select the parent folder in the `Spinner`.
+ folderSpinner.setSelection(parentFolderPosition);
+ }
+
+ // Store the current folder database ID.
+ currentFolderDatabaseId = (int) folderSpinner.getSelectedItemId();
+
+ // Populate the display order `EditText`.
+ displayOrderEditText.setText(String.valueOf(bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER))));
+
+ // Initially disable the edit button.
+ editButton.setEnabled(false);
+
+ // Update the edit button if the icon selection changes.
+ iconRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
+ // Update the edit button.
+ updateEditButton();
+ });
+
+ // Update the edit button if the bookmark name changes.
+ nameEditText.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) {
+ // Update the edit button.
+ updateEditButton();
+ }
+ });
+
+ // Update the edit button if the URL changes.
+ urlEditText.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) {
+ // Update the edit button.
+ updateEditButton();
+ }
+ });
+
+ // Update the edit button if the folder changes.
+ folderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ // Update the edit button.
+ updateEditButton();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+ });
+
+ // Update the edit button if the display order changes.
+ displayOrderEditText.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) {
+ // Update the edit button.
+ updateEditButton();
+ }
+ });
+
+ // Allow the `enter` key on the keyboard to save the bookmark from the bookmark name `EditText`.
+ nameEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the `DialogFragment` to the parent activity.
+ editBookmarkDatabaseViewListener.onSaveBookmark(EditBookmarkDatabaseViewDialog.this, bookmarkDatabaseId);
+
+ // Manually dismiss `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.
+ return false;
+ }
+ });
+
+ // Allow the "enter" key on the keyboard to save the bookmark from the URL `EditText`.
+ urlEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the `DialogFragment` to the parent activity.
+ editBookmarkDatabaseViewListener.onSaveBookmark(EditBookmarkDatabaseViewDialog.this, bookmarkDatabaseId);
+
+ // 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.
+ return false;
+ }
+ });
+
+ // Allow the "enter" key on the keyboard to save the bookmark from the display order `EditText`.
+ displayOrderEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the `DialogFragment` to the parent activity.
+ editBookmarkDatabaseViewListener.onSaveBookmark(EditBookmarkDatabaseViewDialog.this, bookmarkDatabaseId);
+
+ // 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.
+ return false;
+ }
+ });
+
+ // `onCreateDialog` requires the return of an `AlertDialog`.
+ return alertDialog;
+ }
+
+ private void updateEditButton() {
+ // Get the values from the dialog.
+ String newName = nameEditText.getText().toString();
+ String newUrl = urlEditText.getText().toString();
+ int newFolderDatabaseId = (int) folderSpinner.getSelectedItemId();
+ String newDisplayOrder = displayOrderEditText.getText().toString();
+
+ // Has the favorite icon changed?
+ boolean iconChanged = newIconRadioButton.isChecked();
+
+ // Has the name changed?
+ boolean nameChanged = !newName.equals(currentBookmarkName);
+
+ // Has the URL changed?
+ boolean urlChanged = !newUrl.equals(currentUrl);
+
+ // Has the folder changed?
+ boolean folderChanged = newFolderDatabaseId != currentFolderDatabaseId;
+
+ // Has the display order changed?
+ boolean displayOrderChanged = !newDisplayOrder.equals(currentDisplayOrder);
+
+ // Is the display order empty?
+ boolean displayOrderNotEmpty = !newDisplayOrder.isEmpty();
+
+ // Update the enabled status of the edit button.
+ editButton.setEnabled((iconChanged || nameChanged || urlChanged || folderChanged || displayOrderChanged) && displayOrderNotEmpty);
+ }
+}
\ No newline at end of file
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
-import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
import android.support.v7.app.AppCompatDialogFragment;
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, int selectedBookmarkDatabaseId);
- }
-
// Instantiate the class variables.
private EditBookmarkListener editBookmarkListener;
private int selectedBookmarkDatabaseId;
private String currentName;
private String currentUrl;
+ // The public interface is used to send information back to the parent activity.
+ public interface EditBookmarkListener {
+ void onSaveBookmark(AppCompatDialogFragment dialogFragment, int selectedBookmarkDatabaseId);
+ }
+
public void onAttach(Context context) {
// Run the default commands.
super.onAttach(context);
dialogBuilder.setView(getActivity().getLayoutInflater().inflate(R.layout.edit_bookmark_dialog, null));
// Set an `onClick()` listener for the negative button.
- dialogBuilder.setNegativeButton(R.string.cancel, new Dialog.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Do nothing. The `AlertDialog` will close automatically.
- }
+ dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
+ // Do nothing. The `AlertDialog` will close automatically.
});
// Set the `onClick()` listener fo the positive button.
- dialogBuilder.setPositiveButton(R.string.save, new Dialog.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Return the `DialogFragment` to the parent activity on save.
- editBookmarkListener.onSaveEditBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
- }
+ dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
+ // Return the `DialogFragment` to the parent activity on save.
+ editBookmarkListener.onSaveBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
});
// Create an `AlertDialog` from the `AlertDialog.Builder`.
alertDialog.show();
// Get handles for the layout items.
- RadioGroup iconRadioGroup = (RadioGroup) alertDialog.findViewById(R.id.edit_bookmark_icon_radiogroup);
- ImageView currentIconImageView = (ImageView) alertDialog.findViewById(R.id.edit_bookmark_current_icon);
- ImageView newFavoriteIconImageView = (ImageView) alertDialog.findViewById(R.id.edit_bookmark_web_page_favorite_icon);
- newIconRadioButton = (RadioButton) alertDialog.findViewById(R.id.edit_bookmark_web_page_favorite_icon_radiobutton);
- nameEditText = (EditText) alertDialog.findViewById(R.id.edit_bookmark_name_edittext);
- urlEditText = (EditText) alertDialog.findViewById(R.id.edit_bookmark_url_edittext);
+ RadioGroup iconRadioGroup = alertDialog.findViewById(R.id.edit_bookmark_icon_radiogroup);
+ ImageView currentIconImageView = alertDialog.findViewById(R.id.edit_bookmark_current_icon);
+ ImageView newFavoriteIconImageView = alertDialog.findViewById(R.id.edit_bookmark_webpage_favorite_icon);
+ newIconRadioButton = alertDialog.findViewById(R.id.edit_bookmark_webpage_favorite_icon_radiobutton);
+ nameEditText = alertDialog.findViewById(R.id.edit_bookmark_name_edittext);
+ urlEditText = alertDialog.findViewById(R.id.edit_bookmark_url_edittext);
editButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
// Get the current favorite icon byte array from the `Cursor`.
editButton.setEnabled(false);
// Update the edit button if the icon selection changes.
- iconRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
- // Update the edit button.
- updateEditButton();
- }
+ iconRadioGroup.setOnCheckedChangeListener((RadioGroup group, int checkedId) -> {
+ // Update the edit button.
+ updateEditButton();
});
// Update the edit button if the bookmark name changes.
}
});
- // Allow the `enter` key on the keyboard to save the bookmark from `edit_bookmark_name_edittext`.
- nameEditText.setOnKeyListener(new View.OnKeyListener() {
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- // 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, selectedBookmarkDatabaseId);
- // Manually dismiss `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.
- return false;
- }
+ // Allow the `enter` key on the keyboard to save the bookmark from the bookmark name `EditText`.
+ nameEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the `DialogFragment` to the parent activity.
+ editBookmarkListener.onSaveBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
+
+ // Manually dismiss `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.
+ return false;
}
});
- // Allow the "enter" key on the keyboard to save the bookmark from `edit_bookmark_url_edittext`.
- urlEditText.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) && 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, selectedBookmarkDatabaseId);
- // 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.
- return false;
- }
+ // Allow the "enter" key on the keyboard to save the bookmark from the URL `EditText`.
+ urlEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the DialogFragment to the parent activity.
+ editBookmarkListener.onSaveBookmark(EditBookmarkDialog.this, selectedBookmarkDatabaseId);
+
+ // 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.
+ return false;
}
});
// Has the URL changed?
boolean urlChanged = !newUrl.equals(currentUrl);
+ // Update the enabled status of the edit button.
editButton.setEnabled(iconChanged || nameChanged || urlChanged);
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+ *
+ * Privacy Browser is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacybrowser.dialogs;
+
+import android.annotation.SuppressLint;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.widget.ResourceCursorAdapter;
+// `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;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
+
+public class EditBookmarkFolderDatabaseViewDialog extends AppCompatDialogFragment {
+ // Instantiate the constants.
+ public static final int HOME_FOLDER_DATABASE_ID = -1;
+
+ // Instantiate the class variables.
+ private EditBookmarkFolderDatabaseViewListener editBookmarkFolderDatabaseViewListener;
+ private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+ private int folderDatabaseId;
+ private StringBuilder exceptFolders;
+ private String currentFolderName;
+ private int currentParentFolderDatabaseId;
+ private String currentDisplayOrder;
+ private RadioButton currentIconRadioButton;
+ private EditText nameEditText;
+ private Spinner folderSpinner;
+ private EditText displayOrderEditText;
+ private Button editButton;
+
+ // The public interface is used to send information back to the parent activity.
+ public interface EditBookmarkFolderDatabaseViewListener {
+ void onSaveBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId);
+ }
+
+ public void onAttach(Context context) {
+ // Run the default commands.
+ super.onAttach(context);
+
+ // Get a handle for `EditBookmarkDatabaseViewListener` from `context`.
+ try {
+ editBookmarkFolderDatabaseViewListener = (EditBookmarkFolderDatabaseViewListener) context;
+ } catch(ClassCastException exception) {
+ throw new ClassCastException(context.toString() + " must implement EditBookmarkFolderDatabaseViewListener.");
+ }
+ }
+
+ // Store the database ID in the arguments bundle.
+ public static EditBookmarkFolderDatabaseViewDialog folderDatabaseId(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.
+ EditBookmarkFolderDatabaseViewDialog editBookmarkFolderDatabaseViewDialog = new EditBookmarkFolderDatabaseViewDialog();
+ editBookmarkFolderDatabaseViewDialog.setArguments(bundle);
+
+ // Return the new dialog.
+ return editBookmarkFolderDatabaseViewDialog;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ // Run the default commands.
+ super.onCreate(savedInstanceState);
+
+ // Store the bookmark database ID in the class variable.
+ folderDatabaseId = 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) {
+ // 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 = new BookmarksDatabaseHelper(getContext(), null, null, 0);
+
+ // Get a `Cursor` with the selected bookmark and move it to the first position.
+ Cursor folderCursor = bookmarksDatabaseHelper.getBookmarkCursor(folderDatabaseId);
+ folderCursor.moveToFirst();
+
+ // Use `AlertDialog.Builder` to create the `AlertDialog`.
+ AlertDialog.Builder dialogBuilder;
+
+ // Set the style according to the theme.
+ if (MainWebViewActivity.darkTheme) {
+ dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark);
+ } else {
+ dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogLight);
+ }
+
+ // Set the title.
+ dialogBuilder.setTitle(R.string.edit_folder);
+
+ // Set the view. The parent view is `null` because it will be assigned by `AlertDialog`.
+ dialogBuilder.setView(getActivity().getLayoutInflater().inflate(R.layout.edit_bookmark_folder_databaseview_dialog, null));
+
+ // Set an `onClick()` listener for the negative button.
+ dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
+ // Do nothing. The `AlertDialog` will close automatically.
+ });
+
+ // Set the `onClick()` listener fo the positive button.
+ dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
+ // Return the `DialogFragment` to the parent activity on save.
+ editBookmarkFolderDatabaseViewListener.onSaveBookmarkFolder(EditBookmarkFolderDatabaseViewDialog.this, folderDatabaseId);
+ });
+
+ // Create an `AlertDialog` from the `AlertDialog.Builder`.
+ final AlertDialog alertDialog = dialogBuilder.create();
+
+ // Remove the warning below that `setSoftInputMode` might produce `java.lang.NullPointerException`.
+ assert alertDialog.getWindow() != null;
+
+ // Set the keyboard to be hidden when the `AlertDialog` is first shown. If this is not set, the `AlertDialog` will not shrink when the keyboard is displayed.
+ alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
+
+ // The `AlertDialog` must be shown before items in the layout can be modified.
+ alertDialog.show();
+
+ // Get handles for the layout items.
+ TextView databaseIdTextView = alertDialog.findViewById(R.id.edit_folder_database_id_textview);
+ RadioGroup iconRadioGroup = alertDialog.findViewById(R.id.edit_folder_icon_radiogroup);
+ ImageView currentIconImageView = alertDialog.findViewById(R.id.edit_folder_current_icon_imageview);
+ ImageView newFavoriteIconImageView = alertDialog.findViewById(R.id.edit_folder_webpage_favorite_icon_imageview);
+ currentIconRadioButton = alertDialog.findViewById(R.id.edit_folder_current_icon_radiobutton);
+ nameEditText = alertDialog.findViewById(R.id.edit_folder_name_edittext);
+ folderSpinner = alertDialog.findViewById(R.id.edit_folder_parent_folder_spinner);
+ displayOrderEditText = alertDialog.findViewById(R.id.edit_folder_display_order_edittext);
+ editButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+ // Store the current folder values.
+ currentFolderName = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+ currentDisplayOrder = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER));
+ String parentFolder = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER));
+
+ // Set the database ID.
+ databaseIdTextView.setText(String.valueOf(folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper._ID))));
+
+ // Get the current favorite icon byte array from the `Cursor`.
+ 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_bookmark_current_icon`.
+ currentIconImageView.setImageBitmap(currentIconBitmap);
+
+ // Get a `Bitmap` of the favorite icon from `MainWebViewActivity` and display it in `edit_bookmark_web_page_favorite_icon`.
+ newFavoriteIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap);
+
+ // Populate the folder name `EditText`.
+ nameEditText.setText(currentFolderName);
+
+ // Setup a `MatrixCursor` "Home Folder".
+ String[] matrixCursorColumnNames = {BookmarksDatabaseHelper._ID, BookmarksDatabaseHelper.BOOKMARK_NAME};
+ MatrixCursor matrixCursor = new MatrixCursor(matrixCursorColumnNames);
+ matrixCursor.addRow(new Object[]{HOME_FOLDER_DATABASE_ID, getString(R.string.home_folder)});
+
+ // Initialize a `StringBuilder` to track the folders not to display in the `Spinner` and populate it with the current folder.
+ exceptFolders = new StringBuilder(DatabaseUtils.sqlEscapeString(currentFolderName));
+
+ // Add all subfolders of the current folder to the list of folders not to display.
+ addSubfoldersToExceptFolders(currentFolderName);
+
+ // Get a `Cursor` with the list of all the folders.
+ Cursor foldersCursor = bookmarksDatabaseHelper.getFoldersCursorExcept(exceptFolders.toString());
+
+ // Combine `matrixCursor` and `foldersCursor`.
+ MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{matrixCursor, foldersCursor});
+
+ // Create a `ResourceCursorAdapter` for the `Spinner`. `0` specifies no flags.;
+ ResourceCursorAdapter foldersCursorAdapter = new ResourceCursorAdapter(getContext(), R.layout.edit_bookmark_databaseview_spinner_item, foldersMergeCursor, 0) {
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ // Get a handle for the `Spinner` item `TextView`.
+ TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
+
+ // Set the `TextView` to display the folder name.
+ spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+ }
+ };
+
+ // Set the `ResourceCursorAdapter` drop drown view resource.
+ foldersCursorAdapter.setDropDownViewResource(R.layout.edit_bookmark_databaseview_spinner_dropdown_item);
+
+ // Set the adapter for the folder `Spinner`.
+ folderSpinner.setAdapter(foldersCursorAdapter);
+
+ // Select the current folder in the `Spinner` if the bookmark isn't in the "Home Folder".
+ if (!parentFolder.equals("")) {
+ // Get the database ID of the parent folder.
+ int folderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)));
+
+ // Initialize `parentFolderPosition` and the iteration variable.
+ int parentFolderPosition = 0;
+ int i = 0;
+
+ // Find the parent folder position in folders `ResourceCursorAdapter`.
+ do {
+ if (foldersCursorAdapter.getItemId(i) == folderDatabaseId) {
+ // Store the current position for the parent folder.
+ parentFolderPosition = i;
+ } else {
+ // Try the next entry.
+ i++;
+ }
+ // Stop when the parent folder position is found or all the items in the `ResourceCursorAdapter` have been checked.
+ } while ((parentFolderPosition == 0) && (i < foldersCursorAdapter.getCount()));
+
+ // Select the parent folder in the `Spinner`.
+ folderSpinner.setSelection(parentFolderPosition);
+ }
+
+ // Store the current folder database ID.
+ currentParentFolderDatabaseId = (int) folderSpinner.getSelectedItemId();
+
+ // Populate the display order `EditText`.
+ displayOrderEditText.setText(String.valueOf(folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER))));
+
+ // Initially disable the edit button.
+ editButton.setEnabled(false);
+
+ // Update the edit button if the icon selection changes.
+ iconRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
+ // Update the edit button.
+ updateEditButton();
+ });
+
+ // Update the edit button if the bookmark name changes.
+ nameEditText.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) {
+ // Update the edit button.
+ updateEditButton();
+ }
+ });
+
+ // Update the edit button if the folder changes.
+ folderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ // Update the edit button.
+ updateEditButton();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+
+ }
+ });
+
+ // Update the edit button if the display order changes.
+ displayOrderEditText.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) {
+ // Update the edit button.
+ updateEditButton();
+ }
+ });
+
+ // Allow the `enter` key on the keyboard to save the bookmark from the bookmark name `EditText`.
+ nameEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the `DialogFragment` to the parent activity.
+ editBookmarkFolderDatabaseViewListener.onSaveBookmarkFolder(EditBookmarkFolderDatabaseViewDialog.this, folderDatabaseId);
+
+ // Manually dismiss `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.
+ return false;
+ }
+ });
+
+ // Allow the "enter" key on the keyboard to save the bookmark from the display order `EditText`.
+ displayOrderEditText.setOnKeyListener((View v, int keyCode, KeyEvent event) -> {
+ // Save the bookmark if the event is a key-down on the "enter" button.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger the `Listener` and return the `DialogFragment` to the parent activity.
+ editBookmarkFolderDatabaseViewListener.onSaveBookmarkFolder(EditBookmarkFolderDatabaseViewDialog.this, folderDatabaseId);
+
+ // 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.
+ return false;
+ }
+ });
+
+ // `onCreateDialog` requires the return of an `AlertDialog`.
+ return alertDialog;
+ }
+
+ private void updateEditButton() {
+ // Get the values from the dialog.
+ String newFolderName = nameEditText.getText().toString();
+ int newParentFolderDatabaseId = (int) folderSpinner.getSelectedItemId();
+ String newDisplayOrder = displayOrderEditText.getText().toString();
+
+ // Get a cursor for the new folder name if it exists.
+ Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName);
+
+ // Is the new folder name empty?
+ boolean folderNameNotEmpty = !newFolderName.isEmpty();
+
+ // Does the folder name already exist?
+ boolean folderNameAlreadyExists = (!newFolderName.equals(currentFolderName) && (folderExistsCursor.getCount() > 0));
+
+ // Has the favorite icon changed?
+ boolean iconChanged = !currentIconRadioButton.isChecked();
+
+ // Has the name been renamed?
+ boolean folderRenamed = (!newFolderName.equals(currentFolderName) && !folderNameAlreadyExists);
+
+ // Has the folder changed?
+ boolean parentFolderChanged = newParentFolderDatabaseId != currentParentFolderDatabaseId;
+
+ // Has the display order changed?
+ boolean displayOrderChanged = !newDisplayOrder.equals(currentDisplayOrder);
+
+ // Is the display order empty?
+ boolean displayOrderNotEmpty = !newDisplayOrder.isEmpty();
+
+ // Update the enabled status of the edit button.
+ editButton.setEnabled((iconChanged || folderRenamed || parentFolderChanged || displayOrderChanged) && folderNameNotEmpty && displayOrderNotEmpty);
+ }
+
+ private void addSubfoldersToExceptFolders(String folderName) {
+ // Get a `Cursor` will all the immediate subfolders.
+ Cursor subfoldersCursor = bookmarksDatabaseHelper.getSubfoldersCursor(folderName);
+
+ for (int i = 0; i < subfoldersCursor.getCount(); i++) {
+ // Move `subfolderCursor` to the current item.
+ subfoldersCursor.moveToPosition(i);
+
+ // Get the name of the subfolder.
+ String subfolderName = subfoldersCursor.getString(subfoldersCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+
+ // Add the subfolder to `exceptFolders`.
+ exceptFolders.append(",");
+ exceptFolders.append(DatabaseUtils.sqlEscapeString(subfolderName));
+
+ // Run the same tasks for any subfolders of the subfolder.
+ addSubfoldersToExceptFolders(subfolderName);
+ }
+ }
+}
\ No newline at end of file
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
-import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
// `AppCompatDialogFragment` is required instead of `DialogFragment` or an error is produced on API <=22.
import android.support.v7.app.AppCompatDialogFragment;
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, int selectedFolderDatabaseId);
+ void onSaveBookmarkFolder(AppCompatDialogFragment dialogFragment, int selectedFolderDatabaseId);
}
// Instantiate the class variables.
dialogBuilder.setView(getActivity().getLayoutInflater().inflate(R.layout.edit_bookmark_folder_dialog, null));
// Set an `onClick()` listener for the negative button.
- dialogBuilder.setNegativeButton(R.string.cancel, new Dialog.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Do nothing. The `AlertDialog` will close automatically.
- }
+ dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
+ // Do nothing. The `AlertDialog` will close automatically.
});
// Set the `onClick()` listener fo the positive button.
- dialogBuilder.setPositiveButton(R.string.save, new Dialog.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Return the `DialogFragment` to the parent activity on save.
- editBookmarkFolderListener.onSaveEditBookmarkFolder(EditBookmarkFolderDialog.this, selectedFolderDatabaseId);
- }
+ dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
+ // Return the `DialogFragment` to the parent activity on save.
+ editBookmarkFolderListener.onSaveBookmarkFolder(EditBookmarkFolderDialog.this, selectedFolderDatabaseId);
});
// Create an `AlertDialog` from the `AlertDialog.Builder`.
// 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);
+ final RadioButton currentIconRadioButton = alertDialog.findViewById(R.id.edit_folder_current_icon_radiobutton);
+ RadioGroup iconRadioGroup = alertDialog.findViewById(R.id.edit_folder_icon_radio_group);
// Initially disable the edit button.
editButton.setEnabled(false);
// 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`.
- ImageView currentIconImageView = (ImageView) alertDialog.findViewById(R.id.edit_folder_current_icon);
+ ImageView currentIconImageView = alertDialog.findViewById(R.id.edit_folder_current_icon_imageview);
currentIconImageView.setImageBitmap(currentIconBitmap);
// Get a `Bitmap` of the favorite icon from `MainWebViewActivity` and display it in `edit_folder_web_page_favorite_icon`.
- ImageView webPageFavoriteIconImageView = (ImageView) alertDialog.findViewById(R.id.edit_folder_web_page_favorite_icon);
+ ImageView webPageFavoriteIconImageView = alertDialog.findViewById(R.id.edit_folder_web_page_favorite_icon_imageview);
webPageFavoriteIconImageView.setImageBitmap(MainWebViewActivity.favoriteIconBitmap);
// Get the current folder 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);
+ final EditText folderNameEditText = alertDialog.findViewById(R.id.edit_folder_name_edittext);
folderNameEditText.setText(currentFolderName);
// Update the status of the edit button when the folder name is changed.
Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName);
// Is the new folder name empty?
- boolean folderNameEmpty = newFolderName.isEmpty();
+ boolean folderNameNotEmpty = !newFolderName.isEmpty();
// Does the folder name already exist?
boolean folderNameAlreadyExists = (!newFolderName.equals(currentFolderName) && (folderExistsCursor.getCount() > 0));
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));
+ editButton.setEnabled(folderNameNotEmpty && (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();
+ iconRadioGroup.setOnCheckedChangeListener((RadioGroup group, 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 = bookmarksDatabaseHelper.getFolderCursor(newFolderName);
+ // Get a cursor for the new folder name if it exists.
+ Cursor folderExistsCursor = bookmarksDatabaseHelper.getFolderCursor(newFolderName);
- // Is the new folder name empty?
- boolean folderNameEmpty = newFolderName.isEmpty();
+ // Is the new folder name empty?
+ boolean folderNameEmpty = newFolderName.isEmpty();
- // Does the folder name already exist?
- boolean folderNameAlreadyExists = (!newFolderName.equals(currentFolderName) && (folderExistsCursor.getCount() > 0));
+ // 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 folder been renamed?
+ boolean folderRenamed = (!newFolderName.equals(currentFolderName) && !folderNameAlreadyExists);
- // Has the favorite icon changed?
- boolean iconChanged = (!currentIconRadioButton.isChecked() && !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));
- }
+ // 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) && 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, 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.
- return false;
- }
+ folderNameEditText.setOnKeyListener((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) && editButton.isEnabled()) { // The enter key was pressed and the edit button is enabled.
+ // Trigger `editBookmarkListener` and return the DialogFragment to the parent activity.
+ editBookmarkFolderListener.onSaveBookmarkFolder(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.
+ return false;
}
});
import java.io.ByteArrayOutputStream;
public class MoveToFolderDialog extends AppCompatDialogFragment {
+ // Instantiate class variables.
+ private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+ private StringBuilder exceptFolders;
+
// The public interface is used to send information back to the parent activity.
public interface MoveToFolderListener {
void onMoveToFolder(AppCompatDialogFragment dialogFragment);
}
}
- // `exceptFolders` is used in `onCreateDialog()` and `addSubfoldersToExceptFolders()`.
- private String exceptFolders;
-
// `@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) {
+ // 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 = new BookmarksDatabaseHelper(getContext(), null, null, 0);
+
// Use `AlertDialog.Builder` to create the `AlertDialog`.
AlertDialog.Builder dialogBuilder;
dialogBuilder.setView(getActivity().getLayoutInflater().inflate(R.layout.move_to_folder_dialog, null));
// Set an `onClick()` listener for the negative button.
- dialogBuilder.setNegativeButton(R.string.cancel, new Dialog.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Do nothing. The `AlertDialog` will close automatically.
- }
+ dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
+ // Do nothing. The `AlertDialog` will close automatically.
});
// Set the `onClick()` listener fo the positive button.
- dialogBuilder.setPositiveButton(R.string.move, new Dialog.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Return the `DialogFragment` to the parent activity on save.
- moveToFolderListener.onMoveToFolder(MoveToFolderDialog.this);
- }
+ dialogBuilder.setPositiveButton(R.string.move, (DialogInterface dialog, int which) -> {
+ // Return the `DialogFragment` to the parent activity on save.
+ moveToFolderListener.onMoveToFolder(MoveToFolderDialog.this);
});
// Create an `AlertDialog` from the `AlertDialog.Builder`.
// Check to see if we are in the `Home Folder`.
if (BookmarksActivity.currentFolder.isEmpty()) { // Don't display `Home Folder` at the top of the `ListView`.
// Initialize `exceptFolders`.
- exceptFolders = "";
+ exceptFolders = new StringBuilder();
// If a folder is selected, add it and all children to the list of folders not to display.
long[] selectedBookmarksLongArray = BookmarksActivity.checkedItemIds;
int databaseIdInt = (int) databaseIdLong;
// If `databaseIdInt` is a folder.
- if (BookmarksActivity.bookmarksDatabaseHelper.isFolder(databaseIdInt)) {
+ if (bookmarksDatabaseHelper.isFolder(databaseIdInt)) {
// Get the name of the selected folder.
- String folderName = BookmarksActivity.bookmarksDatabaseHelper.getFolderName(databaseIdInt);
+ String folderName = bookmarksDatabaseHelper.getFolderName(databaseIdInt);
- if (exceptFolders.isEmpty()){
+ // Populate the list of folders not to get.
+ if (exceptFolders.toString().isEmpty()){
// Add the selected folder to the list of folders not to display.
- exceptFolders = DatabaseUtils.sqlEscapeString(folderName);
+ exceptFolders.append(DatabaseUtils.sqlEscapeString(folderName));
} else {
// Add the selected folder to the end of the list of folders not to display.
- exceptFolders = exceptFolders + "," + DatabaseUtils.sqlEscapeString(folderName);
+ exceptFolders.append(",");
+ exceptFolders.append(DatabaseUtils.sqlEscapeString(folderName));
}
// Add the selected folder's subfolders to the list of folders not to display.
}
// Get a `Cursor` containing the folders to display.
- foldersCursor = BookmarksActivity.bookmarksDatabaseHelper.getFoldersCursorExcept(exceptFolders);
+ foldersCursor = bookmarksDatabaseHelper.getFoldersCursorExcept(exceptFolders.toString());
// Setup `foldersCursorAdaptor` with `this` context. `false` disables autoRequery.
foldersCursorAdapter = new CursorAdapter(alertDialog.getContext(), foldersCursor, false) {
// Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last.
Bitmap folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.length);
// Display `folderIconBitmap` in `move_to_folder_icon`.
- ImageView folderIconImageView = (ImageView) view.findViewById(R.id.move_to_folder_icon);
+ ImageView folderIconImageView = view.findViewById(R.id.move_to_folder_icon);
folderIconImageView.setImageBitmap(folderIconBitmap);
// Get the folder name from `cursor` and display it in `move_to_folder_name_textview`.
String folderName = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- TextView folderNameTextView = (TextView) view.findViewById(R.id.move_to_folder_name_textview);
+ TextView folderNameTextView = view.findViewById(R.id.move_to_folder_name_textview);
folderNameTextView.setText(folderName);
}
};
homeFolderMatrixCursor.addRow(new Object[]{0, getString(R.string.home_folder), homeFolderIconByteArray});
// Add the parent folder to the list of folders not to display.
- exceptFolders = DatabaseUtils.sqlEscapeString(BookmarksActivity.currentFolder);
+ exceptFolders.append(DatabaseUtils.sqlEscapeString(BookmarksActivity.currentFolder));
// If a folder is selected, add it and all children to the list of folders not to display.
long[] selectedBookmarksLongArray = BookmarksActivity.checkedItemIds;
int databaseIdInt = (int) databaseIdLong;
// If `databaseIdInt` is a folder.
- if (BookmarksActivity.bookmarksDatabaseHelper.isFolder(databaseIdInt)) {
+ if (bookmarksDatabaseHelper.isFolder(databaseIdInt)) {
// Get the name of the selected folder.
- String folderName = BookmarksActivity.bookmarksDatabaseHelper.getFolderName(databaseIdInt);
+ String folderName = bookmarksDatabaseHelper.getFolderName(databaseIdInt);
// Add the selected folder to the end of the list of folders not to display.
- exceptFolders = exceptFolders + "," + DatabaseUtils.sqlEscapeString(folderName);
+ exceptFolders.append(",");
+ exceptFolders.append(DatabaseUtils.sqlEscapeString(folderName));
// Add the selected folder's subfolders to the list of folders not to display.
addSubfoldersToExceptFolders(folderName);
}
// Get a `Cursor` containing the folders to display.
- foldersCursor = BookmarksActivity.bookmarksDatabaseHelper.getFoldersCursorExcept(exceptFolders);
+ foldersCursor = bookmarksDatabaseHelper.getFoldersCursorExcept(exceptFolders.toString());
// Combine `homeFolderMatrixCursor` and `foldersCursor`.
MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{homeFolderMatrixCursor, foldersCursor});
// Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last.
Bitmap folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.length);
// Display `folderIconBitmap` in `move_to_folder_icon`.
- ImageView folderIconImageView = (ImageView) view.findViewById(R.id.move_to_folder_icon);
+ ImageView folderIconImageView = view.findViewById(R.id.move_to_folder_icon);
folderIconImageView.setImageBitmap(folderIconBitmap);
// Get the folder name from `cursor` and display it in `move_to_folder_name_textview`.
String folderName = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
- TextView folderNameTextView = (TextView) view.findViewById(R.id.move_to_folder_name_textview);
+ TextView folderNameTextView = view.findViewById(R.id.move_to_folder_name_textview);
folderNameTextView.setText(folderName);
}
};
}
// Display the ListView
- ListView foldersListView = (ListView) alertDialog.findViewById(R.id.move_to_folder_listview);
+ ListView foldersListView = alertDialog.findViewById(R.id.move_to_folder_listview);
foldersListView.setAdapter(foldersCursorAdapter);
// Enable the move button when a folder is selected.
- foldersListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- // Enable the move button.
- moveButton.setEnabled(true);
- }
+ foldersListView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
+ // Enable the move button.
+ moveButton.setEnabled(true);
});
// `onCreateDialog` requires the return of an `AlertDialog`.
private void addSubfoldersToExceptFolders(String folderName) {
// Get a `Cursor` will all the immediate subfolders.
- Cursor subfoldersCursor = BookmarksActivity.bookmarksDatabaseHelper.getSubfoldersCursor(folderName);
+ Cursor subfoldersCursor = bookmarksDatabaseHelper.getSubfoldersCursor(folderName);
for (int i = 0; i < subfoldersCursor.getCount(); i++) {
// Move `subfolderCursor` to the current item.
// Get the name of the subfolder.
String subfolderName = subfoldersCursor.getString(subfoldersCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+ // Add the subfolder to `exceptFolders`.
+ exceptFolders.append(",");
+ exceptFolders.append(DatabaseUtils.sqlEscapeString(subfolderName));
+
// Run the same tasks for any subfolders of the subfolder.
addSubfoldersToExceptFolders(subfolderName);
-
- // Add the subfolder to `exceptFolders`.
- subfolderName = DatabaseUtils.sqlEscapeString(subfolderName);
- exceptFolders = exceptFolders + "," + subfolderName;
}
-
}
}
tabLayout = inflater.inflate(R.layout.about_tab_version, container, false);
// Get handles for the `TextViews`.
- TextView versionNumberTextView = (TextView) tabLayout.findViewById(R.id.about_version_number);
- TextView versionBrandTextView = (TextView) tabLayout.findViewById(R.id.about_version_brand);
- TextView versionManufacturerTextView = (TextView) tabLayout.findViewById(R.id.about_version_manufacturer);
- TextView versionModelTextView = (TextView) tabLayout.findViewById(R.id.about_version_model);
- TextView versionDeviceTextView = (TextView) tabLayout.findViewById(R.id.about_version_device);
- TextView versionBootloaderTextView = (TextView) tabLayout.findViewById(R.id.about_version_bootloader);
- TextView versionRadioTextView = (TextView) tabLayout.findViewById(R.id.about_version_radio);
- TextView versionAndroidTextView = (TextView) tabLayout.findViewById(R.id.about_version_android);
- TextView versionBuildTextView = (TextView) tabLayout.findViewById(R.id.about_version_build);
- TextView versionSecurityPatchTextView = (TextView) tabLayout.findViewById(R.id.about_version_securitypatch);
- TextView versionWebKitTextView = (TextView) tabLayout.findViewById(R.id.about_version_webkit);
- TextView versionChromeTextView = (TextView) tabLayout.findViewById(R.id.about_version_chrome);
- TextView versionOrbotTextView = (TextView) tabLayout.findViewById(R.id.about_version_orbot);
- TextView certificateIssuerDNTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_issuer_dn);
- TextView certificateSubjectDNTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_subject_dn);
- TextView certificateStartDateTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_start_date);
- TextView certificateEndDateTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_end_date);
- TextView certificateVersionTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_version);
- TextView certificateSerialNumberTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_serial_number);
- TextView certificateSignatureAlgorithmTextView = (TextView) tabLayout.findViewById(R.id.about_version_certificate_signature_algorithm);
+ TextView versionNumberTextView = tabLayout.findViewById(R.id.about_version_number);
+ TextView versionBrandTextView = tabLayout.findViewById(R.id.about_version_brand);
+ TextView versionManufacturerTextView = tabLayout.findViewById(R.id.about_version_manufacturer);
+ TextView versionModelTextView = tabLayout.findViewById(R.id.about_version_model);
+ TextView versionDeviceTextView = tabLayout.findViewById(R.id.about_version_device);
+ TextView versionBootloaderTextView = tabLayout.findViewById(R.id.about_version_bootloader);
+ TextView versionRadioTextView = tabLayout.findViewById(R.id.about_version_radio);
+ TextView versionAndroidTextView = tabLayout.findViewById(R.id.about_version_android);
+ TextView versionSecurityPatchTextView = tabLayout.findViewById(R.id.about_version_securitypatch);
+ TextView versionBuildTextView = tabLayout.findViewById(R.id.about_version_build);
+ TextView versionWebKitTextView = tabLayout.findViewById(R.id.about_version_webkit);
+ TextView versionChromeTextView = tabLayout.findViewById(R.id.about_version_chrome);
+ TextView versionOrbotTextView = tabLayout.findViewById(R.id.about_version_orbot);
+ TextView certificateIssuerDNTextView = tabLayout.findViewById(R.id.about_version_certificate_issuer_dn);
+ TextView certificateSubjectDNTextView = tabLayout.findViewById(R.id.about_version_certificate_subject_dn);
+ TextView certificateStartDateTextView = tabLayout.findViewById(R.id.about_version_certificate_start_date);
+ TextView certificateEndDateTextView = tabLayout.findViewById(R.id.about_version_certificate_end_date);
+ TextView certificateVersionTextView = tabLayout.findViewById(R.id.about_version_certificate_version);
+ TextView certificateSerialNumberTextView = tabLayout.findViewById(R.id.about_version_certificate_serial_number);
+ TextView certificateSignatureAlgorithmTextView = tabLayout.findViewById(R.id.about_version_certificate_signature_algorithm);
// Setup the labels.
String version = getString(R.string.version) + " " + BuildConfig.VERSION_NAME + " (" + getString(R.string.version_code) + " " + Integer.toString(BuildConfig.VERSION_CODE) + ")";
// `webViewLayout` is only used to get the default user agent from `bare_webview`. It is not used to render content on the screen.
View webViewLayout = inflater.inflate(R.layout.bare_webview, container, false);
- WebView tabLayoutWebView = (WebView) webViewLayout.findViewById(R.id.bare_webview);
+ WebView tabLayoutWebView = webViewLayout.findViewById(R.id.bare_webview);
String userAgentString = tabLayoutWebView.getSettings().getUserAgentString();
// Get the device's information and store it in strings.
private static final String BOOKMARKS_TABLE = "bookmarks";
public static final String _ID = "_id";
- public static final String DISPLAY_ORDER = "displayorder";
public static final String BOOKMARK_NAME = "bookmarkname";
public static final String BOOKMARK_URL = "bookmarkurl";
public static final String PARENT_FOLDER = "parentfolder";
+ public static final String DISPLAY_ORDER = "displayorder";
public static final String IS_FOLDER = "isfolder";
public static final String FAVORITE_ICON = "favoriteicon";
// Setup the SQL string to create the `bookmarks` table.
final String CREATE_BOOKMARKS_TABLE = "CREATE TABLE " + BOOKMARKS_TABLE + " (" +
_ID + " integer primary key, " +
- DISPLAY_ORDER + " integer, " +
BOOKMARK_NAME + " text, " +
BOOKMARK_URL + " text, " +
PARENT_FOLDER + " text, " +
+ DISPLAY_ORDER + " integer, " +
IS_FOLDER + " boolean, " +
FAVORITE_ICON + " blob);";
}
// Create a bookmark.
- public void createBookmark(String bookmarkName, String bookmarkURL, int displayOrder, String parentFolder, byte[] favoriteIcon) {
+ public void createBookmark(String bookmarkName, String bookmarkURL, String parentFolder, int displayOrder, byte[] favoriteIcon) {
// We need to store the bookmark data in a `ContentValues`.
ContentValues bookmarkContentValues = new ContentValues();
// ID is created automatically.
- bookmarkContentValues.put(DISPLAY_ORDER, displayOrder);
bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName);
bookmarkContentValues.put(BOOKMARK_URL, bookmarkURL);
bookmarkContentValues.put(PARENT_FOLDER, parentFolder);
+ bookmarkContentValues.put(DISPLAY_ORDER, displayOrder);
bookmarkContentValues.put(IS_FOLDER, false);
bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon);
}
// Create a folder.
- public void createFolder(String folderName, int displayOrder, String parentFolder, byte[] favoriteIcon) {
+ public void createFolder(String folderName, String parentFolder, byte[] favoriteIcon) {
ContentValues bookmarkContentValues = new ContentValues();
- // ID is created automatically.
- bookmarkContentValues.put(DISPLAY_ORDER, displayOrder);
+ // ID is created automatically. Folders are always created at the top of the list.
bookmarkContentValues.put(BOOKMARK_NAME, folderName);
bookmarkContentValues.put(PARENT_FOLDER, parentFolder);
+ bookmarkContentValues.put(DISPLAY_ORDER, 0);
bookmarkContentValues.put(IS_FOLDER, true);
bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon);
return folderName;
}
+ // The the database ID for the specified folder name.
+ public int getFolderDatabaseId (String folderName) {
+ // Get a readable database handle.
+ SQLiteDatabase bookmarksDatabase = this.getReadableDatabase();
+
+ // SQL escape `folderName`.
+ folderName = DatabaseUtils.sqlEscapeString(folderName);
+
+ // Prepare the SQL statement to get the `Cursor` for the folder.
+ final String GET_FOLDER = "SELECT * FROM " + BOOKMARKS_TABLE +
+ " WHERE " + BOOKMARK_NAME + " = " + folderName +
+ " AND " + IS_FOLDER + " = " + 1;
+
+ // Get `folderCursor`. The second argument is `null` because there are no `selectionArgs`.
+ Cursor folderCursor = bookmarksDatabase.rawQuery(GET_FOLDER, null);
+
+ // Get the database ID.
+ folderCursor.moveToFirst();
+ int databaseId = folderCursor.getInt(folderCursor.getColumnIndex(_ID));
+
+ // Close the cursor and the database handle.
+ folderCursor.close();
+ bookmarksDatabase.close();
+
+ // Return the database ID.
+ return databaseId;
+ }
+
// Get a `Cursor` for the specified folder name.
public Cursor getFolderCursor(String folderName) {
// Get a readable database handle.
// Get a readable database handle.
SQLiteDatabase bookmarksDatabase = this.getReadableDatabase();
- // Prepare a string that contains the comma-separated list of IDs not to get.
- String doNotGetIdsString = "";
+ // Prepare a string builder that contains the comma-separated list of IDs not to get.
+ StringBuilder doNotGetIdsStringBuilder = new StringBuilder();
+
// Extract the array to `doNotGetIdsString`.
for (long databaseIdLong : exceptIdLongArray) {
// If this is the first number, only add the number.
- if (doNotGetIdsString.isEmpty()) {
- doNotGetIdsString = String.valueOf(databaseIdLong);
- } else { // If there already is a number in the string, place a `,` before the number.
- doNotGetIdsString = doNotGetIdsString + "," + databaseIdLong;
+ if (doNotGetIdsStringBuilder.toString().isEmpty()) {
+ doNotGetIdsStringBuilder.append(databaseIdLong);
+ } else { // If there already is a number in the string, place a `,` before the new number.
+ doNotGetIdsStringBuilder.append(",");
+ doNotGetIdsStringBuilder.append(databaseIdLong);
}
}
// Prepare the SQL statement to select all items except those with the specified IDs.
final String GET_All_BOOKMARKS_EXCEPT_SPECIFIED = "SELECT * FROM " + BOOKMARKS_TABLE +
" WHERE " + PARENT_FOLDER + " = " + folderName +
- " AND " + _ID + " NOT IN (" + doNotGetIdsString +
+ " AND " + _ID + " NOT IN (" + doNotGetIdsStringBuilder.toString() +
") ORDER BY " + DISPLAY_ORDER + " ASC";
// Return the results as a `Cursor`. The second argument is `null` because there are no `selectionArgs`.
// Update the bookmark name and URL.
public void updateBookmark(int databaseId, String bookmarkName, String bookmarkUrl) {
- // Store the updated values in `bookmarkContentValues`.
+ // Initialize a `ContentValues`.
ContentValues bookmarkContentValues = new ContentValues();
+ // Store the updated values.
bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName);
bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl);
bookmarksDatabase.close();
}
+ // Update the bookmark name, URL, parent folder, and display order.
+ public void updateBookmark(int databaseId, String bookmarkName, String bookmarkUrl, String parentFolder, int displayOrder) {
+ // Initialize a `ContentValues`.
+ ContentValues bookmarkContentValues = new ContentValues();
+
+ // Store the updated values.
+ bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName);
+ bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl);
+ bookmarkContentValues.put(PARENT_FOLDER, parentFolder);
+ bookmarkContentValues.put(DISPLAY_ORDER, displayOrder);
+
+ // Get a writable database handle.
+ SQLiteDatabase bookmarksDatabase = this.getWritableDatabase();
+
+ // Update the bookmark. The last argument is `null` because there are no `whereArgs`.
+ bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, _ID + " = " + databaseId, null);
+
+ // Close the database handle.
+ 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`.
+ // Initialize a `ContentValues`.
+ ContentValues bookmarkContentValues = new ContentValues();
+
+ // Store the updated values.
+ bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName);
+ bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl);
+ bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon);
+
+ // Get a writable database handle.
+ SQLiteDatabase bookmarksDatabase = this.getWritableDatabase();
+
+ // Update the bookmark. The last argument is `null` because there are no `whereArgs`.
+ bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, _ID + " = " + databaseId, null);
+
+ // Close the database handle.
+ bookmarksDatabase.close();
+ }
+
+ // Update the bookmark name, URL, parent folder, display order, and favorite icon.
+ public void updateBookmark(int databaseId, String bookmarkName, String bookmarkUrl, String parentFolder, int displayOrder, byte[] favoriteIcon) {
+ // Initialize a `ContentValues`.
ContentValues bookmarkContentValues = new ContentValues();
+ // Store the updated values.
bookmarkContentValues.put(BOOKMARK_NAME, bookmarkName);
bookmarkContentValues.put(BOOKMARK_URL, bookmarkUrl);
+ bookmarkContentValues.put(PARENT_FOLDER, parentFolder);
+ bookmarkContentValues.put(DISPLAY_ORDER, displayOrder);
bookmarkContentValues.put(FAVORITE_ICON, favoriteIcon);
// Get a writable database handle.
bookmarksDatabase.close();
}
+ // Update the folder name, parent folder, and display order.
+ public void updateFolder(int databaseId, String oldFolderName, String newFolderName, String parentFolder, int displayOrder) {
+ // Get a writable database handle.
+ SQLiteDatabase bookmarksDatabase = this.getWritableDatabase();
+
+ // Update the folder first. Store the new folder name in `folderContentValues`.
+ ContentValues folderContentValues = new ContentValues();
+ folderContentValues.put(BOOKMARK_NAME, newFolderName);
+ folderContentValues.put(PARENT_FOLDER, parentFolder);
+ folderContentValues.put(DISPLAY_ORDER, displayOrder);
+
+ // 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. 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 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 name and icon.
public void updateFolder(int databaseId, String oldFolderName, String newFolderName, byte[] folderIcon) {
// Get a writable database handle.
bookmarksDatabase.close();
}
+ // Update the folder name and icon.
+ public void updateFolder(int databaseId, String oldFolderName, String newFolderName, String parentFolder, int displayOrder, 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(PARENT_FOLDER, parentFolder);
+ folderContentValues.put(DISPLAY_ORDER, displayOrder);
+ 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. 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 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 display order for one bookmark or folder.
public void updateDisplayOrder(int databaseId, int displayOrder) {
// Get a writable database handle.
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+ This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+ Privacy Browser is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Privacy Browser is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- Change the dark theme enabled text from white to gray. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <!-- `#4DFFFFFF` comes from the built-in `@color/primary_text_disabled_material_dark`. -->
+ <item android:state_checked="false" android:color="#4DFFFFFF" />
+ <item android:color="@color/gray_300" />
+</selector>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+ This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+ Privacy Browser is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Privacy Browser is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- Change the dark theme enabled text from white to gray.-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:state_checked="false" android:color="@color/gray_600" />
+ <item android:color="@color/black" />
+</selector>
\ No newline at end of file
You should have received a copy of the GNU General Public License
along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
-<!-- Change the dark theme enabled text from white to gray. -->
+<!-- Change the dark theme enabled text from white to gray.-->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_enabled="false" android:color="@color/gray_400" />
<item android:color="@color/black" />
android:layout_width="wrap_content" />
<TextView
- android:id="@+id/about_version_build"
+ android:id="@+id/about_version_securitypatch"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
<TextView
- android:id="@+id/about_version_securitypatch"
+ android:id="@+id/about_version_build"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
When it is specified the theme should include `<item name="android:windowTranslucentStatus">true</item>`
to make the status bar a transparent, darkened overlay. -->
<android.support.design.widget.CoordinatorLayout
- android:id="@+id/bookmarks_database_view_coordinatorlayout"
+ android:id="@+id/bookmarks_databaseview_coordinatorlayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical" >
<android.support.design.widget.AppBarLayout
- android:id="@+id/bookmarks_database_view_appbarlayout"
+ android:id="@+id/bookmarks_databaseview_appbarlayout"
android:layout_height="wrap_content"
android:layout_width="match_parent" >
<android.support.v7.widget.Toolbar
- android:id="@+id/bookmarks_database_view_toolbar"
+ android:id="@+id/bookmarks_databaseview_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="?attr/colorPrimaryDark"
</android.support.design.widget.AppBarLayout>
<ListView
- android:id="@+id/bookmarks_database_view_listview"
+ android:id="@+id/bookmarks_databaseview_listview"
android:layout_height="match_parent"
android:layout_width="match_parent" />
</LinearLayout>
along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
<LinearLayout
- android:id="@+id/bookmarks_database_view_item_linearlayout"
+ android:id="@+id/bookmarks_databaseview_item_linearlayout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
- android:id="@+id/bookmarks_database_view_database_id"
+ android:id="@+id/bookmarks_databaseview_database_id"
android:layout_height="wrap_content"
android:layout_width="50dp"
android:layout_marginEnd="10dp"
android:textSize="22sp" />
<ImageView
- android:id="@+id/bookmarks_database_view_favorite_icon"
+ android:id="@+id/bookmarks_databaseview_favorite_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
tools:ignore="ContentDescription" />
<TextView
- android:id='@+id/bookmarks_database_view_bookmark_name'
+ android:id='@+id/bookmarks_databaseview_bookmark_name'
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textColor="?android:attr/textColorPrimary"
</LinearLayout>
<!-- Second row. -->
+ <TextView
+ android:id="@+id/bookmarks_databaseview_bookmark_url"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="13dp"
+ android:layout_marginEnd="10dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="22sp"
+ android:ellipsize="end"
+ android:maxLines="1" />
+
+ <!-- Third row. -->
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
+ android:layout_marginBottom="10dp"
android:orientation="horizontal" >
<TextView
- android:id="@+id/bookmarks_database_view_display_order"
+ android:id="@+id/bookmarks_databaseview_display_order"
android:layout_height="wrap_content"
android:layout_width="50dp"
android:layout_marginEnd="10dp"
android:textSize="22sp" />
<ImageView
- android:id="@+id/bookmarks_database_view_parent_folder_icon"
+ android:id="@+id/bookmarks_databaseview_parent_folder_icon"
android:layout_height="30dp"
android:layout_width="30dp"
android:layout_gravity="center_vertical"
tools:ignore="ContentDescription" />
<TextView
- android:id="@+id/bookmarks_database_view_parent_folder"
+ android:id="@+id/bookmarks_databaseview_parent_folder"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="22sp"
android:ellipsize="end"
android:maxLines="1" />
</LinearLayout>
-
- <!-- Third row. -->
- <TextView
- android:id="@+id/bookmarks_database_view_bookmark_url"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_marginBottom="10dp"
- android:layout_marginStart="13dp"
- android:layout_marginEnd="10dp"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="22sp"
- android:ellipsize="end"
- android:maxLines="1" />
</LinearLayout>
\ No newline at end of file
<Spinner
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/bookmarks_database_view_spinner"
+ android:id="@+id/bookmarks_databaseview_spinner"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+ This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+ Privacy Browser is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Privacy Browser is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent" >
+
+ <!-- Setting `android:focusable` and `android:focusableInTouchMode` prevent `edit_bookmark_display_order_edittext` from being autoselected. -->
+ <LinearLayout
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:focusable="true"
+ android:focusableInTouchMode="true" >
+
+ <!-- Database ID. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="6dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="7dp" >
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/database_id"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector"
+ android:layout_marginEnd="8dp" />
+
+ <TextView
+ android:id="@+id/edit_bookmark_database_id_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="18sp"
+ android:textColor="@color/gray_500" />
+ </LinearLayout>
+
+ <!-- The icon selection rows. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal" >
+
+ <!-- The column displaying the icons. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="10dp"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@+id/edit_bookmark_current_icon"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_gravity="center_vertical"
+ tools:ignore="ContentDescription" />
+
+ <ImageView
+ android:id="@+id/edit_bookmark_webpage_favorite_icon"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ tools:ignore="ContentDescription" />
+ </LinearLayout>
+
+ <!-- The column with the `RadioGroup`. -->
+ <RadioGroup
+ android:id="@+id/edit_bookmark_icon_radiogroup"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:checkedButton="@+id/edit_bookmark_current_icon_radiobutton" >
+
+ <RadioButton
+ android:id="@id/edit_bookmark_current_icon_radiobutton"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="4dp"
+ android:text="@string/current_bookmark_icon"
+ android:textSize="18sp" />
+
+ <RadioButton
+ android:id="@+id/edit_bookmark_webpage_favorite_icon_radiobutton"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="5dp"
+ android:text="@string/web_page_favorite_icon"
+ android:textSize="18sp" />
+ </RadioGroup>
+ </LinearLayout>
+
+ <!-- Bookmark name. `android.support.design.widget.TextInputLayout` makes the `android:hint` float above the `EditText`. -->
+ <android.support.design.widget.TextInputLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="6dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp" >
+
+ <!-- `android:imeOptions="actionGo"` sets the keyboard to have a `go` key instead of a `new line` key. `android:inputType="textUri"` disables spell check in the `EditText`. -->
+ <android.support.design.widget.TextInputEditText
+ android:id="@+id/edit_bookmark_name_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:hint="@string/bookmark_name"
+ android:imeOptions="actionGo"
+ android:inputType="textUri"
+ android:selectAllOnFocus="true" />
+ </android.support.design.widget.TextInputLayout>
+
+ <!-- URL. `android.support.design.widget.TextInputLayout` makes the `android:hint` float above the `EditText`. -->
+ <android.support.design.widget.TextInputLayout
+ 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" >
+
+ <!-- `android:imeOptions="actionGo"` sets the keyboard to have a `go` key instead of a `new line` key. `android:inputType="textUri"` disables spell check in the `EditText`. -->
+ <EditText
+ android:id="@+id/edit_bookmark_url_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:hint="@string/bookmark_url"
+ android:imeOptions="actionGo"
+ android:inputType="textUri"
+ android:selectAllOnFocus="true" />
+ </android.support.design.widget.TextInputLayout>
+
+ <!-- Folder. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:layout_marginTop="6dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="7dp" >
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/folder"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector" />
+
+ <Spinner
+ android:id="@+id/edit_bookmark_folder_spinner"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content" />
+ </LinearLayout>
+
+ <!-- Display order. -->
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="7dp" >
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/display_order"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector"
+ android:layout_marginEnd="6dp"
+ android:labelFor="@+id/edit_bookmark_display_order_edittext"/>
+
+ <EditText
+ android:id="@id/edit_bookmark_display_order_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:imeOptions="actionGo"
+ android:inputType="number"
+ android:selectAllOnFocus="true" />
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+ This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+ Privacy Browser is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Privacy Browser is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- A `CheckedTextView` allows the color of the text to be changed when it is selected (checked). -->
+<CheckedTextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/spinner_item_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:textSize="18sp"
+ android:textColor="?attr/editBookmarkSpinnerTextColorSelector" />
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+ This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+ Privacy Browser is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Privacy Browser is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/spinner_item_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector" />
\ No newline at end of file
tools:ignore="ContentDescription" />
<ImageView
- android:id="@+id/edit_bookmark_web_page_favorite_icon"
+ android:id="@+id/edit_bookmark_webpage_favorite_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="6dp"
android:textSize="18sp" />
<RadioButton
- android:id="@+id/edit_bookmark_web_page_favorite_icon_radiobutton"
+ android:id="@+id/edit_bookmark_webpage_favorite_icon_radiobutton"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp" >
- <!-- `android:imeOptions="actionGo"` sets the keyboard to have a `go` key instead of a `new line` key.
- `android:inputType="textUri"` disables spell check in the `EditText`. -->
+ <!-- `android:imeOptions="actionGo"` sets the keyboard to have a `go` key instead of a `new line` key. `android:inputType="textUri"` disables spell check in the `EditText`. -->
<android.support.design.widget.TextInputEditText
android:id="@+id/edit_bookmark_name_edittext"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp" >
- <!-- `android:imeOptions="actionGo"` sets the keyboard to have a "go" key instead of a "new line" key.
- `android:inputType="textUri"` disables spell check in the EditText. -->
+ <!-- `android:imeOptions="actionGo"` sets the keyboard to have a `go` key instead of a `new line` key. `android:inputType="textUri"` disables spell check in the `EditText`. -->
<EditText
android:id="@+id/edit_bookmark_url_edittext"
android:layout_height="wrap_content"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+ This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+ Privacy Browser is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Privacy Browser is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>. -->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent" >
+
+ <!-- Setting `android:focusable` and `android:focusableInTouchMode` prevent `edit_bookmark_display_order_edittext` from being autoselected. -->
+ <LinearLayout
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:focusable="true"
+ android:focusableInTouchMode="true" >
+
+ <!-- Database ID. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="6dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="7dp" >
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/database_id"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector"
+ android:layout_marginEnd="8dp" />
+
+ <TextView
+ android:id="@+id/edit_folder_database_id_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="18sp"
+ android:textColor="@color/gray_500" />
+ </LinearLayout>
+
+ <!-- The icon selection rows. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal" >
+
+ <!-- The column displaying the icons. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="10dp"
+ android:orientation="vertical" >
+
+ <ImageView
+ android:id="@+id/edit_folder_current_icon_imageview"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_gravity="center_vertical"
+ tools:ignore="ContentDescription" />
+
+ <ImageView
+ android:id="@+id/edit_folder_default_icon_imageview"
+ android:layout_height="30dp"
+ android:layout_width="30dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/folder_blue_bitmap"
+ tools:ignore="ContentDescription" />
+
+ <ImageView
+ android:id="@+id/edit_folder_webpage_favorite_icon_imageview"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ tools:ignore="ContentDescription" />
+ </LinearLayout>
+
+ <!-- The column with the `RadioGroup`. -->
+ <RadioGroup
+ android:id="@+id/edit_folder_icon_radiogroup"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:checkedButton="@+id/edit_folder_current_icon_radiobutton" >
+
+ <RadioButton
+ android:id="@id/edit_folder_current_icon_radiobutton"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="4dp"
+ android:text="@string/current_bookmark_icon"
+ android:textSize="18sp" />
+
+ <RadioButton
+ android:id="@+id/edit_folder_default_icon_radiobutton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp"
+ android:layout_marginBottom="4dp"
+ android:text="@string/default_folder_icon"
+ android:textSize="18sp" />
+
+ <RadioButton
+ android:id="@+id/edit_folder_webpage_favorite_icon_radiobutton"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="5dp"
+ android:text="@string/web_page_favorite_icon"
+ android:textSize="18sp" />
+ </RadioGroup>
+ </LinearLayout>
+
+ <!-- Folder name. `android.support.design.widget.TextInputLayout` makes the `android:hint` float above the `EditText`. -->
+ <android.support.design.widget.TextInputLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp" >
+
+ <!-- `android:imeOptions="actionGo"` sets the keyboard to have a `go` key instead of a `new line` key. `android:inputType="textUri"` disables spell check in the `EditText`. -->
+ <android.support.design.widget.TextInputEditText
+ android:id="@+id/edit_folder_name_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:hint="@string/folder_name"
+ android:imeOptions="actionGo"
+ android:inputType="textUri"
+ android:selectAllOnFocus="true" />
+ </android.support.design.widget.TextInputLayout>
+
+ <!-- Folder. -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:layout_marginTop="6dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="7dp" >
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/parent_folder"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector" />
+
+ <Spinner
+ android:id="@+id/edit_folder_parent_folder_spinner"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content" />
+ </LinearLayout>
+
+ <!-- Display order. -->
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:layout_marginTop="6dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="7dp" >
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/display_order"
+ android:textSize="18sp"
+ android:textColor="?attr/primaryTextColorSelector"
+ android:layout_marginEnd="6dp"
+ android:labelFor="@+id/edit_folder_display_order_edittext"/>
+
+ <EditText
+ android:id="@id/edit_folder_display_order_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:imeOptions="actionGo"
+ android:inputType="number"
+ android:selectAllOnFocus="true" />
+ </LinearLayout>
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:gravity="center_horizontal"
+ android:text="@string/folder_names_must_be_unique" />
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
android:layout_marginEnd="10dp" >
<ImageView
- android:id="@+id/edit_folder_current_icon"
+ android:id="@+id/edit_folder_current_icon_imageview"
android:layout_height="30dp"
android:layout_width="30dp"
android:layout_marginTop="12dp"
tools:ignore="ContentDescription" />
<ImageView
- android:id="@+id/edit_folder_default_icon"
+ android:id="@+id/edit_folder_default_icon_imageview"
android:layout_height="30dp"
android:layout_width="30dp"
android:layout_marginTop="6dp"
tools:ignore="ContentDescription" />
<ImageView
- android:id="@+id/edit_folder_web_page_favorite_icon"
+ android:id="@+id/edit_folder_web_page_favorite_icon_imageview"
android:layout_height="30dp"
android:layout_width="30dp"
android:layout_marginTop="6dp"
<attr name="bookmarksSpinnerHeaderTextColor" format="reference" />
<attr name="bookmarksSpinnerTextColorSelector" format="reference" />
<attr name="bookmarksSpinnerBackground" format="reference" />
+ <attr name="editBookmarkSpinnerTextColorSelector" format="reference" />
<attr name="redText" format="reference" />
<attr name="navigationHeaderBackground" format="reference" />
<string name="bookmarks_database_view">Bookmarks Database View</string>
<string name="all_folders">All Folders</string>
<string name="home_folder">Home Folder</string>
+ <string name="database_id">Database ID:</string>
+ <string name="folder">Folder:</string>
+ <string name="parent_folder">Parent folder:</string>
+ <string name="display_order">Display order:</string>
<!-- Domains. -->
<string name="domains">Domains</string>
<item name="bookmarksSpinnerHeaderTextColor">@color/white</item>
<item name="bookmarksSpinnerTextColorSelector">@color/bookmarks_spinner_color_selector_light</item>
<item name="bookmarksSpinnerBackground">@color/blue_750</item>
+ <item name="editBookmarkSpinnerTextColorSelector">@color/edit_bookmark_spinner_color_selector_light</item>
<item name="listSelectorDrawable">@drawable/list_selector_light</item>
<item name="aboutTitle">@color/blue_900</item>
<item name="aboutText">@color/blue_700</item>
<item name="bookmarksSpinnerHeaderTextColor">@color/gray_300</item>
<item name="bookmarksSpinnerTextColorSelector">@color/bookmarks_spinner_color_selector_dark</item>
<item name="bookmarksSpinnerBackground">@color/blue_830</item>
+ <item name="editBookmarkSpinnerTextColorSelector">@color/edit_bookmark_spinner_color_selector_dark</item>
<item name="aboutTitle">@color/blue_600</item>
<item name="aboutText">@color/blue_400</item>
<item name="aboutBackground">@color/gray_850</item>
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
+ classpath 'com.android.tools.build:gradle:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
allprojects {
repositories {
jcenter()
- maven {
- url "https://maven.google.com"
- }
+ google()
}
}
-#Thu Mar 02 15:10:19 MST 2017
+#Wed Nov 01 01:37:59 MST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip