Bug 1354536 - Part 3 - When the Library view is shown, populate a new 'Recent Highlights' section with at most 12 items as in about:newtab. r?Gijs
MozReview-Commit-ID: Bs1RzL0uewH
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1271,16 +1271,18 @@ pref("browser.newtabpage.columns", 5);
// directory tiles download URL
pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v3/links/fetch/%LOCALE%/%CHANNEL%");
// activates Activity Stream
pref("browser.newtabpage.activity-stream.enabled", true);
pref("browser.newtabpage.activity-stream.prerender", true);
pref("browser.newtabpage.activity-stream.aboutHome.enabled", true);
+pref("browser.library.activity-stream.enabled", true);
+
// Enable the DOM fullscreen API.
pref("full-screen-api.enabled", true);
// Startup Crash Tracking
// number of startup crashes that can occur before starting into safe mode automatically
// (this pref has no effect if more than 6 hours have passed since the last crash)
pref("toolkit.startup.max_resumed_crashes", 3);
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -500,16 +500,17 @@ toolbar:not(#TabsToolbar) > #personal-bo
#PanelUI-feeds > .feed-toolbarbutton:-moz-locale-dir(rtl) {
direction: rtl;
}
#appMenu_historyMenu > .bookmark-item,
#appMenu-library-recentlyClosedTabs > .panel-subview-body > .bookmark-item,
#appMenu-library-recentlyClosedWindows > .panel-subview-body > .bookmark-item,
+#appMenu-library-recentHighlights > .bookmark-item,
#panelMenu_bookmarksMenu > .bookmark-item {
max-width: none;
}
#main-window:-moz-lwtheme {
background-repeat: no-repeat;
background-position: top right;
}
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -716,16 +716,26 @@
label="&libraryDownloads.label;"
closemenu="none"
oncommand="DownloadsSubview.show(this);"/>
<toolbarbutton id="appMenu-library-remotetabs-button"
class="subviewbutton subviewbutton-iconic subviewbutton-nav"
label="&appMenuRemoteTabs.label;"
closemenu="none"
oncommand="PanelUI.showSubView('PanelUI-remotetabs', this)"/>
+ <toolbarseparator/>
+ <label value="&appMenuRecentHighlights.label;"
+ class="subview-subheader"/>
+ <toolbaritem id="appMenu-library-recentHighlights"
+ orient="vertical"
+ smoothscroll="false"
+ flatList="true"
+ tooltip="bhTooltip">
+ <!-- Recent Highlights will go here -->
+ </toolbaritem>
</vbox>
</panelview>
<panelview id="PanelUI-bookmarkingTools" class="PanelUI-subView">
<vbox class="panel-subview-body">
<toolbarbutton id="panelMenu_toggleBookmarksMenu"
label="&addBookmarksMenu.label;"
label-checked="&removeBookmarksMenu.label;"
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -1,16 +1,18 @@
/* 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/. */
+XPCOMUtils.defineLazyModuleGetter(this, "AppMenuNotifications",
+ "resource://gre/modules/AppMenuNotifications.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
+ "resource://gre/modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ScrollbarSampler",
"resource:///modules/ScrollbarSampler.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "AppMenuNotifications",
- "resource://gre/modules/AppMenuNotifications.jsm");
/**
* Maintains the state and dispatches events for the main menu panel.
*/
const PanelUI = {
/** Panel events that we listen for. **/
get kEvents() {
@@ -20,16 +22,17 @@ const PanelUI = {
* Used for lazily getting and memoizing elements from the document. Lazy
* getters are set in init, and memoizing happens after the first retrieval.
*/
get kElements() {
return {
mainView: "appMenu-mainView",
multiView: "appMenu-multiView",
helpView: "PanelUI-helpView",
+ libraryView: "appMenu-libraryView",
menuButton: "PanelUI-menu-button",
panel: "appMenu-popup",
notificationPanel: "appMenu-notification-popup",
addonNotificationContainer: "appMenu-addon-banners",
overflowFixedList: "widget-overflow-fixed-list",
overflowPanel: "widget-overflow",
navbar: "nav-bar",
};
@@ -70,16 +73,22 @@ const PanelUI = {
if (this.autoHideToolbarInFullScreen) {
window.addEventListener("fullscreen", this);
} else {
window.addEventListener("MozDOMFullscreen:Entered", this);
window.addEventListener("MozDOMFullscreen:Exited", this);
}
+ XPCOMUtils.defineLazyPreferenceGetter(this, "libraryRecentHighlightsEnabled",
+ "browser.library.activity-stream.enabled", false, (pref, previousValue, newValue) => {
+ if (!newValue)
+ this.clearLibraryRecentHighlights();
+ });
+
window.addEventListener("activate", this);
window.matchMedia("(-moz-overlay-scrollbars)").addListener(this._overlayScrollListenerBoundFn);
CustomizableUI.addListener(this);
for (let event of this.kEvents) {
this.notificationPanel.addEventListener(event, this);
}
@@ -145,16 +154,17 @@ const PanelUI = {
window.removeEventListener("MozDOMFullscreen:Exited", this);
window.removeEventListener("fullscreen", this);
window.removeEventListener("activate", this);
this.menuButton.removeEventListener("mousedown", this);
this.menuButton.removeEventListener("keypress", this);
window.matchMedia("(-moz-overlay-scrollbars)").removeListener(this._overlayScrollListenerBoundFn);
CustomizableUI.removeListener(this);
this._overlayScrollListenerBoundFn = null;
+ this.libraryView.removeEventListener("ViewShowing", this);
},
/**
* Customize mode extracts the mainView and puts it somewhere else while the
* user customizes. Upon completion, this function can be called to put the
* panel back to where it belongs in normal browsing mode.
*
* @param aMainView
@@ -288,16 +298,21 @@ const PanelUI = {
this.toggle(aEvent);
break;
case "MozDOMFullscreen:Entered":
case "MozDOMFullscreen:Exited":
case "fullscreen":
case "activate":
this._updateNotifications();
break;
+ case "ViewShowing":
+ if (aEvent.target == this.libraryView) {
+ this.onLibraryViewShowing(aEvent.target);
+ }
+ break;
}
},
get isReady() {
return !!this._isReady;
},
get isNotificationPanelOpen() {
@@ -379,16 +394,18 @@ const PanelUI = {
return;
}
if (!aAnchor) {
Cu.reportError("Expected an anchor when opening subview with id: " + aViewId);
return;
}
+ this.ensureLibraryInitialized(viewNode);
+
let container = aAnchor.closest("panelmultiview,photonpanelmultiview");
if (container) {
container.showSubView(aViewId, aAnchor);
} else if (!aAnchor.open) {
aAnchor.open = true;
let tempPanel = document.createElement("panel");
tempPanel.setAttribute("type", "arrow");
@@ -477,16 +494,105 @@ const PanelUI = {
tempPanel.openPopup(anchor, {
position: "bottomcenter topright",
triggerEvent: domEvent,
});
}
},
/**
+ * Sets up the event listener for when the Library view is shown.
+ *
+ * @param {panelview} viewNode The library view.
+ */
+ ensureLibraryInitialized(viewNode) {
+ if (viewNode != this.libraryView || viewNode._initialized)
+ return;
+
+ viewNode._initialized = true;
+ viewNode.addEventListener("ViewShowing", this);
+ },
+
+ /**
+ * When the Library view is showing, we can start fetching and populating the
+ * list of Recent Highlights.
+ * This is done asynchronously and may finish when the view is already visible.
+ *
+ * @param {panelview} viewNode The library view.
+ */
+ async onLibraryViewShowing(viewNode) {
+ if (this._loadingRecentHighlights) {
+ return;
+ }
+ this._loadingRecentHighlights = true;
+
+ // Since the library is the first view shown, we don't want to add a blocker
+ // to the event, which would make PanelMultiView wait to show it.
+ let container = this.clearLibraryRecentHighlights();
+ if (!this.libraryRecentHighlightsEnabled) {
+ this._loadingRecentHighlights = false;
+ return;
+ }
+
+ let highlights = await NewTabUtils.activityStreamLinks.getHighlights({ withFavicons: true });
+ // If there's nothing to display, or the panel is already hidden, get out.
+ if (!highlights.length || viewNode.panelMultiView.getAttribute("panelopen") != "true") {
+ this._loadingRecentHighlights = false;
+ return;
+ }
+
+ container.hidden = container.previousSibling.hidden =
+ container.previousSibling.previousSibling.hidden = false;
+ let fragment = document.createDocumentFragment();
+ for (let highlight of highlights) {
+ let button = document.createElement("toolbarbutton");
+ button.classList.add("subviewbutton", "highlight", "subviewbutton-iconic", "bookmark-item");
+ let title = highlight.title || highlight.url;
+ button.setAttribute("label", title);
+ button.setAttribute("tooltiptext", title);
+ button.setAttribute("type", "highlight-" + highlight.type);
+ button.setAttribute("onclick", "PanelUI.onLibraryHighlightClick(event)");
+ if (highlight.favicon) {
+ button.setAttribute("image", highlight.favicon);
+ }
+ button._highlight = highlight;
+ fragment.appendChild(button);
+ }
+ container.appendChild(fragment);
+
+ this._loadingRecentHighlights = false;
+ },
+
+ /**
+ * Remove all the nodes from the 'Recent Highlights' section and hide it as well.
+ */
+ clearLibraryRecentHighlights() {
+ let container = document.getElementById("appMenu-library-recentHighlights")
+ while (container.firstChild) {
+ container.firstChild.remove();
+ }
+ container.hidden = container.previousSibling.hidden =
+ container.previousSibling.previousSibling.hidden = true;
+ return container;
+ },
+
+ /**
+ * Event handler; invoked when an item of the Recent Highlights is clicked.
+ *
+ * @param {MouseEvent} event Click event, originating from the Highlight.
+ */
+ onLibraryHighlightClick(event) {
+ let button = event.target;
+ if (event.button > 1 || !button._highlight) {
+ return;
+ }
+ window.openUILink(button._highlight.url, event);
+ },
+
+ /**
* NB: The enable- and disableSingleSubviewPanelAnimations methods only
* affect the hiding/showing animations of single-subview panels (tempPanel
* in the showSubView method).
*/
disableSingleSubviewPanelAnimations() {
this._disableAnimations = true;
},
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -1301,16 +1301,34 @@ panelview .toolbarbutton-1,
}
.subviewbutton[shortcut]::after,
.subviewbutton[shortcut]::after,
.PanelUI-subView .subviewbutton-nav::after {
margin-inline-start: 10px;
}
+.subviewbutton[type="highlight-bookmark"]::after {
+ content: url("chrome://browser/skin/bookmark-hollow.svg");
+}
+
+.subviewbutton[type="highlight-history"]::after {
+ content: url("chrome://browser/skin/history.svg");
+}
+
+.subviewbutton[type="highlight-bookmark"]::after,
+.subviewbutton[type="highlight-history"]::after {
+ -moz-context-properties: fill;
+ fill: GrayText;
+ float: right;
+ opacity: .5;
+ /* Centers the icon and resizes it to 12px square. */
+ transform: translateY(2px) scaleX(.75);
+}
+
/* This is a <label> but it should fit in with the menu font- and colorwise. */
#PanelUI-characterEncodingView-autodetect-label {
font: menu;
color: inherit;
}
/* START photon adjustments */