commit
9fcf822140
4 changed files with 46 additions and 137 deletions
|
@ -68,6 +68,16 @@ Containers will use Test Pilot Telemetry with no batching of data. Details
|
||||||
of when pings are sent are below, along with examples of the `payload` portion
|
of when pings are sent are below, along with examples of the `payload` portion
|
||||||
of a `testpilottest` telemetry ping for each scenario.
|
of a `testpilottest` telemetry ping for each scenario.
|
||||||
|
|
||||||
|
* The user shows the new tab menu
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"uuid": <uuid>,
|
||||||
|
"event": "show-plus-button-menu",
|
||||||
|
"eventSource": ["plus-button"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
* The user clicks on a container name to open a tab in that container
|
* The user clicks on a container name to open a tab in that container
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -76,7 +86,7 @@ of a `testpilottest` telemetry ping for each scenario.
|
||||||
"userContextId": <userContextId>,
|
"userContextId": <userContextId>,
|
||||||
"clickedContainerTabCount": <number-of-tabs-in-the-container>,
|
"clickedContainerTabCount": <number-of-tabs-in-the-container>,
|
||||||
"event": "open-tab",
|
"event": "open-tab",
|
||||||
"eventSource": ["tab-bar"|"pop-up"|"file-menu"|"alltabs-menu"]
|
"eventSource": ["tab-bar"|"pop-up"|"file-menu"|"alltabs-menu"|"plus-button"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -269,7 +279,7 @@ local schema = {
|
||||||
|
|
||||||
### Valid data should be enforced on the server side:
|
### Valid data should be enforced on the server side:
|
||||||
|
|
||||||
* `eventSource` should be one of `tab-bar`, `pop-up`, or `file-menu`.
|
* `eventSource` should be one of `tab-bar`, `pop-up`, `file-menu`, "alltabs-nmenu" or "plus-button".
|
||||||
|
|
||||||
All Mozilla data is kept by default for 180 days and in accordance with our
|
All Mozilla data is kept by default for 180 days and in accordance with our
|
||||||
privacy policies.
|
privacy policies.
|
||||||
|
|
165
index.js
165
index.js
|
@ -6,9 +6,6 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
const DEFAULT_TAB = "about:newtab";
|
const DEFAULT_TAB = "about:newtab";
|
||||||
const LOOKUP_KEY = "$ref";
|
const LOOKUP_KEY = "$ref";
|
||||||
|
|
||||||
const SHOW_MENU_TIMEOUT = 100;
|
|
||||||
const HIDE_MENU_TIMEOUT = 300;
|
|
||||||
|
|
||||||
const INCOMPATIBLE_ADDON_IDS = [
|
const INCOMPATIBLE_ADDON_IDS = [
|
||||||
"pulse@mozilla.com",
|
"pulse@mozilla.com",
|
||||||
"snoozetabs@mozilla.com",
|
"snoozetabs@mozilla.com",
|
||||||
|
@ -246,18 +243,15 @@ const ContainerService = {
|
||||||
}
|
}
|
||||||
|
|
||||||
tabs.on("open", tab => {
|
tabs.on("open", tab => {
|
||||||
this._hideAllPanels();
|
|
||||||
this._restyleTab(tab);
|
this._restyleTab(tab);
|
||||||
this._remapTab(tab);
|
this._remapTab(tab);
|
||||||
});
|
});
|
||||||
|
|
||||||
tabs.on("close", tab => {
|
tabs.on("close", tab => {
|
||||||
this._hideAllPanels();
|
|
||||||
this._remapTab(tab);
|
this._remapTab(tab);
|
||||||
});
|
});
|
||||||
|
|
||||||
tabs.on("activate", tab => {
|
tabs.on("activate", tab => {
|
||||||
this._hideAllPanels();
|
|
||||||
this._restyleActiveTab(tab).catch(() => {});
|
this._restyleActiveTab(tab).catch(() => {});
|
||||||
this._configureActiveWindows();
|
this._configureActiveWindows();
|
||||||
this._remapTab(tab);
|
this._remapTab(tab);
|
||||||
|
@ -941,12 +935,6 @@ const ContainerService = {
|
||||||
return this._configureWindows();
|
return this._configureWindows();
|
||||||
},
|
},
|
||||||
|
|
||||||
_hideAllPanels() {
|
|
||||||
for (let windowObject of this._windowMap.values()) { // eslint-disable-line prefer-const
|
|
||||||
windowObject.hidePanel();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_restyleActiveTab(tab) {
|
_restyleActiveTab(tab) {
|
||||||
if (!tab) {
|
if (!tab) {
|
||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
|
@ -1105,22 +1093,50 @@ ContainerWindow.prototype = {
|
||||||
_timeoutStore: new Map(),
|
_timeoutStore: new Map(),
|
||||||
_elementCache: new Map(),
|
_elementCache: new Map(),
|
||||||
_tooltipCache: new Map(),
|
_tooltipCache: new Map(),
|
||||||
_plusButton: null,
|
|
||||||
_overflowPlusButton: null,
|
|
||||||
_tabsElement: null,
|
_tabsElement: null,
|
||||||
|
|
||||||
_init(window) {
|
_init(window) {
|
||||||
this._window = window;
|
this._window = window;
|
||||||
this._tabsElement = this._window.document.getElementById("tabbrowser-tabs");
|
this._tabsElement = this._window.document.getElementById("tabbrowser-tabs");
|
||||||
|
this._style = Style({ uri: self.data.url("usercontext.css") });
|
||||||
this._plusButton = this._window.document.getAnonymousElementByAttribute(this._tabsElement, "anonid", "tabs-newtab-button");
|
this._plusButton = this._window.document.getAnonymousElementByAttribute(this._tabsElement, "anonid", "tabs-newtab-button");
|
||||||
this._overflowPlusButton = this._window.document.getElementById("new-tab-button");
|
this._overflowPlusButton = this._window.document.getElementById("new-tab-button");
|
||||||
this._style = Style({ uri: self.data.url("usercontext.css") });
|
|
||||||
|
// Only hack the normal plus button as the alltabs is done elsewhere
|
||||||
|
this.attachMenuEvent("plus-button", this._plusButton);
|
||||||
|
|
||||||
attachTo(this._style, this._window);
|
attachTo(this._style, this._window);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
attachMenuEvent(source, button) {
|
||||||
|
const popup = button.querySelector(".new-tab-popup");
|
||||||
|
popup.addEventListener("popupshown", () => {
|
||||||
|
ContainerService.sendTelemetryPayload({
|
||||||
|
"event": "show-plus-button-menu",
|
||||||
|
"eventSource": source
|
||||||
|
});
|
||||||
|
popup.querySelector("menuseparator").remove();
|
||||||
|
const popupMenuItems = [...popup.querySelectorAll("menuitem")];
|
||||||
|
popupMenuItems.forEach((item) => {
|
||||||
|
const userContextId = item.getAttribute("data-usercontextid");
|
||||||
|
if (!userContextId) {
|
||||||
|
item.remove();
|
||||||
|
}
|
||||||
|
item.setAttribute("command", "");
|
||||||
|
item.addEventListener("command", (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
ContainerService.openTab({
|
||||||
|
userContextId: userContextId,
|
||||||
|
source: source
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
configure() {
|
configure() {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
this._configurePlusButtonMenu(),
|
|
||||||
this._configureActiveTab(),
|
this._configureActiveTab(),
|
||||||
this._configureFileMenu(),
|
this._configureFileMenu(),
|
||||||
this._configureAllTabsMenu(),
|
this._configureAllTabsMenu(),
|
||||||
|
@ -1133,113 +1149,6 @@ ContainerWindow.prototype = {
|
||||||
return this._configureContextMenu();
|
return this._configureContextMenu();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEvent(e) {
|
|
||||||
let el = e.target;
|
|
||||||
switch (e.type) {
|
|
||||||
case "mouseover":
|
|
||||||
this._createTimeout("show", () => {
|
|
||||||
this.showPopup(el);
|
|
||||||
}, SHOW_MENU_TIMEOUT);
|
|
||||||
break;
|
|
||||||
case "click":
|
|
||||||
this.hidePanel();
|
|
||||||
break;
|
|
||||||
case "mouseout":
|
|
||||||
while(el) {
|
|
||||||
if (el === this._panelElement ||
|
|
||||||
el === this._plusButton ||
|
|
||||||
el === this._overflowPlusButton) {
|
|
||||||
// Clear show timeout so we don't hide and reshow
|
|
||||||
this._cleanTimeout("show");
|
|
||||||
this._createTimeout("hidden", () => {
|
|
||||||
this.hidePanel();
|
|
||||||
}, HIDE_MENU_TIMEOUT);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
el = el.parentElement;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
showPopup(buttonElement) {
|
|
||||||
this._cleanAllTimeouts();
|
|
||||||
this._panelElement.openPopup(buttonElement);
|
|
||||||
},
|
|
||||||
|
|
||||||
_configurePlusButtonMenuElement(buttonElement) {
|
|
||||||
if (buttonElement) {
|
|
||||||
// Let's remove the tooltip because it can go over our panel.
|
|
||||||
this._tooltipCache.set(buttonElement, buttonElement.getAttribute("tooltip"));
|
|
||||||
buttonElement.setAttribute("tooltip", "");
|
|
||||||
this._disableElement(buttonElement);
|
|
||||||
|
|
||||||
buttonElement.addEventListener("mouseover", this);
|
|
||||||
buttonElement.addEventListener("click", this);
|
|
||||||
buttonElement.addEventListener("mouseout", this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async _configurePlusButtonMenu() {
|
|
||||||
const mainPopupSetElement = this._window.document.getElementById("mainPopupSet");
|
|
||||||
|
|
||||||
// Let's remove all the previous panels.
|
|
||||||
if (this._panelElement) {
|
|
||||||
this._panelElement.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._panelElement = this._window.document.createElementNS(XUL_NS, "panel");
|
|
||||||
this._panelElement.setAttribute("id", "new-tab-overlay");
|
|
||||||
this._panelElement.setAttribute("position", "bottomcenter topleft");
|
|
||||||
this._panelElement.setAttribute("side", "top");
|
|
||||||
this._panelElement.setAttribute("flip", "side");
|
|
||||||
this._panelElement.setAttribute("type", "arrow");
|
|
||||||
this._panelElement.setAttribute("animate", "open");
|
|
||||||
this._panelElement.setAttribute("consumeoutsideclicks", "never");
|
|
||||||
mainPopupSetElement.appendChild(this._panelElement);
|
|
||||||
|
|
||||||
this._configurePlusButtonMenuElement(this._plusButton);
|
|
||||||
this._configurePlusButtonMenuElement(this._overflowPlusButton);
|
|
||||||
|
|
||||||
this._panelElement.addEventListener("mouseout", this);
|
|
||||||
|
|
||||||
this._panelElement.addEventListener("mouseover", () => {
|
|
||||||
this._cleanAllTimeouts();
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const identities = await ContainerService.queryIdentities();
|
|
||||||
identities.forEach(identity => {
|
|
||||||
const menuItemElement = this._window.document.createElementNS(XUL_NS, "menuitem");
|
|
||||||
this._panelElement.appendChild(menuItemElement);
|
|
||||||
menuItemElement.className = "menuitem-iconic";
|
|
||||||
menuItemElement.setAttribute("tooltiptext", identity.name);
|
|
||||||
menuItemElement.setAttribute("label", identity.name);
|
|
||||||
menuItemElement.setAttribute("data-usercontextid", identity.userContextId);
|
|
||||||
menuItemElement.setAttribute("data-identity-icon", identity.icon);
|
|
||||||
menuItemElement.setAttribute("data-identity-color", identity.color);
|
|
||||||
|
|
||||||
menuItemElement.addEventListener("command", (e) => {
|
|
||||||
ContainerService.openTab({
|
|
||||||
userContextId: identity.userContextId,
|
|
||||||
source: "tab-bar"
|
|
||||||
});
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
menuItemElement.addEventListener("mouseover", () => {
|
|
||||||
this._cleanAllTimeouts();
|
|
||||||
});
|
|
||||||
|
|
||||||
menuItemElement.addEventListener("mouseout", this);
|
|
||||||
|
|
||||||
this._panelElement.appendChild(menuItemElement);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.hidePanel();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_configureTabStyle() {
|
_configureTabStyle() {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
for (let tab of modelFor(this._window).tabs) { // eslint-disable-line prefer-const
|
for (let tab of modelFor(this._window).tabs) { // eslint-disable-line prefer-const
|
||||||
|
@ -1409,11 +1318,6 @@ ContainerWindow.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hidePanel() {
|
|
||||||
this._cleanAllTimeouts();
|
|
||||||
this._panelElement.hidePopup();
|
|
||||||
},
|
|
||||||
|
|
||||||
shutdown() {
|
shutdown() {
|
||||||
// CSS must be removed.
|
// CSS must be removed.
|
||||||
detachFrom(this._style, this._window);
|
detachFrom(this._style, this._window);
|
||||||
|
@ -1437,11 +1341,6 @@ ContainerWindow.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_shutdownPlusButtonMenu() {
|
|
||||||
this._shutDownPlusButtonMenuElement(this._plusButton);
|
|
||||||
this._shutDownPlusButtonMenuElement(this._overflowPlusButton);
|
|
||||||
},
|
|
||||||
|
|
||||||
_shutdownFileMenu() {
|
_shutdownFileMenu() {
|
||||||
this._shutdownMenu("menu_newUserContext");
|
this._shutdownMenu("menu_newUserContext");
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.container-notification {
|
.container-notification {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #33f70c;
|
background: #efefef;
|
||||||
color: #003f07;
|
color: #003f07;
|
||||||
display: flex;
|
display: flex;
|
||||||
font: 12px sans-serif;
|
font: 12px sans-serif;
|
||||||
|
|
|
@ -31,7 +31,7 @@ async function addMessage(message) {
|
||||||
|
|
||||||
await delayAnimation(100);
|
await delayAnimation(100);
|
||||||
await doAnimation(divElement, "transform", "translateY(0)");
|
await doAnimation(divElement, "transform", "translateY(0)");
|
||||||
await delayAnimation(2000);
|
await delayAnimation(3000);
|
||||||
await doAnimation(divElement, "transform", "translateY(-100%)");
|
await doAnimation(divElement, "transform", "translateY(-100%)");
|
||||||
|
|
||||||
divElement.remove();
|
divElement.remove();
|
||||||
|
|
Loading…
Add table
Reference in a new issue