From 0cbc9879bb7f345bbba0378ad2c22a36fb2d1570 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Wed, 12 Feb 2020 12:24:35 -0600 Subject: [PATCH 01/29] Implemented UI/UX for container list Panel (first panel). --- src/css/popup.css | 140 ++++++++++++++++--- src/img/arrow-icon-left.svg | 1 + src/img/arrow-icon-right.svg | 21 +++ src/img/movetowindow-16.svg | 7 + src/img/open-in-new-16.svg | 7 + src/img/open-in-stop-16.svg | 7 + src/img/password-hide.svg | 9 ++ src/img/refresh-16.svg | 6 + src/img/sort-16_1.svg | 6 + src/img/tab-new-16.svg | 6 + src/js/popup.js | 253 +++++++++++++++-------------------- src/popup.html | 124 ++++++++++++----- 12 files changed, 383 insertions(+), 204 deletions(-) create mode 100644 src/img/arrow-icon-left.svg create mode 100644 src/img/arrow-icon-right.svg create mode 100644 src/img/movetowindow-16.svg create mode 100644 src/img/open-in-new-16.svg create mode 100644 src/img/open-in-stop-16.svg create mode 100644 src/img/password-hide.svg create mode 100644 src/img/refresh-16.svg create mode 100644 src/img/sort-16_1.svg create mode 100644 src/img/tab-new-16.svg diff --git a/src/css/popup.css b/src/css/popup.css index 3ce65aa..2dc9bc9 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -91,7 +91,7 @@ table { } .scrollable { - border-block-start: 1px solid #f1f1f1; +/* border-block-start: 1px solid #f1f1f1;*/ inline-size: 100%; max-block-size: 400px; overflow: auto; @@ -493,24 +493,6 @@ manage things like container crud */ margin-inline-start: var(--inline-item-space-size); } -#container-panel #sort-containers-link { - align-items: center; - block-size: var(--block-url-label-size); - border: 1px solid #d8d8d8; - border-radius: var(--small-radius); - color: var(--title-text-color); - display: flex; - font-size: var(--small-text-size); - inline-size: var(--inline-button-size); - justify-content: center; - text-decoration: none; -} - -#container-panel #sort-containers-link:hover, -#container-panel #sort-containers-link:focus { - background: #f2f2f2; -} - span ~ .panel-header-text { padding-block-end: 0; padding-block-start: 0; @@ -649,7 +631,7 @@ span ~ .panel-header-text { background-image: var(--identity-icon); background-position: center center; background-repeat: no-repeat; - background-size: 20px 20px; + background-size: 16px 16px; block-size: 100%; fill: var(--identity-icon-color); filter: url('/img/filters.svg#fill'); @@ -1008,3 +990,121 @@ span ~ .panel-header-text { .amo-rate-cta { background: #0f1126; } + +body { + font-family: 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + color: #000000; + font-size: 13px; + letter-spacing: -0.1px; + width: 320px; + /* remove in prodcution*/ +} + +h3.title { + width: 100%; + color: #000000; + font-size: 13px; + letter-spacing: -0.1px; + font-weight: bold; + line-height: 40px; + text-align: center; + height: 40px; +} + +.menu { + width: 100%; + border-style: none; +} + +.menu-item { + height: 24px; + line-height: 24px; + width: 100%; + cursor: pointer; +} + +.menu-item:hover { + background: #1296F8; + color: #FFFFFF; +} + +.hover-highlight { + +} + +.menu-text { + line-height: 24px; +} + +.menu-icon { + float: left; + text-align: center; + width: 40px; + display: block; + height: 24px; + padding: 0 8px 0 16px; +} + +.menu-right-float { + float: right; + text-align: right; + width: 60px; + display: inline-block; + height: 24px; +} + +.container-count { + opacity: 0.6; + padding: 0 6px 0 0; + text-align: right; +} + +.menu-arrow { + float: right; + text-align: center; + width: 18px; + display: inline-block; + height: 24px; + padding: 6px 12px 6px 0; +} + +.menu-arrow img { + padding: 2 2 2 2; + height: 12px; + width: 12px; +} + +hr { + display: block; + border: 0; + border-top: 1px solid #e3e3e3; + padding: 0 0 6px 0; + margin: 6px 0 0 0; +} + +.sub-header { + height: 24px; + color: #737373; + line-height: 24px; + padding: 0 16px 0 16px; +} + +.identities-list { + margin: 0 0 41px 0; +} + +.bottom-btn { + height: 41px; + line-height: 41px; + background-color: #e3e3e3; + padding: 0 16px 0 16px; + border: solid 1px #d9d9d9; + cursor: pointer; + position: fixed; + bottom: 0px; + width: 100%; +} + +.menu-panel { + justify-content: flex-start; +} \ No newline at end of file diff --git a/src/img/arrow-icon-left.svg b/src/img/arrow-icon-left.svg new file mode 100644 index 0000000..ab0a30f --- /dev/null +++ b/src/img/arrow-icon-left.svg @@ -0,0 +1 @@ + diff --git a/src/img/arrow-icon-right.svg b/src/img/arrow-icon-right.svg new file mode 100644 index 0000000..f740140 --- /dev/null +++ b/src/img/arrow-icon-right.svg @@ -0,0 +1,21 @@ + + + + Arrow + Created with Sketch. + + + + + + + + + + + + + + + + diff --git a/src/img/movetowindow-16.svg b/src/img/movetowindow-16.svg new file mode 100644 index 0000000..80181a3 --- /dev/null +++ b/src/img/movetowindow-16.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/src/img/open-in-new-16.svg b/src/img/open-in-new-16.svg new file mode 100644 index 0000000..c6685c4 --- /dev/null +++ b/src/img/open-in-new-16.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/src/img/open-in-stop-16.svg b/src/img/open-in-stop-16.svg new file mode 100644 index 0000000..8ba3d97 --- /dev/null +++ b/src/img/open-in-stop-16.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/src/img/password-hide.svg b/src/img/password-hide.svg new file mode 100644 index 0000000..af7818d --- /dev/null +++ b/src/img/password-hide.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/src/img/refresh-16.svg b/src/img/refresh-16.svg new file mode 100644 index 0000000..2e40ef6 --- /dev/null +++ b/src/img/refresh-16.svg @@ -0,0 +1,6 @@ + + + + diff --git a/src/img/sort-16_1.svg b/src/img/sort-16_1.svg new file mode 100644 index 0000000..83ae0ee --- /dev/null +++ b/src/img/sort-16_1.svg @@ -0,0 +1,6 @@ + + + + diff --git a/src/img/tab-new-16.svg b/src/img/tab-new-16.svg new file mode 100644 index 0000000..d8c7ba6 --- /dev/null +++ b/src/img/tab-new-16.svg @@ -0,0 +1,6 @@ + + + + diff --git a/src/js/popup.js b/src/js/popup.js index 1349ffa..1d4fce6 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -20,7 +20,11 @@ const P_ONBOARDING_5 = "onboarding5"; const P_ONBOARDING_6 = "onboarding6"; const P_ONBOARDING_7 = "onboarding7"; const P_CONTAINERS_LIST = "containersList"; -const P_CONTAINERS_EDIT = "containersEdit"; +const P_CONTAINER_PICKER = "containerPicker"; +const OPEN_NEW_CONTAINER_PICKER = "new-tab"; +const MANAGE_CONTAINERS_PICKER = "manage"; +const REOPEN_IN_CONTAINER = "reopen-in"; +const ALWAYS_OPEN_IN_PICKER = "always-open-in"; const P_CONTAINER_INFO = "containerInfo"; const P_CONTAINER_EDIT = "containerEdit"; const P_CONTAINER_DELETE = "containerDelete"; @@ -275,7 +279,7 @@ const Logic = { } }, - async showPanel(panel, currentIdentity = null) { + async showPanel(panel, currentIdentity = null, pickerType = null) { // Invalid panel... ?!? if (!(panel in this._panels)) { throw new Error("Something really bad happened. Unknown panel: " + panel); @@ -283,6 +287,7 @@ const Logic = { this._previousPanel = this._currentPanel; this._currentPanel = panel; + this.pickerType = pickerType; this._currentIdentity = currentIdentity; @@ -589,16 +594,20 @@ Logic.registerPanel(P_CONTAINERS_LIST, { // This method is called when the object is registered. async initialize() { - Logic.addEnterHandler(document.querySelector("#container-add-link"), () => { - Logic.showPanel(P_CONTAINER_EDIT, { name: Logic.generateIdentityName() }); - }); - - Logic.addEnterHandler(document.querySelector("#edit-containers-link"), (e) => { + Logic.addEnterHandler(document.querySelector("#manage-containers-link"), (e) => { if (!e.target.classList.contains("disable-edit-containers")) { - Logic.showPanel(P_CONTAINERS_EDIT); + Logic.showPanel(P_CONTAINER_PICKER, null, MANAGE_CONTAINERS_PICKER); } }); - + Logic.addEnterHandler(document.querySelector("#open-new-tab-in"), () => { + Logic.showPanel(P_CONTAINER_PICKER, null, OPEN_NEW_CONTAINER_PICKER); + }); + Logic.addEnterHandler(document.querySelector("#reopen-site-in"), () => { + Logic.showPanel(P_CONTAINER_PICKER, null, REOPEN_IN_CONTAINER); + }); + Logic.addEnterHandler(document.querySelector("#always-open-in"), () => { + Logic.showPanel(P_CONTAINER_PICKER, null, ALWAYS_OPEN_IN_PICKER); + }); Logic.addEnterHandler(document.querySelector("#sort-containers-link"), async () => { try { await browser.runtime.sendMessage({ @@ -660,123 +669,47 @@ Logic.registerPanel(P_CONTAINERS_LIST, { break; } }); - - // When the popup is open sometimes the tab will still be updating it's state - this.tabUpdateHandler = (tabId, changeInfo) => { - const propertiesToUpdate = ["title", "favIconUrl"]; - const hasChanged = Object.keys(changeInfo).find((changeInfoKey) => { - if (propertiesToUpdate.includes(changeInfoKey)) { - return true; - } - }); - if (hasChanged) { - this.prepareCurrentTabHeader(); - } - }; - browser.tabs.onUpdated.addListener(this.tabUpdateHandler); }, unregister() { - browser.tabs.onUpdated.removeListener(this.tabUpdateHandler); - }, - setupAssignmentCheckbox(siteSettings, currentUserContextId) { - const assignmentCheckboxElement = document.getElementById("container-page-assigned"); - let checked = false; - if (siteSettings && Number(siteSettings.userContextId) === currentUserContextId) { - checked = true; - } - assignmentCheckboxElement.checked = checked; - let disabled = false; - if (siteSettings === false) { - disabled = true; - } - assignmentCheckboxElement.disabled = disabled; - }, - - async prepareCurrentTabHeader() { - const currentTab = await Logic.currentTab(); - const currentTabElement = document.getElementById("current-tab"); - const assignmentCheckboxElement = document.getElementById("container-page-assigned"); - const currentTabUserContextId = Logic.userContextId(currentTab.cookieStoreId); - assignmentCheckboxElement.addEventListener("change", () => { - Logic.setOrRemoveAssignment(currentTab.id, currentTab.url, currentTabUserContextId, !assignmentCheckboxElement.checked); - }); - currentTabElement.hidden = !currentTab; - this.setupAssignmentCheckbox(false, currentTabUserContextId); - if (currentTab) { - const identity = await Logic.identity(currentTab.cookieStoreId); - const siteSettings = await Logic.getAssignment(currentTab); - this.setupAssignmentCheckbox(siteSettings, currentTabUserContextId); - const currentPage = document.getElementById("current-page"); - currentPage.innerHTML = escaped`${currentTab.title}`; - const favIconElement = Utils.createFavIconElement(currentTab.favIconUrl || ""); - currentPage.prepend(favIconElement); - - const currentContainer = document.getElementById("current-container"); - currentContainer.innerText = identity.name; - - currentContainer.setAttribute("data-identity-color", identity.color); - } }, // This method is called when the panel is shown. async prepare() { const fragment = document.createDocumentFragment(); - this.prepareCurrentTabHeader(); - Logic.identities().forEach(identity => { - const hasTabs = (identity.hasHiddenTabs || identity.hasOpenTabs); const tr = document.createElement("tr"); - const context = document.createElement("td"); - const manage = document.createElement("td"); + tr.classList.add("menu-item"); + const td = document.createElement("td"); + const openTabs = identity.numberOfOpenTabs || "" ; - tr.classList.add("container-panel-row"); - - context.classList.add("userContext-wrapper", "open-newtab", "clickable", "firstTabindex"); - manage.classList.add("show-tabs", "pop-button"); - manage.setAttribute("title", `View ${identity.name} container`); - context.setAttribute("tabindex", "0"); - context.setAttribute("title", `Create ${identity.name} tab`); - context.innerHTML = escaped` -
+ td.innerHTML = escaped` + -
`; - context.querySelector(".container-name").textContent = identity.name; - manage.innerHTML = ""; + ${identity.name} + + ${openTabs} + + Container Info + + `; fragment.appendChild(tr); - tr.appendChild(context); + tr.appendChild(td); - if (hasTabs) { - tr.appendChild(manage); - } - - Logic.addEnterHandler(tr, async (e) => { - if (e.target.matches(".open-newtab") - || e.target.parentNode.matches(".open-newtab") - || e.type === "keydown") { - try { - browser.tabs.create({ - cookieStoreId: identity.cookieStoreId - }); - window.close(); - } catch (e) { - window.close(); - } - } else if (hasTabs) { - Logic.showPanel(P_CONTAINER_INFO, identity); - } + Logic.addEnterHandler(tr, () => { + Logic.showPanel(P_CONTAINER_INFO, identity); }); }); - const list = document.querySelector(".identities-list tbody"); + const list = document.querySelector("#identities-list"); list.innerHTML = ""; list.appendChild(fragment); @@ -796,14 +729,6 @@ Logic.registerPanel(P_CONTAINERS_LIST, { document.addEventListener("mousedown", () => { document.removeEventListener("focus", focusHandler); }); - /* If no container is present disable the Edit Containers button */ - const editContainer = document.querySelector("#edit-containers-link"); - if (Logic.identities().length === 0) { - editContainer.classList.add("disable-edit-containers"); - } else { - editContainer.classList.remove("disable-edit-containers"); - } - return Promise.resolve(); }, }); @@ -955,68 +880,100 @@ Logic.registerPanel(P_CONTAINER_INFO, { }, }); -// P_CONTAINERS_EDIT: Makes the list editable. +// P_CONTAINER_PICKER: Makes the list editable. // ---------------------------------------------------------------------------- -Logic.registerPanel(P_CONTAINERS_EDIT, { - panelSelector: "#edit-containers-panel", +Logic.registerPanel(P_CONTAINER_PICKER, { + panelSelector: "#container-picker-panel", // This method is called when the object is registered. initialize() { - Logic.addEnterHandler(document.querySelector("#exit-edit-mode-link"), () => { - Logic.showPanel(P_CONTAINERS_LIST); - }); + // Logic.addEnterHandler(document.querySelector("#exit-edit-mode-link"), () => { + // Logic.showPanel(P_CONTAINERS_LIST); + // }); }, // This method is called when the panel is shown. prepare() { const fragment = document.createDocumentFragment(); + let pickedFunction; + switch (Logic.pickerType) { + case OPEN_NEW_CONTAINER_PICKER: + pickedFunction = function (identity) { + try { + browser.tabs.create({ + cookieStoreId: identity.cookieStoreId + }); + window.close(); + } catch (e) { + window.close(); + } + }; + break; + case MANAGE_CONTAINERS_PICKER: + pickedFunction = function (identity) { + Logic.showPanel(P_CONTAINER_EDIT, identity); + }; + break; + case REOPEN_IN_CONTAINER: + pickedFunction = function (identity) { + try { + browser.tabs.create({ + cookieStoreId: identity.cookieStoreId + }); + window.close(); + } catch (e) { + window.close(); + } + }; + break; + case ALWAYS_OPEN_IN_PICKER: + default: + pickedFunction = async function (identity) { + const currentTab = await Logic.currentTab(); + console.log(identity.cookieStoreId) + console.log(identity) + Logic.setOrRemoveAssignment( + currentTab.id, + currentTab.url, + identity.cookieStoreId, + false + ); + window.close(); + }; + break; + } + Logic.identities().forEach(identity => { const tr = document.createElement("tr"); - fragment.appendChild(tr); - tr.classList.add("container-panel-row"); - tr.innerHTML = escaped` - -
-
-
+ tr.classList.add("menu-item"); + const td = document.createElement("td"); + + td.innerHTML = escaped` + + ${identity.name}`; + fragment.appendChild(tr); - Logic.addEnterHandler(tr, e => { - if (e.target.matches(".edit-container-icon") || e.target.parentNode.matches(".edit-container-icon")) { - Logic.showPanel(P_CONTAINER_EDIT, identity); - } else if (e.target.matches(".delete-container-icon") || e.target.parentNode.matches(".delete-container-icon")) { - Logic.showPanel(P_CONTAINER_DELETE, identity); - } + tr.appendChild(td); + + Logic.addEnterHandler(tr, () => { + pickedFunction(identity); }); }); - const list = document.querySelector("#edit-identities-list"); + const list = document.querySelector("#picker-identities-list"); list.innerHTML = ""; list.appendChild(fragment); return Promise.resolve(null); - }, + } }); // P_CONTAINER_EDIT: Editor for a container. diff --git a/src/popup.html b/src/popup.html index 813a02d..dca1948 100644 --- a/src/popup.html +++ b/src/popup.html @@ -115,34 +115,79 @@ Done
-
-
-

