[WIP] Bug 1232439 (972193) - Add "Create folder" bookmark edit dialog option. draft
authorTom Klein <twointofive@gmail.com>
Fri, 23 Dec 2016 17:24:18 -0600
changeset 453961 44fb5136dd8b306c7d083006ca722a0964a2005c
parent 453960 3fecda8a0f25d06e05d4d74032259d815867a6fb
child 453962 c72d800988a0d5042a53f968f22f11358d0ebadc
push id39777
push userbmo:twointofive@gmail.com
push dateMon, 26 Dec 2016 21:30:36 +0000
bugs1232439, 972193
milestone53.0a1
[WIP] Bug 1232439 (972193) - Add "Create folder" bookmark edit dialog option. MozReview-Commit-ID: 1Rrx4UgBUM3
mobile/android/base/java/org/mozilla/gecko/ChooseBookmarkFolderDialog.java
mobile/android/base/java/org/mozilla/gecko/CreateBookmarkFolderDialog.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/moz.build
mobile/android/base/resources/layout/create_bookmark_folder.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/java/org/mozilla/gecko/ChooseBookmarkFolderDialog.java
+++ b/mobile/android/base/java/org/mozilla/gecko/ChooseBookmarkFolderDialog.java
@@ -1,18 +1,21 @@
 /* -*- 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.app.Activity;
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
+import android.support.v4.app.FragmentTransaction;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
 public class ChooseBookmarkFolderDialog extends BookmarkFolderTreeDialog {
     private int currentFolderId;
     private String currentFolderName;
 
@@ -47,15 +50,33 @@ public class ChooseBookmarkFolderDialog 
         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.
+                final CreateBookmarkFolderDialog createFolderDialog = CreateBookmarkFolderDialog.newInstance(currentFolderId, currentFolderName);
+                createFolderDialog.setTargetFragment(ChooseBookmarkFolderDialog.this, TARGET_FRAGMENT_CODE_UNUSED);
+                final FragmentTransaction transaction = getFragmentManager().beginTransaction();
+                transaction.replace(android.R.id.content, createFolderDialog)
+                        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+                        .addToBackStack(null)
+                        .commit();
             }
         });
 
         return editView;
     }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (resultCode != Activity.RESULT_OK || data == null) {
+            return;
+        }
+
+        // The user just created a new folder - send it straight on to the Edit panel.
+        final String folderName = data.getStringExtra(ARG_FOLDER_NAME);
+        final int folderId = data.getIntExtra(ARG_FOLDER_ID, INVALID_FOLDER_ID);
+        folderSelected(folderName, folderId);
+    }
 }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/CreateBookmarkFolderDialog.java
@@ -0,0 +1,116 @@
+/* -*- 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 org.mozilla.gecko.db.BrowserDB;
+import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.util.UIAsyncTask;
+
+import android.content.ContentResolver;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.design.widget.Snackbar;
+import android.support.design.widget.TextInputLayout;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+public class CreateBookmarkFolderDialog extends BookmarkToolbarDialog {
+    // The id and name of the folder in which the new folder will be created.
+    private int parentFolderId;
+    private String parentFolderName;
+
+    private ViewGroup rootView;
+    private EditText newFolderNameEdit;
+
+    public static CreateBookmarkFolderDialog newInstance(int currentFolderId, String currentFolderName) {
+        final CreateBookmarkFolderDialog dialog = new CreateBookmarkFolderDialog();
+        dialog.setDialogFolderArguments(currentFolderId, currentFolderName);
+        return dialog;
+    }
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Bundle args = getArguments();
+        parentFolderId = args.getInt(ARG_FOLDER_ID);
+        parentFolderName = args.getString(ARG_FOLDER_NAME);
+    }
+
+    @Override
+    protected @StringRes int toolbarTitle() {
+        return R.string.bookmark_dialog_add_folder_title;
+    }
+
+    private void toolbarSaveClicked() {
+        final String newFolderName = newFolderNameEdit.getText().toString().trim();
+        if (newFolderName.isEmpty()) {
+            newFolderNameEdit.requestFocus();
+            // The name edit starts out blank, and the text watcher doesn't run until text is
+            // entered, so just in case that's the state we're in, enter some empty text to trigger
+            // the text watcher error.
+            newFolderNameEdit.setText("");
+            return;
+        }
+
+        final BrowserDB db = BrowserDB.from(getContext());
+        (new UIAsyncTask.WithoutParams<Long>(ThreadUtils.getBackgroundHandler()) {
+            @Override
+            public Long doInBackground() {
+                final ContentResolver cr = getContext().getContentResolver();
+                db.addBookmarkFolder(cr, newFolderName, parentFolderId);
+                return db.getIDForFolder(cr, newFolderName, parentFolderId);
+            }
+
+            @Override
+            public void onPostExecute(Long newFolderId) {
+                if (newFolderId == null) {
+                    return;
+                }
+
+                Snackbar.make(rootView, R.string.bookmark_folder_created, Snackbar.LENGTH_SHORT).show();
+                folderSelected(newFolderName, newFolderId.intValue());
+            }
+        }).execute();
+    }
+
+    @Override
+    protected boolean toolbarMenuItemClicked(int menuItemId) {
+        if (menuItemId == R.id.save) {
+            toolbarSaveClicked();
+            return true;
+        }
+        return false;
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
+        final View folderCreateView = inflater.inflate(R.layout.create_bookmark_folder, container, false);
+        rootView = container;
+
+        setupToolbar(folderCreateView, R.menu.bookmarks_dialog_menu_save);
+
+        final TextInputLayout newFolderNameLayout = (TextInputLayout) folderCreateView.findViewById(R.id.new_folder_name_layout);
+        newFolderNameEdit = (EditText) folderCreateView.findViewById(R.id.new_folder_name);
+        final String emptyFolderNameErrorText = getString(R.string.bookmark_add_folder_name_empty_error);
+        newFolderNameEdit.addTextChangedListener(new EmptyTextWatcher(newFolderNameLayout, emptyFolderNameErrorText));
+
+        final EditText selectParentFolderEdit = (EditText) folderCreateView.findViewById(R.id.select_parent_folder);
+        selectParentFolderEdit.setText(parentFolderName);
+        selectParentFolderEdit.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // TODO: Create new fragment to select the parent folder of the new folder.
+            }
+        });
+
+        return folderCreateView;
+    }
+}
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -69,16 +69,17 @@
 <!ENTITY bookmark_remove "Remove bookmark">
 <!ENTITY bookmark_added "Bookmark added">
 <!-- Localization note (bookmark_already_added) : This string is
      used as a label in a toast. It is the verb "to bookmark", not
      the noun "a bookmark". -->
 <!ENTITY bookmark_already_added "Already bookmarked">
 <!ENTITY bookmark_removed "Bookmark removed">
 <!ENTITY bookmark_updated "Bookmark updated">
+<!ENTITY bookmark_folder_created "Folder created">
 <!ENTITY bookmark_options "Options">
 <!-- Localization note (selected_folder): Alternate text for accessibility; not UI visible.
      Indicates which Bookmarks folder is currently selected (selected is an adjective and not a verb
      here). -->
 <!ENTITY bookmarks_selected_folder "Selected folder">
 <!ENTITY screenshot_added_to_bookmarks "Screenshot added to bookmarks">
 <!-- Localization note (screenshot_folder_label_in_bookmarks): We save links to screenshots
      the user takes. The folder we store these links in is located in the bookmarks list
@@ -94,16 +95,21 @@
 <!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">
 
+<!ENTITY bookmark_dialog_add_folder_title "Add folder">
+<!ENTITY bookmark_add_folder_name_empty_error "Folder name is required">
+<!ENTITY bookmark_add_folder_title "Title">
+<!ENTITY bookmark_add_folder_parent_folder "Parent folder">
+
 <!-- Localization note (bookmark_folder_items): The variable is replaced by the number of items
      in the folder. -->
 <!ENTITY bookmark_folder_items "&formatD; items">
 <!ENTITY bookmark_folder_one_item "1 item">
 
 <!ENTITY reader_saved_offline "Saved offline">
 <!-- Localization note (reader_switch_to_bookmarks) : This
      string is used as an action in a snackbar - it lets you
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -345,16 +345,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'BookmarkFolderTreeDialog.java',
     'BookmarkToolbarDialog.java',
     'BootReceiver.java',
     'BrowserApp.java',
     'BrowserLocaleManager.java',
     'ChooseBookmarkFolderDialog.java',
     'cleanup/FileCleanupController.java',
     'cleanup/FileCleanupService.java',
+    'CreateBookmarkFolderDialog.java',
     'CustomEditText.java',
     'customtabs/CustomTabsActivity.java',
     'customtabs/GeckoCustomTabsService.java',
     'DataReportingNotification.java',
     'db/AbstractPerProfileDatabaseProvider.java',
     'db/AbstractTransactionalProvider.java',
     'db/BaseTable.java',
     'db/BrowserDatabaseHelper.java',
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/create_bookmark_folder.xml
@@ -0,0 +1,63 @@
+<?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"
+              xmlns:app="http://schemas.android.com/apk/res-auto"
+              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"/>
+
+    <ScrollView android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center_horizontal">
+
+        <LinearLayout android:layout_width="match_parent"
+                      android:layout_height="wrap_content"
+                      android:padding="24dp"
+                      android:orientation="vertical">
+
+            <android.support.design.widget.TextInputLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:id="@+id/new_folder_name_layout"
+                    app:hintAnimationEnabled="true">
+
+                <android.support.design.widget.TextInputEditText
+                        android:id="@+id/new_folder_name"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:maxLines="1"
+                        android:hint="@string/bookmark_add_folder_title">
+                    <requestFocus/>
+                </android.support.design.widget.TextInputEditText>
+            </android.support.design.widget.TextInputLayout>
+
+            <android.support.design.widget.TextInputLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    app:hintAnimationEnabled="true">
+
+                <!-- Use focusableInTouchMode="false" so that the text edit receives a click event
+                     the first time it's clicked - otherwise the first tap only focuses the field
+                     and you don't get a click event until the second tap. -->
+                <android.support.design.widget.TextInputEditText
+                        android:id="@+id/select_parent_folder"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:maxLines="1"
+                        android:focusableInTouchMode="false"
+                        android:hint="@string/bookmark_add_folder_parent_folder"
+                        android:editable="false"/>
+            </android.support.design.widget.TextInputLayout>
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -91,16 +91,17 @@
 
   <string name="quit">&quit;</string>
   <string name="bookmark">&bookmark;</string>
   <string name="bookmark_remove">&bookmark_remove;</string>
   <string name="bookmark_added">&bookmark_added;</string>
   <string name="bookmark_already_added">&bookmark_already_added;</string>
   <string name="bookmark_removed">&bookmark_removed;</string>
   <string name="bookmark_updated">&bookmark_updated;</string>
+  <string name="bookmark_folder_created">&bookmark_folder_created;</string>
   <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>
@@ -108,16 +109,21 @@
   <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_dialog_add_folder_title">&bookmark_dialog_add_folder_title;</string>
+  <string name="bookmark_add_folder_name_empty_error">&bookmark_add_folder_name_empty_error;</string>
+  <string name="bookmark_add_folder_title">&bookmark_add_folder_title;</string>
+  <string name="bookmark_add_folder_parent_folder">&bookmark_add_folder_parent_folder;</string>
+
   <string name="bookmark_folder_items">&bookmark_folder_items;</string>
   <string name="bookmark_folder_one_item">&bookmark_folder_one_item;</string>
 
   <string name="reader_saved_offline">&reader_saved_offline;</string>
   <string name="reader_switch_to_bookmarks">&reader_switch_to_bookmarks;</string>
 
   <string name="history_today_section">&history_today_section;</string>
   <string name="history_yesterday_section">&history_yesterday_section;</string>