diff --git a/package.json b/package.json index 746a84f..8c2d546 100644 --- a/package.json +++ b/package.json @@ -2,20 +2,19 @@ "name": "testpilot-containers", "title": "Multi-Account Containers", "description": "Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.", - "version": "6.0.0", + "version": "6.0.1", "author": "Andrea Marchesini, Luke Crouch and Jonathan Kingston", "bugs": { "url": "https://github.com/mozilla/multi-account-containers/issues" }, "dependencies": {}, "devDependencies": { - "addons-linter": "^0.15.14", + "addons-linter": "^1.3.2", "chai": "^4.1.2", - "deploy-txp": "^1.0.7", "eslint": "^3.17.1", "eslint-plugin-no-unsanitized": "^2.0.0", "eslint-plugin-promise": "^3.4.0", - "htmllint-cli": "^0.0.5", + "htmllint-cli": "0.0.7", "jsdom": "^11.6.2", "json": "^9.0.6", "mocha": "^5.0.0", @@ -36,7 +35,6 @@ }, "scripts": { "build": "npm test && cd src && web-ext build --overwrite-dest", - "deploy": "deploy-txp", "lint": "npm-run-all lint:*", "lint:addon": "addons-linter src --self-hosted", "lint:css": "stylelint src/css/*.css", diff --git a/src/css/popup.css b/src/css/popup.css index af78306..6f9e64a 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -45,6 +45,7 @@ body { --small-text-size: 0.833rem; /* 10px */ --small-radius: 3px; --icon-button-size: calc(calc(var(--block-line-separation-size) * 2) + 1.66rem); /* 20px */ + --inactive-opacity: 0.3; } @media (min-resolution: 1dppx) { @@ -537,7 +538,7 @@ span ~ .panel-header-text { } #current-tab > label > input:checked { - background-image: url("chrome://global/skin/in-content/check.svg#check-native"); + background-image: url("/img/check.svg"); background-position: -1px -1px; background-size: var(--icon-size); } @@ -578,6 +579,11 @@ span ~ .panel-header-text { max-inline-size: 204px; } +.disable-edit-containers { + opacity: var(--inactive-opacity); + pointer-events: none; +} + .userContext-wrapper { align-items: center; display: flex; diff --git a/src/img/blank-favicon.svg b/src/img/blank-favicon.svg new file mode 100644 index 0000000..c2393b6 --- /dev/null +++ b/src/img/blank-favicon.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/img/check.svg b/src/img/check.svg new file mode 100644 index 0000000..bcbcfc0 --- /dev/null +++ b/src/img/check.svg @@ -0,0 +1,6 @@ + + + + diff --git a/src/js/popup.js b/src/js/popup.js index a9e3d26..18eec68 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -162,7 +162,7 @@ const Logic = { async clearBrowserActionBadge() { const extensionInfo = await getExtensionInfo(); const storage = await browser.storage.local.get({browserActionBadgesClicked: []}); - browser.browserAction.setBadgeBackgroundColor({color: ""}); + browser.browserAction.setBadgeBackgroundColor({color: null}); browser.browserAction.setBadgeText({text: ""}); storage.browserActionBadgesClicked.push(extensionInfo.version); // use set and spread to create a unique array @@ -212,6 +212,27 @@ const Logic = { return false; }, + async numTabs() { + const activeTabs = await browser.tabs.query({windowId: browser.windows.WINDOW_ID_CURRENT}); + return activeTabs.length; + }, + + _disableMoveTabs(message) { + const moveTabsEl = document.querySelector("#container-info-movetabs"); + const fragment = document.createDocumentFragment(); + const incompatEl = document.createElement("div"); + + moveTabsEl.classList.remove("clickable"); + moveTabsEl.setAttribute("title", message); + + fragment.appendChild(incompatEl); + incompatEl.setAttribute("id", "container-info-movetabs-incompat"); + incompatEl.textContent = message; + incompatEl.classList.add("container-info-tab-row"); + + moveTabsEl.parentNode.insertBefore(fragment, moveTabsEl.nextSibling); + }, + async refreshIdentities() { const [identities, state] = await Promise.all([ browser.contextualIdentities.query({}), @@ -485,8 +506,10 @@ Logic.registerPanel(P_CONTAINERS_LIST, { Logic.showPanel(P_CONTAINER_EDIT, { name: Logic.generateIdentityName() }); }); - Logic.addEnterHandler(document.querySelector("#edit-containers-link"), () => { - Logic.showPanel(P_CONTAINERS_EDIT); + Logic.addEnterHandler(document.querySelector("#edit-containers-link"), (e) => { + if (!e.target.classList.contains("disable-edit-containers")){ + Logic.showPanel(P_CONTAINERS_EDIT); + } }); Logic.addEnterHandler(document.querySelector("#sort-containers-link"), async function () { @@ -666,6 +689,13 @@ 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(); }, @@ -698,37 +728,31 @@ Logic.registerPanel(P_CONTAINER_INFO, { }); // Check if the user has incompatible add-ons installed + let incompatible = false; try { - const incompatible = await browser.runtime.sendMessage({ + incompatible = await browser.runtime.sendMessage({ method: "checkIncompatibleAddons" }); - const moveTabsEl = document.querySelector("#container-info-movetabs"); - if (incompatible) { - const fragment = document.createDocumentFragment(); - const incompatEl = document.createElement("div"); - - moveTabsEl.classList.remove("clickable"); - moveTabsEl.setAttribute("title", "Moving container tabs is incompatible with Pulse, PageShot, and SnoozeTabs."); - - fragment.appendChild(incompatEl); - incompatEl.setAttribute("id", "container-info-movetabs-incompat"); - incompatEl.textContent = "Incompatible with other Experiments."; - incompatEl.classList.add("container-info-tab-row"); - - moveTabsEl.parentNode.insertBefore(fragment, moveTabsEl.nextSibling); - } else { - Logic.addEnterHandler(moveTabsEl, async function () { - await browser.runtime.sendMessage({ - method: "moveTabsToWindow", - windowId: browser.windows.WINDOW_ID_CURRENT, - cookieStoreId: Logic.currentIdentity().cookieStoreId, - }); - window.close(); - }); - } } catch (e) { throw new Error("Could not check for incompatible add-ons."); } + const moveTabsEl = document.querySelector("#container-info-movetabs"); + const numTabs = await Logic.numTabs(); + if (incompatible) { + Logic._disableMoveTabs("Moving container tabs is incompatible with Pulse, PageShot, and SnoozeTabs."); + return; + } else if (numTabs === 1) { + Logic._disableMoveTabs("Cannot move a tab from a single-tab window."); + return; + } + Logic.addEnterHandler(moveTabsEl, async function () { + await browser.runtime.sendMessage({ + method: "moveTabsToWindow", + windowId: browser.windows.WINDOW_ID_CURRENT, + cookieStoreId: Logic.currentIdentity().cookieStoreId, + }); + window.close(); + }); }, // This method is called when the panel is shown. @@ -1001,6 +1025,11 @@ Logic.registerPanel(P_CONTAINER_EDIT, { document.querySelector("#edit-container-panel-name-input").value = identity.name || ""; document.querySelector("#edit-container-panel-usercontext-input").value = userContextId || NEW_CONTAINER_ID; + const containerName = document.querySelector("#edit-container-panel-name-input"); + window.requestAnimationFrame(() => { + containerName.select(); + containerName.focus(); + }); [...document.querySelectorAll("[name='container-color']")].forEach(colorInput => { colorInput.checked = colorInput.value === identity.color; }); diff --git a/src/js/utils.js b/src/js/utils.js index 5d5046b..804e9d9 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -1,4 +1,4 @@ -const DEFAULT_FAVICON = "moz-icon://goat?size=16"; +const DEFAULT_FAVICON = "/img/blank-favicon.svg"; // TODO use export here instead of globals window.Utils = { diff --git a/src/manifest.json b/src/manifest.json index f3fa049..d624d32 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Firefox Multi-Account Containers", - "version": "6.0.0", + "version": "6.0.1", "description": "Multi-Account Containers helps you keep all the parts of your online life contained in different tabs. Custom labels and color-coded tabs help keep different activities — like online shopping, travel planning, or checking work email — separate.", "icons": {