Current Tab

-
- + @@ -170,19 +215,26 @@
-
-
-

Edit Containers

-
-
- - +
+

+ Multi-Account Containers +

+
+
+
+ + +
-
From 97d4c46a4e1c6f5ce36667fd6dfc61b580511542 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 13 Feb 2020 16:21:29 -0600 Subject: [PATCH 02/29] Added Facebook Container Fence icon. Fixes #1425 --- src/css/popup.css | 4 ++++ src/img/usercontext.svg | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/css/popup.css b/src/css/popup.css index 2dc9bc9..36f9a52 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -206,6 +206,10 @@ table { --identity-icon: url("/img/usercontext.svg#chill"); } +[data-identity-icon="fence"] { + --identity-icon: url("/img/usercontext.svg#fence"); +} + #current-tab [data-identity-icon="default-tab"] { background: center center no-repeat url("/img/blank-tab.svg"); fill: currentColor; diff --git a/src/img/usercontext.svg b/src/img/usercontext.svg index f58067a..fb48e4a 100644 --- a/src/img/usercontext.svg +++ b/src/img/usercontext.svg @@ -13,6 +13,7 @@ display: none; } + + + + + + + + + From fbba6beee29e52b8296b0ace9af83b1cf2e8ae23 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Thu, 13 Feb 2020 23:56:28 -0600 Subject: [PATCH 03/29] testing keyboard shortcuts --- src/js/background/backgroundLogic.js | 12 +++++++++++- src/manifest.json | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index d68e51e..7aba5f6 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -331,4 +331,14 @@ const backgroundLogic = { cookieStoreId(userContextId) { return `firefox-container-${userContextId}`; } -}; \ No newline at end of file +}; + +browser.commands.onCommand.addListener(function (command) { + if (command === "open_container_2") { + browser.tabs.create({cookieStoreId: "firefox-container-2"}); + } + if (command === "open_container_1") { + console.log("Toggling the feature!"); + browser.tabs.create({cookieStoreId: "firefox-container-1"}); + } +}); \ No newline at end of file diff --git a/src/manifest.json b/src/manifest.json index a18a44c..57402c5 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -39,6 +39,18 @@ "mac": "MacCtrl+Period" }, "description": "Open containers panel" + }, + "open_container_1": { + "suggested_key": { + "default": "Ctrl+Shift+1" + }, + "description": "Container Shortcut 1" + }, + "open_container_2": { + "suggested_key": { + "default": "Ctrl+Shift+2" + }, + "description": "Container Shortcut 2" } }, "browser_action": { From 1870ce08bc91173c37cb0dbdc54ca70774cf9594 Mon Sep 17 00:00:00 2001 From: Kendall Werts Date: Fri, 14 Feb 2020 00:08:37 -0600 Subject: [PATCH 04/29] Page action assigns site to a container and simultaneously reopens site in container. --- .eslintrc.js | 2 +- src/js/.eslintrc.js | 3 +- src/js/background/assignManager.js | 1 + src/js/background/messageHandler.js | 10 ++ src/js/pageAction.js | 51 +++++++++ src/js/popup.js | 157 ++++++++-------------------- src/js/utils.js | 86 ++++++++++++++- src/manifest.json | 8 ++ src/pageActionPopup.html | 34 ++++++ 9 files changed, 235 insertions(+), 117 deletions(-) create mode 100644 src/js/pageAction.js create mode 100644 src/pageActionPopup.html diff --git a/.eslintrc.js b/.eslintrc.js index 1b0e906..f52aeb7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -46,7 +46,7 @@ module.exports = { "error", { "escape": { - "taggedTemplates": ["escaped"] + "taggedTemplates": ["escaped", "Utils.escaped"] } } ], diff --git a/src/js/.eslintrc.js b/src/js/.eslintrc.js index 11cd71a..4941e75 100644 --- a/src/js/.eslintrc.js +++ b/src/js/.eslintrc.js @@ -8,6 +8,7 @@ module.exports = { "backgroundLogic": true, "identityState": true, "messageHandler": true, - "sync": true + "sync": true, + "Utils": true } }; diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index 9dd6e88..861b928 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -474,6 +474,7 @@ window.assignManager = { }, async _setOrRemoveAssignment(tabId, pageUrl, userContextId, remove) { + console.log(userContextId) let actionName; // https://github.com/mozilla/testpilot-containers/issues/626 diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js index f4236f1..3e93802 100644 --- a/src/js/background/messageHandler.js +++ b/src/js/background/messageHandler.js @@ -73,6 +73,16 @@ const messageHandler = { case "exemptContainerAssignment": response = assignManager._exemptTab(m); break; + case "reloadInContainer": + response = assignManager.reloadPageInContainer( + m.url, + m.currentUserContextId, + m.newUserContextId, + m.tabIndex, + m.active, + true + ); + break; } return response; }); diff --git a/src/js/pageAction.js b/src/js/pageAction.js new file mode 100644 index 0000000..9242f24 --- /dev/null +++ b/src/js/pageAction.js @@ -0,0 +1,51 @@ +async function init() { + const fragment = document.createDocumentFragment(); + + const identities = await browser.contextualIdentities.query({}); + + identities.forEach(identity => { + const tr = document.createElement("tr"); + tr.classList.add("menu-item"); + const td = document.createElement("td"); + + td.innerHTML = Utils.escaped` + + ${identity.name}`; + + fragment.appendChild(tr); + + tr.appendChild(td); + + Utils.addEnterHandler(tr, async () => { + const currentTab = await Utils.currentTab(); + const assignedUserContextId = Utils.userContextId(identity.cookieStoreId); + Utils.setOrRemoveAssignment( + currentTab.id, + currentTab.url, + assignedUserContextId, + false + ); + console.log(currentTab); + Utils.reloadInContainer( + currentTab.url, + false, + assignedUserContextId, + currentTab.index + 1, + currentTab.active + ); + window.close(); + }); + }); + + const list = document.querySelector("#picker-identities-list"); + + list.innerHTML = ""; + list.appendChild(fragment); +} + +init(); diff --git a/src/js/popup.js b/src/js/popup.js index 1d4fce6..e6f22e8 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -30,41 +30,6 @@ const P_CONTAINER_EDIT = "containerEdit"; const P_CONTAINER_DELETE = "containerDelete"; const P_CONTAINERS_ACHIEVEMENT = "containersAchievement"; -/** - * Escapes any occurances of &, ", <, > or / with XML entities. - * - * @param {string} str - * The string to escape. - * @return {string} The escaped string. - */ -function escapeXML(str) { - const replacements = { "&": "&", "\"": """, "'": "'", "<": "<", ">": ">", "/": "/" }; - return String(str).replace(/[&"'<>/]/g, m => replacements[m]); -} - -/** - * A tagged template function which escapes any XML metacharacters in - * interpolated values. - * - * @param {Array} strings - * An array of literal strings extracted from the templates. - * @param {Array} values - * An array of interpolated values extracted from the template. - * @returns {string} - * The result of the escaped values interpolated with the literal - * strings. - */ -function escaped(strings, ...values) { - const result = []; - - for (const [i, string] of strings.entries()) { - result.push(string); - if (i < values.length) - result.push(escapeXML(values[i])); - } - - return result.join(""); -} async function getExtensionInfo() { const manifestPath = browser.extension.getURL("manifest.json"); @@ -201,31 +166,6 @@ const Logic = { } }, - addEnterHandler(element, handler) { - element.addEventListener("click", (e) => { - handler(e); - }); - element.addEventListener("keydown", (e) => { - if (e.keyCode === 13) { - e.preventDefault(); - handler(e); - } - }); - }, - - userContextId(cookieStoreId = "") { - const userContextId = cookieStoreId.replace("firefox-container-", ""); - return (userContextId !== cookieStoreId) ? Number(userContextId) : false; - }, - - async currentTab() { - const activeTabs = await browser.tabs.query({ active: true, windowId: browser.windows.WINDOW_ID_CURRENT }); - if (activeTabs.length > 0) { - return activeTabs[0]; - } - return false; - }, - async numTabs() { const activeTabs = await browser.tabs.query({ windowId: browser.windows.WINDOW_ID_CURRENT }); return activeTabs.length; @@ -338,7 +278,7 @@ const Logic = { currentUserContextId() { const identity = Logic.currentIdentity(); - return Logic.userContextId(identity.cookieStoreId); + return Utils.userContextId(identity.cookieStoreId); }, currentCookieStoreId() { @@ -374,16 +314,6 @@ const Logic = { }); }, - setOrRemoveAssignment(tabId, url, userContextId, value) { - return browser.runtime.sendMessage({ - method: "setOrRemoveAssignment", - tabId, - url, - userContextId, - value - }); - }, - generateIdentityName() { const defaultName = "Container #"; const ids = []; @@ -423,7 +353,7 @@ Logic.registerPanel(P_ONBOARDING_1, { initialize() { // Let's move to the next panel. [...document.querySelectorAll(".onboarding-start-button")].forEach(startElement => { - Logic.addEnterHandler(startElement, async () => { + Utils.addEnterHandler(startElement, async () => { await Logic.setOnboardingStage(1); Logic.showPanel(P_ONBOARDING_2); }); @@ -447,7 +377,7 @@ Logic.registerPanel(P_ONBOARDING_2, { initialize() { // Let's move to the containers list panel. [...document.querySelectorAll(".onboarding-next-button")].forEach(nextElement => { - Logic.addEnterHandler(nextElement, async () => { + Utils.addEnterHandler(nextElement, async () => { await Logic.setOnboardingStage(2); Logic.showPanel(P_ONBOARDING_3); }); @@ -471,7 +401,7 @@ Logic.registerPanel(P_ONBOARDING_3, { initialize() { // Let's move to the containers list panel. [...document.querySelectorAll(".onboarding-almost-done-button")].forEach(almostElement => { - Logic.addEnterHandler(almostElement, async () => { + Utils.addEnterHandler(almostElement, async () => { await Logic.setOnboardingStage(3); Logic.showPanel(P_ONBOARDING_4); }); @@ -493,7 +423,7 @@ Logic.registerPanel(P_ONBOARDING_4, { // This method is called when the object is registered. initialize() { // Let's move to the containers list panel. - Logic.addEnterHandler(document.querySelector("#onboarding-done-button"), async () => { + Utils.addEnterHandler(document.querySelector("#onboarding-done-button"), async () => { await Logic.setOnboardingStage(4); Logic.showPanel(P_ONBOARDING_5); }); @@ -514,7 +444,7 @@ Logic.registerPanel(P_ONBOARDING_5, { // This method is called when the object is registered. initialize() { // Let's move to the containers list panel. - Logic.addEnterHandler(document.querySelector("#onboarding-longpress-button"), async () => { + Utils.addEnterHandler(document.querySelector("#onboarding-longpress-button"), async () => { await Logic.setOnboardingStage(5); Logic.showPanel(P_ONBOARDING_6); }); @@ -535,7 +465,7 @@ Logic.registerPanel(P_ONBOARDING_6, { // This method is called when the object is registered. initialize() { // Let's move to the containers list panel. - Logic.addEnterHandler(document.querySelector("#start-sync-button"), async () => { + Utils.addEnterHandler(document.querySelector("#start-sync-button"), async () => { await Logic.setOnboardingStage(6); await browser.storage.local.set({syncEnabled: true}); await browser.runtime.sendMessage({ @@ -543,7 +473,7 @@ Logic.registerPanel(P_ONBOARDING_6, { }); Logic.showPanel(P_ONBOARDING_7); }); - Logic.addEnterHandler(document.querySelector("#no-sync"), async () => { + Utils.addEnterHandler(document.querySelector("#no-sync"), async () => { await Logic.setOnboardingStage(7); await browser.storage.local.set({syncEnabled: false}); await browser.runtime.sendMessage({ @@ -568,14 +498,14 @@ Logic.registerPanel(P_ONBOARDING_7, { // This method is called when the object is registered. initialize() { // Let's move to the containers list panel. - Logic.addEnterHandler(document.querySelector("#sign-in"), async () => { + Utils.addEnterHandler(document.querySelector("#sign-in"), async () => { browser.tabs.create({ url: "https://accounts.firefox.com/?service=sync&action=email&context=fx_desktop_v3&entrypoint=multi-account-containers&utm_source=addon&utm_medium=panel&utm_campaign=container-sync", }); await Logic.setOnboardingStage(7); Logic.showPanel(P_CONTAINERS_LIST); }); - Logic.addEnterHandler(document.querySelector("#no-sign-in"), async () => { + Utils.addEnterHandler(document.querySelector("#no-sign-in"), async () => { await Logic.setOnboardingStage(7); Logic.showPanel(P_CONTAINERS_LIST); }); @@ -594,21 +524,21 @@ Logic.registerPanel(P_CONTAINERS_LIST, { // This method is called when the object is registered. async initialize() { - Logic.addEnterHandler(document.querySelector("#manage-containers-link"), (e) => { + Utils.addEnterHandler(document.querySelector("#manage-containers-link"), (e) => { if (!e.target.classList.contains("disable-edit-containers")) { Logic.showPanel(P_CONTAINER_PICKER, null, MANAGE_CONTAINERS_PICKER); } }); - Logic.addEnterHandler(document.querySelector("#open-new-tab-in"), () => { + Utils.addEnterHandler(document.querySelector("#open-new-tab-in"), () => { Logic.showPanel(P_CONTAINER_PICKER, null, OPEN_NEW_CONTAINER_PICKER); }); - Logic.addEnterHandler(document.querySelector("#reopen-site-in"), () => { + Utils.addEnterHandler(document.querySelector("#reopen-site-in"), () => { Logic.showPanel(P_CONTAINER_PICKER, null, REOPEN_IN_CONTAINER); }); - Logic.addEnterHandler(document.querySelector("#always-open-in"), () => { + Utils.addEnterHandler(document.querySelector("#always-open-in"), () => { Logic.showPanel(P_CONTAINER_PICKER, null, ALWAYS_OPEN_IN_PICKER); }); - Logic.addEnterHandler(document.querySelector("#sort-containers-link"), async () => { + Utils.addEnterHandler(document.querySelector("#sort-containers-link"), async () => { try { await browser.runtime.sendMessage({ method: "sortTabs" @@ -685,7 +615,7 @@ Logic.registerPanel(P_CONTAINERS_LIST, { const td = document.createElement("td"); const openTabs = identity.numberOfOpenTabs || "" ; - td.innerHTML = escaped` + td.innerHTML = Utils.escaped`