diff --git a/package.json b/package.json index 74113d1..988a762 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "stylelint": "^13.5.0", "stylelint-config-standard": "^20.0.0", "stylelint-order": "^4.0.0", - "web-ext": "^2.9.3", + "web-ext": "^5.4.1", "webextensions-jsdom": "^1.2.1" }, "homepage": "https://github.com/mozilla/multi-account-containers#readme", diff --git a/src/css/confirm-page.css b/src/css/confirm-page.css index 113ffef..b954443 100644 --- a/src/css/confirm-page.css +++ b/src/css/confirm-page.css @@ -18,7 +18,6 @@ main { button .container-name, #current-container-name { font-weight: bold; - text-transform: capitalize; } @media only screen and (max-width: 1300px) { diff --git a/src/css/popup.css b/src/css/popup.css index 543936e..4dfb8dc 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -691,6 +691,10 @@ h3.title { max-inline-size: 300px; } +.menu-item.drag-over td { + border-block-start: 2px solid var(--text-normal-color); +} + .disabled-menu-item { color: grey; cursor: default; @@ -931,3 +935,115 @@ tr > td > .trash-button { tr:hover > td > .trash-button { display: block; } + +.move-button { + cursor: move; + display: inline-block; + height: 100%; + inline-size: 16px; + margin-block-end: 4px; + margin-block-start: 4px; + margin-inline-end: 10px; + margin-inline-start: auto; + text-align: center; +} + +.move-button > img { + height: 16px; +} + +@media (prefers-color-scheme: dark) { + :root { + --title-text-color: #fff; + --text-normal-color: #f9f9fa; + --text-heading-color: #fff; + } + + html { + background-color: #4a4a4a; + } + + body { + color: #fff; + + --hr-grey: #38383d; + --text-grey: #f9f9fa; + } + + h3.title { + color: #fff; + } + + .bottom-btn { + background-color: #737373; + border: solid 1px #737373; + } + + .btn-return.arrow-left { + background-color: transparent; + } + + .onboarding-title, + .delete-container-confirm-title { + color: #ededf0; + } + + input { + border: solid 1px #737373; + } + + #edit-container-panel-name-input { + background-color: #38383d; + color: #fff; + } + + .delete-container { + background-color: #4a4a4a; + } + + .delete-btn { + background-color: #737373; + color: #f9f9fa; + } + + .cancel-button, + .grey-button { + background-color: #737373; + color: #fff; + } + + .button.secondary:hover, + .button.secondary:focus { + background-color: #676767; + } + + .panel-footer { + border-block-end: solid 1px #4a4a4a; + } + + img.menu-icon, + .menu-icon > img, + .menu-arrow > img, + .info-icon > img, + .btn-return.arrow-left { + filter: invert(1); + } + + #edit-sites-assigned .menu-icon, + #container-info-table .menu-icon { + filter: invert(0); + } + + .truncate-text::after { + background: #4a4a4a; + mask-image: linear-gradient(to right, transparent, #4a4a4a 70%); + } + + [data-identity-color="grey"] { + --identity-icon-color: #ededf0; + } + + [type="radio"]:checked + [data-identity-color="grey"] { + --identity-icon-color: #616161; + } +} diff --git a/src/img/container-move.svg b/src/img/container-move.svg new file mode 100644 index 0000000..ee4fd70 --- /dev/null +++ b/src/img/container-move.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/js/popup.js b/src/js/popup.js index c242e12..6c0d7ab 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -10,6 +10,8 @@ const DEFAULT_ICON = "circle"; const NEW_CONTAINER_ID = "new"; const ONBOARDING_STORAGE_KEY = "onboarding-stage"; +const CONTAINER_ORDER_STORAGE_KEY = "container-order"; +const CONTAINER_DRAG_DATA_TYPE = "firefox-container"; // List of panels const P_ONBOARDING_1 = "onboarding1"; @@ -192,16 +194,29 @@ const Logic = { elementToEnable.classList.remove("disabled-menu-item"); }, + async saveContainerOrder(rows) { + const containerOrder = {}; + rows.forEach((node, index) => { + return containerOrder[node.dataset.containerId] = index; + }); + await browser.storage.local.set({ + [CONTAINER_ORDER_STORAGE_KEY]: containerOrder + }); + }, + async refreshIdentities() { - const [identities, state] = await Promise.all([ + const [identities, state, containerOrderStorage] = await Promise.all([ browser.contextualIdentities.query({}), browser.runtime.sendMessage({ method: "queryIdentitiesState", message: { windowId: browser.windows.WINDOW_ID_CURRENT } - }) + }), + browser.storage.local.get([CONTAINER_ORDER_STORAGE_KEY]) ]); + const containerOrder = + containerOrderStorage && containerOrderStorage[CONTAINER_ORDER_STORAGE_KEY]; this._identities = identities.map((identity) => { const stateObject = state[identity.cookieStoreId]; if (stateObject) { @@ -211,8 +226,11 @@ const Logic = { identity.numberOfOpenTabs = stateObject.numberOfOpenTabs; identity.isIsolated = stateObject.isIsolated; } + if (containerOrder) { + identity.order = containerOrder[identity.cookieStoreId]; + } return identity; - }); + }).sort((i1, i2) => i1.order - i2.order); }, getPanelSelector(panel) { @@ -1010,12 +1028,59 @@ Logic.registerPanel(MANAGE_CONTAINERS_PICKER, { data-identity-color="${identity.color}"> - ${identity.name}`; + ${identity.name} + + + `; fragment.appendChild(tr); tr.appendChild(td); + tr.draggable = true; + tr.dataset.containerId = identity.cookieStoreId; + tr.addEventListener("dragstart", (e) => { + e.dataTransfer.setData(CONTAINER_DRAG_DATA_TYPE, identity.cookieStoreId); + }); + tr.addEventListener("dragover", (e) => { + if (e.dataTransfer.types.includes(CONTAINER_DRAG_DATA_TYPE)) { + tr.classList.add("drag-over"); + e.preventDefault(); + } + }); + tr.addEventListener("dragenter", (e) => { + if (e.dataTransfer.types.includes(CONTAINER_DRAG_DATA_TYPE)) { + e.preventDefault(); + tr.classList.add("drag-over"); + } + }); + tr.addEventListener("dragleave", (e) => { + if (e.dataTransfer.types.includes(CONTAINER_DRAG_DATA_TYPE)) { + e.preventDefault(); + tr.classList.remove("drag-over"); + } + }); + tr.addEventListener("drop", async (e) => { + e.preventDefault(); + const parent = tr.parentNode; + const containerId = e.dataTransfer.getData(CONTAINER_DRAG_DATA_TYPE); + let droppedElement; + parent.childNodes.forEach((node) => { + if (node.dataset.containerId === containerId) { + droppedElement = node; + } + }); + if (droppedElement && droppedElement !== tr) { + tr.classList.remove("drag-over"); + parent.insertBefore(droppedElement, tr); + await Logic.saveContainerOrder(parent.childNodes); + await Logic.refreshIdentities(); + } + }); + Utils.addEnterHandler(tr, () => { pickedFunction(identity); });