Bug 1080406 - "Add an optional badge to the hamburger menu when updates are available". r=gijskruitbosch+bugs c=jwalker

This commit is contained in:
Matteo Ferretti 2014-11-02 02:09:00 +01:00
parent daabef29fa
commit c6387f65a5
6 changed files with 170 additions and 0 deletions

View File

@ -182,6 +182,9 @@ pref("app.update.metro.enabled", true);
// If set to true, the Update Service will present no UI for any event.
pref("app.update.silent", false);
// If set to true, the hamburger button will show badges for update events.
pref("app.update.badge", false);
// If set to true, the Update Service will apply updates in the background
// when it finishes downloading them.
pref("app.update.staging.enabled", true);

View File

@ -1324,6 +1324,8 @@ var gBrowserInit = {
// Add Devtools menuitems and listeners
gDevToolsBrowser.registerBrowserWindow(window);
gMenuButtonUpdateBadge.init();
window.addEventListener("mousemove", MousePosTracker, false);
window.addEventListener("dragover", MousePosTracker, false);
@ -1470,6 +1472,8 @@ var gBrowserInit = {
DevEdition.uninit();
gMenuButtonUpdateBadge.uninit();
var enumerator = Services.wm.getEnumerator(null);
enumerator.getNext();
if (!enumerator.hasMoreElements()) {
@ -2439,6 +2443,118 @@ function PageProxyClickHandler(aEvent)
middleMousePaste(aEvent);
}
// Setup the hamburger button badges for updates, if enabled.
let gMenuButtonUpdateBadge = {
enabled: false,
init: function () {
try {
this.enabled = Services.prefs.getBoolPref("app.update.badge");
} catch (e) {}
if (this.enabled) {
PanelUI.menuButton.classList.add("badged-button");
Services.obs.addObserver(this, "update-staged", false);
}
},
uninit: function () {
if (this.enabled) {
Services.obs.removeObserver(this, "update-staged");
PanelUI.panel.removeEventListener("popupshowing", this, true);
this.enabled = false;
}
},
onMenuPanelCommand: function(event) {
if (event.originalTarget.getAttribute("update-status") === "succeeded") {
// restart the app
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]
.createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
if (!cancelQuit.data) {
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
}
} else {
// open the page for manual update
let url = Services.urlFormatter.formatURLPref("app.update.url.manual");
openUILinkIn(url, "tab");
}
},
observe: function (subject, topic, status) {
const STATE_DOWNLOADING = "downloading";
const STATE_PENDING = "pending";
const STATE_PENDING_SVC = "pending-service";
const STATE_APPLIED = "applied";
const STATE_APPLIED_SVC = "applied-service";
const STATE_FAILED = "failed";
let updateButton = document.getElementById("PanelUI-update-status");
let updateButtonText;
let stringId;
// Update the UI when the background updater is finished.
switch (status) {
case STATE_APPLIED:
case STATE_APPLIED_SVC:
case STATE_PENDING:
case STATE_PENDING_SVC:
// If the update is successfully applied, or if the updater has fallen back
// to non-staged updates, add a badge to the hamburger menu to indicate an
// update will be applied once the browser restarts.
let badge = document.getAnonymousElementByAttribute(PanelUI.menuButton,
"class",
"toolbarbutton-badge");
badge.style.backgroundColor = 'green';
PanelUI.menuButton.setAttribute("badge", "\u2605");
let brandBundle = document.getElementById("bundle_brand");
let brandShortName = brandBundle.getString("brandShortName");
stringId = "appmenu.restartNeeded.description";
updateButtonText = gNavigatorBundle.getFormattedString(stringId,
[brandShortName]);
updateButton.label = updateButtonText;
updateButton.hidden = false;
updateButton.setAttribute("update-status", "succeeded");
PanelUI.panel.addEventListener("popupshowing", this, true);
break;
case STATE_FAILED:
// Background update has failed, let's show the UI responsible for
// prompting the user to update manually.
PanelUI.menuButton.setAttribute("badge", "!");
stringId = "appmenu.updateFailed.description";
updateButtonText = gNavigatorBundle.getString(stringId);
updateButton.label = updateButtonText;
updateButton.hidden = false;
updateButton.setAttribute("update-status", "failed");
PanelUI.panel.addEventListener("popupshowing", this, true);
break;
case STATE_DOWNLOADING:
// We've fallen back to downloading the full update because the partial
// update failed to get staged in the background. Therefore we need to keep
// our observer.
return;
}
this.uninit();
},
handleEvent: function(e) {
if (e.type === "popupshowing") {
PanelUI.menuButton.removeAttribute("badge");
PanelUI.panel.removeEventListener("popupshowing", this, true);
}
}
};
/**
* Handle command events bubbling up from error page content
* or from about:newtab or from remote error pages that invoke

View File

@ -16,6 +16,10 @@
</vbox>
<footer id="PanelUI-footer">
<toolbarbutton id="PanelUI-update-status"
oncommand="gMenuButtonUpdateBadge.onMenuPanelCommand(event);"
wrap="true"
hidden="true"/>
<toolbarbutton id="PanelUI-fxa-status"
defaultlabel="&fxaSignIn.label;"
errorlabel="&fxaSignInError.label;"

View File

@ -1413,6 +1413,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
-moz-image-region: rect(0px, 192px, 32px, 160px);
}
#PanelUI-update-status > .toolbarbutton-icon,
#PanelUI-fxa-status > .toolbarbutton-icon,
#PanelUI-quit > .toolbarbutton-icon,
#PanelUI-customize > .toolbarbutton-icon,

View File

@ -22,6 +22,10 @@
linear-gradient(rgba(255,255,255,0.3), transparent);
}
#PanelUI-update-status {
list-style-image: url(chrome://branding/content/icon32.png);
}
#PanelUI-fxa-status {
list-style-image: url(chrome://browser/skin/sync-horizontalbar@2x.png);
}

View File

@ -381,6 +381,7 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"] > iframe {
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .panel-wide-item,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-contents-scroller > #PanelUI-contents > .toolbarbutton-1:not([panel-multiview-anchor="true"]),
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-fxa-status,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-update-status,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > toolbarseparator,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > #PanelUI-customize,
#PanelUI-multiView[viewtype="subview"] #PanelUI-mainView > #PanelUI-footer > #PanelUI-footer-inner > #PanelUI-help:not([panel-multiview-anchor="true"]) {
@ -493,6 +494,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
margin: 0;
}
#PanelUI-update-status,
#PanelUI-help,
#PanelUI-fxa-status,
#PanelUI-customize,
@ -509,12 +511,14 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
-moz-box-orient: horizontal;
}
#PanelUI-update-status,
#PanelUI-fxa-status {
border-top: 1px solid hsla(210,4%,10%,.14);
border-bottom: 1px solid transparent;
margin-bottom: -1px;
}
#PanelUI-update-status > .toolbarbutton-text,
#PanelUI-fxa-status > .toolbarbutton-text {
width: 0; /* Fancy cropping solution for flexbox. */
}
@ -524,6 +528,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
min-width: 46px;
}
#PanelUI-update-status > .toolbarbutton-text,
#PanelUI-fxa-status > .toolbarbutton-text,
#PanelUI-customize > .toolbarbutton-text {
margin: 0;
@ -536,6 +541,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
display: none;
}
#PanelUI-update-status > .toolbarbutton-icon,
#PanelUI-fxa-status > .toolbarbutton-icon,
#PanelUI-customize > .toolbarbutton-icon,
#PanelUI-help > .toolbarbutton-icon,
@ -550,6 +556,16 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
-moz-border-start-style: none;
}
#PanelUI-update-status {
width: calc(@menuPanelWidth@ + 30px);
-moz-padding-start: 15px;
-moz-border-start-style: none;
}
#PanelUI-update-status {
list-style-image: url(chrome://branding/content/icon16.png);
}
#PanelUI-fxa-status {
list-style-image: url(chrome://browser/skin/sync-horizontalbar.png);
}
@ -625,6 +641,32 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
outline: none;
}
#PanelUI-update-status[update-status="succeeded"] {
background-color: hsla(96, 65%, 75%, 0.1);
}
#PanelUI-update-status[update-status="succeeded"]:not([disabled]):hover {
background-color: hsla(96, 65%, 75%, 0.4);
}
#PanelUI-update-status[update-status="succeeded"]:not([disabled]):hover:active {
background-color: hsla(96, 65%, 75%, 0.6);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
#PanelUI-update-status[update-status="failed"] {
background-color: hsla(359, 69%, 84%, 0.1);
}
#PanelUI-update-status[update-status="failed"]:not([disabled]):hover {
background-color: hsla(359, 69%, 84%, 0.4);
}
#PanelUI-update-status[update-status="failed"]:not([disabled]):hover:active {
background-color: hsla(359, 69%, 84%, 0.6);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}
#PanelUI-quit:not([disabled]):hover {
background-color: #d94141;
outline-color: #c23a3a;