Bug 1464580 - WIP draft
authorTim Nguyen <ntim.bugs@gmail.com>
Sat, 26 May 2018 15:22:57 +0200
changeset 800260 1a896267e3b44991069e972387464f2a8d930893
parent 800252 3eccd139667d491ca259e8ff96f740ecfa36a781
push id111302
push userbmo:ntim.bugs@gmail.com
push dateSat, 26 May 2018 13:23:39 +0000
bugs1464580
milestone62.0a1
Bug 1464580 - WIP MozReview-Commit-ID: 5GcYiXD4KUK
browser/base/content/browser-places.js
browser/base/content/browser.css
browser/base/content/browser.xul
browser/components/customizableui/PanelMultiView.jsm
browser/components/places/content/editBookmark.js
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -226,24 +226,23 @@ var StarUI = {
   },
 
   async _doShowEditBookmarkPanel(aNode, aAnchorElement, aPosition, aUrl) {
     if (this.panel.state != "closed")
       return;
 
     this._blockCommands(); // un-done in the popuphidden handler
 
-    this._element("editBookmarkPanelTitle").value =
-      this._isNewBookmark ?
-        gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle") :
-        gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle");
+    let title = this._isNewBookmark ?
+      gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle") :
+      gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle");
+    this._element("editBookmarkMainView").setAttribute("title", title);
 
     // No description; show the Done, Remove;
     this._element("editBookmarkPanelBottomButtons").hidden = false;
-    this._element("editBookmarkPanelContent").hidden = false;
 
     this._itemGuids = [];
     await PlacesUtils.bookmarks.fetch({url: aUrl},
       bookmark => this._itemGuids.push(bookmark.guid));
 
     let removeButton = this._element("editBookmarkPanelRemoveButton");
     if (this._isNewBookmark) {
       removeButton.label = gNavigatorBundle.getString("editBookmarkPanel.cancel.label");
@@ -282,17 +281,17 @@ var StarUI = {
         fn();
       }, {"capture": true, "once": true});
     };
     gEditItemOverlay.initPanel({ node: aNode,
                                  onPanelReady,
                                  hiddenRows: ["description", "location",
                                               "loadInSidebar", "keyword"],
                                  focusedElement: "preferred"});
