mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1561537 - Add badge/feature-callout style that matches the design spec r=r1cky
Differential Revision: https://phabricator.services.mozilla.com/D37403 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
556047a14b
commit
74e5670fe7
204
browser/components/newtab/lib/ToolbarBadgeHub.jsm
Normal file
204
browser/components/newtab/lib/ToolbarBadgeHub.jsm
Normal file
@ -0,0 +1,204 @@
|
||||
/* 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/. */
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"EveryWindow",
|
||||
"resource:///modules/EveryWindow.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"ToolbarPanelHub",
|
||||
"resource://activity-stream/lib/ToolbarPanelHub.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"setTimeout",
|
||||
"resource://gre/modules/Timer.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"clearTimeout",
|
||||
"resource://gre/modules/Timer.jsm"
|
||||
);
|
||||
|
||||
const notificationsByWindow = new WeakMap();
|
||||
|
||||
class _ToolbarBadgeHub {
|
||||
constructor() {
|
||||
this.id = "toolbar-badge-hub";
|
||||
this.template = "toolbar_badge";
|
||||
this.state = null;
|
||||
this.removeAllNotifications = this.removeAllNotifications.bind(this);
|
||||
this.removeToolbarNotification = this.removeToolbarNotification.bind(this);
|
||||
this.addToolbarNotification = this.addToolbarNotification.bind(this);
|
||||
this.registerBadgeToAllWindows = this.registerBadgeToAllWindows.bind(this);
|
||||
|
||||
this._handleMessageRequest = null;
|
||||
this._addImpression = null;
|
||||
this._blockMessageById = null;
|
||||
}
|
||||
|
||||
async init(
|
||||
waitForInitialized,
|
||||
{ handleMessageRequest, addImpression, blockMessageById }
|
||||
) {
|
||||
this._handleMessageRequest = handleMessageRequest;
|
||||
this._blockMessageById = blockMessageById;
|
||||
this._addImpression = addImpression;
|
||||
this.state = {};
|
||||
// Need to wait for ASRouter to initialize before trying to fetch messages
|
||||
await waitForInitialized;
|
||||
this.messageRequest("toolbarBadgeUpdate");
|
||||
}
|
||||
|
||||
executeAction({ id }) {
|
||||
switch (id) {
|
||||
case "show-whatsnew-button":
|
||||
ToolbarPanelHub.enableToolbarButton();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_clearBadgeTimeout() {
|
||||
if (this.state.showBadgeTimeoutId) {
|
||||
clearTimeout(this.state.showBadgeTimeoutId);
|
||||
}
|
||||
}
|
||||
|
||||
removeAllNotifications(event) {
|
||||
if (event) {
|
||||
// ignore right clicks
|
||||
if (
|
||||
(event.type === "mousedown" || event.type === "click") &&
|
||||
event.button !== 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// ignore keyboard access that is not one of the usual accessor keys
|
||||
if (
|
||||
event.type === "keypress" &&
|
||||
event.key !== " " &&
|
||||
event.key !== "Enter"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.target.removeEventListener(
|
||||
"mousedown",
|
||||
this.removeAllNotifications
|
||||
);
|
||||
event.target.removeEventListener("click", this.removeAllNotifications);
|
||||
}
|
||||
// Will call uninit on every window
|
||||
EveryWindow.unregisterCallback(this.id);
|
||||
if (this.state.notification) {
|
||||
this._blockMessageById(this.state.notification.id);
|
||||
}
|
||||
this._clearBadgeTimeout();
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
removeToolbarNotification(toolbarButton) {
|
||||
toolbarButton
|
||||
.querySelector(".toolbarbutton-badge")
|
||||
.classList.remove("feature-callout");
|
||||
toolbarButton
|
||||
.querySelector(".toolbarbutton-icon")
|
||||
.classList.add("feature-callout");
|
||||
toolbarButton.removeAttribute("badged");
|
||||
}
|
||||
|
||||
addToolbarNotification(win, message) {
|
||||
const document = win.browser.ownerDocument;
|
||||
if (message.content.action) {
|
||||
this.executeAction(message.content.action);
|
||||
}
|
||||
let toolbarbutton = document.getElementById(message.content.target);
|
||||
if (toolbarbutton) {
|
||||
toolbarbutton.setAttribute("badged", true);
|
||||
toolbarbutton
|
||||
.querySelector(".toolbarbutton-badge")
|
||||
.classList.add("feature-callout");
|
||||
toolbarbutton
|
||||
.querySelector(".toolbarbutton-icon")
|
||||
.classList.add("feature-callout");
|
||||
|
||||
// `mousedown` event required because of the `onmousedown` defined on
|
||||
// the button that prevents `click` events from firing
|
||||
toolbarbutton.addEventListener("mousedown", this.removeAllNotifications);
|
||||
// `click` event required for keyboard accessibility
|
||||
toolbarbutton.addEventListener("click", this.removeAllNotifications);
|
||||
this.state = { notification: { id: message.id } };
|
||||
|
||||
return toolbarbutton;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
registerBadgeToAllWindows(message) {
|
||||
// Impression should be added when the badge becomes visible
|
||||
this._addImpression(message);
|
||||
|
||||
EveryWindow.registerCallback(
|
||||
this.id,
|
||||
win => {
|
||||
if (notificationsByWindow.has(win)) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
const el = this.addToolbarNotification(win, message);
|
||||
notificationsByWindow.set(win, el);
|
||||
},
|
||||
win => {
|
||||
const el = notificationsByWindow.get(win);
|
||||
this.removeToolbarNotification(el);
|
||||
notificationsByWindow.delete(win);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
registerBadgeNotificationListener(message, options = {}) {
|
||||
// We need to clear any existing notifications and only show
|
||||
// the one set by devtools
|
||||
if (options.force) {
|
||||
this.removeAllNotifications();
|
||||
}
|
||||
|
||||
if (message.content.delay) {
|
||||
this.state.showBadgeTimeoutId = setTimeout(() => {
|
||||
this.registerBadgeToAllWindows(message);
|
||||
}, message.content.delay);
|
||||
} else {
|
||||
this.registerBadgeToAllWindows(message);
|
||||
}
|
||||
}
|
||||
|
||||
async messageRequest(triggerId) {
|
||||
const message = await this._handleMessageRequest({
|
||||
triggerId,
|
||||
template: this.template,
|
||||
});
|
||||
if (message) {
|
||||
this.registerBadgeNotificationListener(message);
|
||||
}
|
||||
}
|
||||
|
||||
uninit() {
|
||||
this._clearBadgeTimeout();
|
||||
this.state = null;
|
||||
}
|
||||
}
|
||||
|
||||
this._ToolbarBadgeHub = _ToolbarBadgeHub;
|
||||
|
||||
/**
|
||||
* ToolbarBadgeHub - singleton instance of _ToolbarBadgeHub that can initiate
|
||||
* message requests and render messages.
|
||||
*/
|
||||
this.ToolbarBadgeHub = new _ToolbarBadgeHub();
|
||||
|
||||
const EXPORTED_SYMBOLS = ["ToolbarBadgeHub", "_ToolbarBadgeHub"];
|
1
browser/themes/shared/badge-blue.svg
Normal file
1
browser/themes/shared/badge-blue.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><circle fill-opacity=".2" fill="#0DF" cx="8" cy="8" r="4"/><circle stroke-opacity=".5" stroke="#0090ED" fill="#00B3F4" cx="8" cy="8" r="2.5"/></g></svg>
|
After Width: | Height: | Size: 250 B |
5
browser/themes/shared/badge-cutout.svg
Normal file
5
browser/themes/shared/badge-cutout.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
|
||||
<clipPath id="badge-cutout">
|
||||
<path d="M11.1 0A5 5 0 0 0 16 6v10H0V0h11.1z"></path>
|
||||
</clipPath>
|
||||
</svg>
|
After Width: | Height: | Size: 172 B |
@ -245,6 +245,8 @@
|
||||
skin/classic/browser/translation-16.png (../shared/translation/translation-16.png)
|
||||
skin/classic/browser/translation-16@2x.png (../shared/translation/translation-16@2x.png)
|
||||
skin/classic/browser/update-badge.svg (../shared/update-badge.svg)
|
||||
skin/classic/browser/badge-cutout.svg (../shared/badge-cutout.svg)
|
||||
skin/classic/browser/badge-blue.svg (../shared/badge-blue.svg)
|
||||
skin/classic/browser/warning.svg (../shared/warning.svg)
|
||||
skin/classic/browser/cert-error.svg (../shared/incontent-icons/cert-error.svg)
|
||||
skin/classic/browser/wifi.svg (../shared/incontent-icons/wifi.svg)
|
||||
|
@ -389,3 +389,21 @@ toolbarbutton.bookmark-item {
|
||||
padding: 1px var(--toolbarbutton-inner-padding);
|
||||
border-radius: var(--toolbarbutton-border-radius);
|
||||
}
|
||||
|
||||
/* Alternative style for .toolbarbutton-badge used by CFR notifications */
|
||||
.toolbarbutton-badge.feature-callout {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
min-width: auto;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
display: block;
|
||||
margin: -7px 0 0 !important;
|
||||
margin-inline-end: -6px !important;
|
||||
background: url(chrome://browser/skin/badge-blue.svg);
|
||||
}
|
||||
|
||||
.toolbarbutton-icon.feature-callout {
|
||||
clip-path: url(chrome://browser/skin/badge-cutout.svg#badge-cutout);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user