[WIP]
Bug 1232439 (972193) - Add "Choose Folder" bookmark edit dialog option.
MozReview-Commit-ID: L152bg4QH4Q
--- a/mobile/android/base/java/org/mozilla/gecko/BookmarkToolbarDialog.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BookmarkToolbarDialog.java
@@ -7,29 +7,34 @@ package org.mozilla.gecko;
import org.mozilla.gecko.db.BrowserContract;
import android.app.Activity;
import android.content.Intent;
import android.support.annotation.MenuRes;
import android.support.annotation.StringRes;
import android.support.design.widget.TextInputLayout;
+import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MenuItem;
import android.view.View;
public abstract class BookmarkToolbarDialog extends DialogFragment
implements FolderTreeView.FolderSelectedListener {
protected static final String ARG_FOLDER_ID = "folder_id";
protected static final String ARG_FOLDER_NAME = "folder_name";
+ // setTargetFragment requires an int code, which we don't actually need since a given dialog is
+ // only ever the target of at most one other dialog.
+ protected static final int TARGET_FRAGMENT_CODE_UNUSED = -1;
+
// The fake Dekstop folder isn't selectable, so use its ID as our invalid folder ID value (the
// desktop folder doesn't actually exist in the database, so attempting to use it in the
// database as a parent folder ID will crash on a failed foreign key constraint rather than
// leading to invalid parent data).
protected static int INVALID_FOLDER_ID = BrowserContract.Bookmarks.FAKE_DESKTOP_FOLDER_ID;
protected abstract @StringRes int toolbarTitle();
@@ -85,16 +90,23 @@ public abstract class BookmarkToolbarDia
// Send on the selected folder data to this fragment's target fragment.
final Intent intent = new Intent();
intent.putExtra(ARG_FOLDER_NAME, folderName);
intent.putExtra(ARG_FOLDER_ID, folderId);
targetFragment.onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
getFragmentManager().popBackStack();
}
+ protected void setDialogFolderArguments(int folderId, String folderName) {
+ final Bundle args = new Bundle();
+ args.putInt(ARG_FOLDER_ID, folderId);
+ args.putString(ARG_FOLDER_NAME, folderName);
+ setArguments(args);
+ }
+
protected static class EmptyTextWatcher implements TextWatcher {
private final TextInputLayout textInputLayout;
private final String errorText;
EmptyTextWatcher(TextInputLayout textInputLayout, String errorText) {
this.textInputLayout = textInputLayout;
this.errorText = errorText;
}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/ChooseBookmarkFolderDialog.java
@@ -0,0 +1,61 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ChooseBookmarkFolderDialog extends BookmarkFolderTreeDialog {
+ private int currentFolderId;
+ private String currentFolderName;
+
+ public static ChooseBookmarkFolderDialog newInstance(int currentFolderId, String currentFolderName) {
+ final ChooseBookmarkFolderDialog dialog = new ChooseBookmarkFolderDialog();
+ dialog.setDialogFolderArguments(currentFolderId, currentFolderName);
+ return dialog;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Bundle args = getArguments();
+ currentFolderId = args.getInt(ARG_FOLDER_ID);
+ currentFolderName = args.getString(ARG_FOLDER_NAME);
+ }
+
+ @Override
+ protected @StringRes int toolbarTitle() {
+ return R.string.bookmark_dialog_choose_folder;
+ }
+
+ @Override
+ protected int currentFolderId() {
+ return currentFolderId;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
+ final View editView = inflater.inflate(R.layout.choose_bookmark_folder, container, false);
+
+ setupToolbar(editView, null);
+ setupFolderTree(editView, true);
+
+ editView.findViewById(R.id.add_new_folder).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO: Create new fragment to add a new folder.
+ }
+ });
+
+ return editView;
+ }
+}
--- a/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java
+++ b/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java
@@ -5,18 +5,20 @@
package org.mozilla.gecko;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.UIAsyncTask;
+import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputLayout;
@@ -33,16 +35,18 @@ import android.widget.EditText;
*/
public class EditBookmarkDialog extends BookmarkToolbarDialog {
private Bookmark mBookmark;
private ViewGroup rootView;
private EditText nameText;
private EditText locationText;
private EditText keywordText;
+ private EditText folderText;
+
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mBookmark.saveToBundle(outState);
}
@Override
@@ -165,41 +169,73 @@ public class EditBookmarkDialog extends
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
final View editView = inflater.inflate(R.layout.bookmark_edit, container, false);
rootView = container;
nameText = ((EditText) editView.findViewById(R.id.edit_bookmark_name));
locationText = ((EditText) editView.findViewById(R.id.edit_bookmark_location));
keywordText = ((EditText) editView.findViewById(R.id.edit_bookmark_keyword));
- final EditText folderText = ((EditText) editView.findViewById(R.id.edit_bookmark_folder));
+ folderText = ((EditText) editView.findViewById(R.id.edit_bookmark_folder));
setupToolbar(editView, R.menu.bookmarks_dialog_menu_save_and_remove);
// Insert text BEFORE the cursor - when the user opens the dialog we want the cursor to be at the end of the name
// field. We've already requested focus in the layout file using <requestFocus/>, however using setText
// results in the cursor staying at the start of the text, whereas insert(0,...) results in the text being
// inserted in front of the cursor.
nameText.getText().insert(0, mBookmark.title);
locationText.setText(mBookmark.url);
keywordText.setText(mBookmark.keyword);
+ // The folder text is updated in onResume (see the note there).
folderText.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- // TODO: launch new folder chooser dialog.
+ final ChooseBookmarkFolderDialog chooseFolderDialog =
+ ChooseBookmarkFolderDialog.newInstance(mBookmark.folderId, mBookmark.folderName);
+ chooseFolderDialog.setTargetFragment(EditBookmarkDialog.this, TARGET_FRAGMENT_CODE_UNUSED);
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(android.R.id.content, chooseFolderDialog)
+ .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+ .addToBackStack(null)
+ .commit();
}
});
final TextInputLayout locationTextLayout = (TextInputLayout) editView.findViewById(R.id.edit_bookmark_location_layout);
final String emptyURLErrorText = getString(R.string.bookmark_edit_location_empty_error);
locationText.addTextChangedListener(new EmptyTextWatcher(locationTextLayout, emptyURLErrorText));
return editView;
}
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // Updating the folder text after a new folder has been chosen doesn't work in
+ // onActivityResult or onCreateView, so we just always set it here.
+ folderText.setText(mBookmark.folderName);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode != Activity.RESULT_OK || data == null) {
+ return;
+ }
+
+ final String folderName = data.getStringExtra(ARG_FOLDER_NAME);
+ final int folderId = data.getIntExtra(ARG_FOLDER_ID, INVALID_FOLDER_ID);
+ if (folderName != null && folderId != INVALID_FOLDER_ID) {
+ mBookmark.folderId = folderId;
+ mBookmark.folderName = folderName;
+ // Updating the EditText folder name doesn't work here; we do it in onResume instead.
+ }
+ }
+
/**
* Show the Edit bookmark dialog for a particular url. If the url is bookmarked multiple times
* this will just edit the first instance it finds.
*
* @param url The url of the bookmark to edit. The dialog will look up other information like the id,
* current title, or keywords associated with this url. If the url isn't bookmarked, the
* dialog will fail silently. If the url is bookmarked multiple times, this will only show
* information about the first it finds.
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -85,16 +85,18 @@
and is labeled by this String. -->
<!ENTITY screenshot_folder_label_in_bookmarks "Screenshots">
<!ENTITY readinglist_smartfolder_label_in_bookmarks "Reading List">
<!-- Localization note (bookmark_dialog_save_and_return): Alternate text for accessibility; not UI
visible. Save the data input in the current dialog and return to the previous dialog. -->
<!ENTITY bookmark_dialog_save_and_return "Save and return">
<!ENTITY bookmark_dialog_folder "Folder">
+<!ENTITY bookmark_dialog_choose_folder "Choose folder">
+<!ENTITY bookmark_dialog_new_folder "New folder...">
<!ENTITY bookmark_edit_title "Edit Bookmark">
<!ENTITY bookmark_edit_name "Name">
<!ENTITY bookmark_edit_location "Location">
<!ENTITY bookmark_edit_keyword "Keyword">
<!ENTITY bookmark_edit_location_empty_error "Bookmark location must contain a URL">
<!-- Localization note (bookmark_folder_items): The variable is replaced by the number of items
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -342,16 +342,17 @@ gbjar.sources += ['java/org/mozilla/geck
'animation/Rotate3DAnimation.java',
'animation/ViewHelper.java',
'ANRReporter.java',
'BookmarkFolderTreeDialog.java',
'BookmarkToolbarDialog.java',
'BootReceiver.java',
'BrowserApp.java',
'BrowserLocaleManager.java',
+ 'ChooseBookmarkFolderDialog.java',
'cleanup/FileCleanupController.java',
'cleanup/FileCleanupService.java',
'CustomEditText.java',
'customtabs/CustomTabsActivity.java',
'customtabs/GeckoCustomTabsService.java',
'DataReportingNotification.java',
'db/AbstractPerProfileDatabaseProvider.java',
'db/AbstractTransactionalProvider.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/choose_bookmark_folder.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/white"
+ android:theme="@style/GeckoAlertDialog">
+
+ <include layout="@layout/bookmark_dialog_toolbar"/>
+
+ <android.support.v4.widget.NestedScrollView android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <Button android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="24dp"
+ android:paddingTop="24dp"
+ android:paddingRight="24dp"
+ android:paddingBottom="12dp"
+ android:id="@+id/add_new_folder"
+ android:drawableLeft="@drawable/tab_new"
+ android:drawableStart="@drawable/tab_new"
+ android:drawablePadding="8dp"
+ android:textAllCaps="false"
+ android:text="@string/bookmark_dialog_new_folder"
+ android:gravity="start|center_vertical"
+ style="?android:attr/borderlessButtonStyle"/>
+
+ <include layout="@layout/folder_tree_view"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"/>
+
+ </LinearLayout>
+
+ </android.support.v4.widget.NestedScrollView>
+
+</LinearLayout>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -99,16 +99,18 @@
<string name="bookmark_options">&bookmark_options;</string>
<string name="bookmarks_selected_folder">&bookmarks_selected_folder;</string>
<string name="screenshot_added_to_bookmarks">&screenshot_added_to_bookmarks;</string>
<string name="screenshot_folder_label_in_bookmarks">&screenshot_folder_label_in_bookmarks;</string>
<string name="readinglist_smartfolder_label_in_bookmarks">&readinglist_smartfolder_label_in_bookmarks;</string>
<string name="bookmark_dialog_save_and_return">&bookmark_dialog_save_and_return;</string>
<string name="bookmark_dialog_folder">&bookmark_dialog_folder;</string>
+ <string name="bookmark_dialog_choose_folder">&bookmark_dialog_choose_folder;</string>
+ <string name="bookmark_dialog_new_folder">&bookmark_dialog_new_folder;</string>
<string name="bookmark_edit_title">&bookmark_edit_title;</string>
<string name="bookmark_edit_name">&bookmark_edit_name;</string>
<string name="bookmark_edit_location">&bookmark_edit_location;</string>
<string name="bookmark_edit_keyword">&bookmark_edit_keyword;</string>
<string name="bookmark_edit_location_empty_error">&bookmark_edit_location_empty_error;</string>
<string name="bookmark_folder_items">&bookmark_folder_items;</string>