-    this.panel.openPopup(aAnchorElement, aPosition);
+    await PanelMultiView.openPopup(this.panel, aAnchorElement, aPosition);
   },
 
   panelShown:
   function SU_panelShown(aEvent) {
     if (aEvent.target == this.panel) {
       if (this._element("editBookmarkPanelContent").hidden) {
         // Note this isn't actually used anymore, we should remove this
         // once we decide not to bring back the page bookmarked notification
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -100,17 +100,17 @@ panelview {
   -moz-box-orient: vertical;
 }
 
 panelview:not([visible]) {
   visibility: collapse;
 }
 
 /* Hide the header when a subview is reused as a main view. */
-panelview[mainview] > .panel-header {
+panelview:not([forceShowTitle])[mainview] > .panel-header {
   display: none;
 }
 
 .panel-viewcontainer {
   overflow: hidden;
 }
 
 .panel-viewcontainer[panelopen] {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -217,41 +217,144 @@
     <panel id="editBookmarkPanel"
            type="arrow"
            orient="vertical"
            ignorekeys="true"
            hidden="true"
            tabspecific="true"
            onpopupshown="StarUI.panelShown(event);"
            aria-labelledby="editBookmarkPanelTitle">
-      <box class="panel-header">
-        <label id="editBookmarkPanelTitle"/>
-      </box>
-#include ../../components/places/content/editBookmarkPanel.inc.xul
-      <hbox id="editBookmarkPanelBottomButtons" pack="end">
+      <panelmultiview id="editBookmarkMultiview"
+                      mainViewId="editBookmarkMainView"
+                      viewCacheId="appMenu-viewCache">
+        <panelview id="editBookmarkMainView" class="PanelUI-subView" forceShowTitle="true">
+          <vbox id="editBookmarkPanelRows">
+            <vbox id="editBMPanel_nameRow">
+              <label value="&editBookmarkOverlay.name.label;"
+                     accesskey="&editBookmarkOverlay.name.accesskey;"
+                     control="editBMPanel_namePicker"/>
+              <textbox id="editBMPanel_namePicker"
+                       onchange="gEditItemOverlay.onNamePickerChange().catch(Components.utils.reportError);"/>
+            </vbox>
+
+            <vbox id="editBMPanel_locationRow"
+                  collapsed="true">
+              <label value="&editBookmarkOverlay.location.label;"
+                     accesskey="&editBookmarkOverlay.location.accesskey;"
+                     control="editBMPanel_locationField"/>
+              <textbox id="editBMPanel_locationField"
+                       class="uri-element"
+                       onchange="gEditItemOverlay.onLocationFieldChange();"/>
+            </vbox>
+            <vbox id="editBMPanel_folderRow">
+              <label value="&editBookmarkOverlay.folder.label;"
+                     control="editBMPanel_folderMenuList"/>
+              <hbox flex="1" align="center">
+                <menulist id="editBMPanel_folderMenuList"
+                          class="folder-icon"
+                          flex="1"
+                          oncommand="gEditItemOverlay.onFolderMenuListCommand(event).catch(Components.utils.reportError);">
+                  <menupopup>
+                    <!-- Static item for special folders -->
+                    <menuitem id="editBMPanel_toolbarFolderItem"
+                              class="menuitem-iconic folder-icon"/>
+                    <menuitem id="editBMPanel_bmRootItem"
+                              class="menuitem-iconic folder-icon"/>
+                    <menuitem id="editBMPanel_unfiledRootItem"
+                              class="menuitem-iconic folder-icon"/>
+                    <menuseparator id="editBMPanel_chooseFolderSeparator"/>
+                    <menuitem id="editBMPanel_chooseFolderMenuItem"
+                              label="&editBookmarkOverlay.choose.label;"
+                              class="menuitem-iconic folder-icon"/>
+                    <menuseparator id="editBMPanel_foldersSeparator" hidden="true"/>
+                  </menupopup>
+                </menulist>
+                <button id="editBMPanel_foldersExpander"
+                        class="expander-down"
+                        tooltiptext="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
+                        tooltiptextdown="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
+                        tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
+                        oncommand="document.getElementById('editBookmarkMultiview').showSubView('editBMPanel_folderTreeRow')"/>
+              </hbox>
+            </vbox>
+            <vbox id="editBMPanel_tagsRow">
+              <label value="&editBookmarkOverlay.tags.label;"
+                     accesskey="&editBookmarkOverlay.tags.accesskey;"
+                     control="editBMPanel_tagsField"/>
+              <hbox flex="1" align="center">
+                <textbox id="editBMPanel_tagsField"
+                         type="autocomplete"
+                         flex="1"
+                         autocompletesearch="places-tag-autocomplete"
+                         autocompletepopup="PopupAutoComplete"
+                         completedefaultindex="true"
+                         tabscrolling="true"
+                         placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"
+                         onchange="gEditItemOverlay.onTagsFieldChange();"/>
+                <button id="editBMPanel_tagsSelectorExpander"
+                        class="expander-down"
+                        tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
+                        tooltiptextdown="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
+                        tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
+                        oncommand="document.getElementById('editBookmarkMultiview').showSubView('editBMPanel_tagsSelectorRow')"/>
+              </hbox>
+            </vbox>
+          </vbox>
+
+          <hbox id="editBookmarkPanelBottomButtons" pack="end">
 #ifndef XP_UNIX
-        <button id="editBookmarkPanelDoneButton"
-                class="editBookmarkPanelBottomButton"
-                label="&editBookmark.done.label;"
-                default="true"
-                oncommand="StarUI.panel.hidePopup();"/>
-        <button id="editBookmarkPanelRemoveButton"
-                class="editBookmarkPanelBottomButton"
-                oncommand="StarUI.removeBookmarkButtonCommand();"/>
+            <button id="editBookmarkPanelDoneButton"
+                    class="editBookmarkPanelBottomButton"
+                    label="&editBookmark.done.label;"
+                    default="true"
+                    oncommand="StarUI.panel.hidePopup();"/>
+            <button id="editBookmarkPanelRemoveButton"
+                    class="editBookmarkPanelBottomButton"
+                    oncommand="StarUI.removeBookmarkButtonCommand();"/>
 #else
-        <button id="editBookmarkPanelRemoveButton"
-                class="editBookmarkPanelBottomButton"
-                oncommand="StarUI.removeBookmarkButtonCommand();"/>
-        <button id="editBookmarkPanelDoneButton"
-                class="editBookmarkPanelBottomButton"
-                label="&editBookmark.done.label;"
-                default="true"
-                oncommand="StarUI.panel.hidePopup();"/>
+            <button id="editBookmarkPanelRemoveButton"
+                    class="editBookmarkPanelBottomButton"
+                    oncommand="StarUI.removeBookmarkButtonCommand();"/>
+            <button id="editBookmarkPanelDoneButton"
+                    class="editBookmarkPanelBottomButton"
+                    label="&editBookmark.done.label;"
+                    default="true"
+                    oncommand="StarUI.panel.hidePopup();"/>
 #endif
-      </hbox>
+          </hbox>
+        </panelview>
+        <panelview id="editBMPanel_tagsSelectorRow" title="&editBookmarkOverlay.tags.label;">
+          <listbox id="editBMPanel_tagsSelector"
+                   height="150"/>
+        </panelview>
+        <panelview id="editBMPanel_folderTreeRow" title="&editBookmarkOverlay.folder.label;">
+          <tree id="editBMPanel_folderTree"
+                flex="1"
+                class="placesTree"
+                type="places"
+                height="150"
+                minheight="150"
+                editable="true"
+                onselect="gEditItemOverlay.onFolderTreeSelect();"
+                disableUserActions="true"
+                hidecolumnpicker="true">
+            <treecols>
+              <treecol anonid="title" flex="1" primary="true" hideheader="true"/>
+            </treecols>
+            <treechildren flex="1"/>
+          </tree>
+
+          <hbox id="editBMPanel_newFolderBox">
+            <button label="&editBookmarkOverlay.newFolderButton.label;"
+                    id="editBMPanel_newFolderButton"
+                    accesskey="&editBookmarkOverlay.newFolderButton.accesskey;"
+                    oncommand="gEditItemOverlay.newFolder().catch(Components.utils.reportError);"/>
+          </hbox>
+        </panelview>
+      </panelmultiview>
     </panel>
 
     <!-- UI tour experience -->
     <panel id="UITourTooltip"
            type="arrow"
            hidden="true"
            noautofocus="true"
            noautohide="true"
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -704,18 +704,19 @@ var PanelMultiView = class extends Assoc
 
     this._activateView(nextPanelView);
   }
 
   /**
    * Prepares the main view before showing the panel.
    */
   async _showMainView() {
-    let nextPanelView = PanelView.forNode(this.document.getElementById(
-      this.node.getAttribute("mainViewId")));
+    let viewNode = this.document.getElementById(
+      this.node.getAttribute("mainViewId"));
+    let nextPanelView = PanelView.forNode(viewNode);
 
     // If the view is already open in another panel, close the panel first.
     let oldPanelMultiViewNode = nextPanelView.node.panelMultiView;
     if (oldPanelMultiViewNode) {
       PanelMultiView.forNode(oldPanelMultiViewNode).hidePopup();
       // Wait for a layout flush after hiding the popup, otherwise the view may
       // not be displayed correctly for some time after the new panel is opened.
       // This is filed as bug 1441015.
@@ -724,17 +725,22 @@ var PanelMultiView = class extends Assoc
 
     if (!(await this._openView(nextPanelView))) {
       return false;
     }
 
     // The main view of a panel can be a subview in another one. Make sure to
     // reset all the properties that may be set on a subview.
     nextPanelView.mainview = true;
-    nextPanelView.headerText = "";
+    console.log(viewNode, viewNode.getAttribute("title"), viewNode.hasAttribute("forceShowTitle"))
+    if (viewNode.hasAttribute("forceShowTitle")) {
+      nextPanelView.headerText = viewNode.getAttribute("title");
+    } else {
+      nextPanelView.headerText = "";
+    }
     nextPanelView.minMaxWidth = 0;
 
     // Ensure the view will be visible once the panel is opened.
     nextPanelView.visible = true;
     nextPanelView.descriptionHeightWorkaround();
 
     return true;
   }
@@ -1153,16 +1159,20 @@ var PanelView = class extends Associated
 
   /**
    * Indicates whether the view is open in the specified PanelMultiView object.
    */
   isOpenIn(panelMultiView) {
     return this.node.panelMultiView == panelMultiView.node;
   }
 
+  get mainview() {
+    return this.node.hasAttribute("mainview");
+  }
+
   /**
    * The "mainview" attribute is set before the panel is opened when this view
    * is displayed as the main view, and is removed before the <panelview> is
    * displayed as a subview. The same view element can be displayed as a main
    * view and as a subview at different times.
    */
   set mainview(value) {
     if (value) {
@@ -1217,33 +1227,36 @@ var PanelView = class extends Associated
     // The header doesn't exist, only create it if needed.
     if (!value) {
       return;
     }
 
     header = this.document.createElement("box");
     header.classList.add("panel-header");
 
-    let backButton = this.document.createElement("toolbarbutton");
-    backButton.className =
-      "subviewbutton subviewbutton-iconic subviewbutton-back";
-    backButton.setAttribute("closemenu", "none");
-    backButton.setAttribute("tabindex", "0");
-    backButton.setAttribute("aria-label",
-      gBundle.GetStringFromName("panel.back"));
-    backButton.addEventListener("command", () => {
-      // The panelmultiview element may change if the view is reused.
-      this.node.panelMultiView.goBack();
-      backButton.blur();
-    });
+    if (!this.mainview) {
+      let backButton = this.document.createElement("toolbarbutton");
+      backButton.className =
+        "subviewbutton subviewbutton-iconic subviewbutton-back";
+      backButton.setAttribute("closemenu", "none");
+      backButton.setAttribute("tabindex", "0");
+      backButton.setAttribute("aria-label",
+        gBundle.GetStringFromName("panel.back"));
+      backButton.addEventListener("command", () => {
+        // The panelmultiview element may change if the view is reused.
+        this.node.panelMultiView.goBack();
+        backButton.blur();
+      });
+      header.append(backButton);
+    }
 
     let label = this.document.createElement("label");
     label.setAttribute("value", value);
 
-    header.append(backButton, label);
+    header.append(label);
     this.node.prepend(header);
   }
 
   /**
    * Also make sure that the correct method is called on CustomizableWidget.
    */
   dispatchCustomEvent(...args) {
     CustomizableUI.ensureSubviewListeners(this.node);
--- a/browser/components/places/content/editBookmark.js
+++ b/browser/components/places/content/editBookmark.js
@@ -224,17 +224,17 @@ var gEditItemOverlay = {
 
     let showOrCollapse =
       (rowId, isAppropriateForInput, nameInHiddenRows = null) => {
         let visible = isAppropriateForInput;
         if (visible && "hiddenRows" in aInfo && nameInHiddenRows)
           visible &= !aInfo.hiddenRows.includes(nameInHiddenRows);
         if (visible)
           visibleRows.add(rowId);
-        return !(this._element(rowId).collapsed = !visible);
+        return this._element(rowId) && !(this._element(rowId).collapsed = !visible);
       };
 
     if (showOrCollapse("nameRow", !bulkTagging, "name")) {
       this._initNamePicker();
       this._namePicker.readOnly = this.readOnly;
     }
 
     // In some cases we want to hide the location field, since it's not