From 977617c1329f604722369c20b148e8081be880f7 Mon Sep 17 00:00:00 2001 From: George Vlachos Date: Sun, 24 Feb 2019 11:53:44 +0200 Subject: [PATCH] added code to sort the containers list including icons (feathericons.com) --- src/css/popup.css | 28 ++++++- src/img/chevron-down.svg | 1 + src/img/chevron-up.svg | 1 + src/js/popup.js | 157 ++++++++++++++++++++++++--------------- src/popup.html | 5 ++ 5 files changed, 129 insertions(+), 63 deletions(-) create mode 100644 src/img/chevron-down.svg create mode 100644 src/img/chevron-up.svg diff --git a/src/css/popup.css b/src/css/popup.css index f2423a3..67271fb 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -40,6 +40,7 @@ body { --block-url-label-size: 2rem; /* 24px */ --inline-start-size: 1.66rem; /* 20px */ --inline-button-size: 5.833rem; /* 70px */ + --inline-button-large-size: 11.666rem; /* 140px */ --icon-size: 1.166rem; /* 14px */ --small-text-size: 0.833rem; /* 10px */ @@ -308,6 +309,16 @@ table { transform: rotate(180deg); } +.up-arrow-img { + block-size: 16px; + inline-size: 16px; +} + +.down-arrow-img { + block-size: 16px; + inline-size: 16px; +} + /* Onboarding styles */ .onboarding * { text-align: center; @@ -452,7 +463,8 @@ manage things like container crud */ margin-inline-start: var(--inline-item-space-size); } -#container-panel #sort-containers-link { +#container-panel #sort-containers-link, +#container-panel #sort-containers-list-link { align-items: center; block-size: var(--block-url-label-size); border: 1px solid #d8d8d8; @@ -460,13 +472,23 @@ manage things like container crud */ 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 { + inline-size: var(--inline-button-size); +} + +#container-panel #sort-containers-list-link { + inline-size: var(--inline-button-large-size); + margin-left: 1rem; +} + #container-panel #sort-containers-link:hover, -#container-panel #sort-containers-link:focus { +#container-panel #sort-containers-link:focus, +#container-panel #sort-containers-list-link:hover, +#container-panel #sort-containers-list-link:focus { background: #f2f2f2; } diff --git a/src/img/chevron-down.svg b/src/img/chevron-down.svg new file mode 100644 index 0000000..278c6a3 --- /dev/null +++ b/src/img/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/img/chevron-up.svg b/src/img/chevron-up.svg new file mode 100644 index 0000000..4eb5ecc --- /dev/null +++ b/src/img/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/js/popup.js b/src/js/popup.js index a672017..3e10a12 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -235,6 +235,23 @@ const Logic = { moveTabsEl.parentNode.insertBefore(fragment, moveTabsEl.nextSibling); }, + async sortContainerList(list) { + const update = [...list]; + const result = await browser.storage.local.get({containerSortOrder: null}); + const upArrowElement = document.querySelector("#sort-containers-list-link .up-arrow-img"); + const downArrowElement = document.querySelector("#sort-containers-list-link .down-arrow-img"); + if (result.containerSortOrder === "asc") { + update.sort((a, b) => (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1); + downArrowElement.style.display = "inline"; + upArrowElement.style.display = "none"; + } else if (result.containerSortOrder === "desc") { + update.sort((a, b) => (a.name.toLowerCase() < b.name.toLowerCase()) ? 1 : -1); + upArrowElement.style.display = "inline"; + downArrowElement.style.display = "none"; + } + return update; + }, + async refreshIdentities() { const [identities, state] = await Promise.all([ browser.contextualIdentities.query({}), @@ -245,7 +262,7 @@ const Logic = { } }) ]); - this._identities = identities.map((identity) => { + const identitiesList = identities.map((identity) => { const stateObject = state[identity.cookieStoreId]; if (stateObject) { identity.hasOpenTabs = stateObject.hasOpenTabs; @@ -255,6 +272,8 @@ const Logic = { } return identity; }); + this._identities = await this.sortContainerList(identitiesList); + return this._identities; }, getPanelSelector(panel) { @@ -382,6 +401,63 @@ const Logic = { } } }, + + createContainerList(listParentElement) { + const fragment = document.createDocumentFragment(); + + 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("container-panel-row"); + + context.classList.add("userContext-wrapper", "open-newtab", "clickable"); + manage.classList.add("show-tabs", "pop-button"); + manage.title = escaped`View ${identity.name} container`; + context.setAttribute("tabindex", "0"); + context.title = escaped`Create ${identity.name} tab`; + context.innerHTML = escaped` +
+
+
+
+
`; + context.querySelector(".container-name").textContent = identity.name; + manage.innerHTML = ""; + + fragment.appendChild(tr); + + tr.appendChild(context); + + 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); + } + }); + }); + + listParentElement.innerHTML = ""; + listParentElement.appendChild(fragment); + } }; // P_ONBOARDING_1: First page for Onboarding. @@ -527,6 +603,20 @@ Logic.registerPanel(P_CONTAINERS_LIST, { } }); + Logic.addEnterHandler(document.querySelector("#sort-containers-list-link"), async () => { + try { + const toggle = current => current === "asc" ? "desc": "asc"; + let result = await browser.storage.local.get({containerSortOrder: null}); + result = {containerSortOrder: toggle(result.containerSortOrder)}; + await browser.storage.local.set(result); + await Logic.refreshIdentities(); + const listParentElement = document.querySelector(".identities-list tbody"); + Logic.createContainerList(listParentElement); + } catch (e) { + window.close(); + } + }); + document.addEventListener("keydown", (e) => { const selectables = [...document.querySelectorAll("[tabindex='0'], [tabindex='-1']")]; const element = document.activeElement; @@ -623,69 +713,16 @@ Logic.registerPanel(P_CONTAINERS_LIST, { // 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"); + const listParentElement = document.querySelector(".identities-list tbody"); + Logic.createContainerList(listParentElement); - tr.classList.add("container-panel-row"); - - context.classList.add("userContext-wrapper", "open-newtab", "clickable"); - manage.classList.add("show-tabs", "pop-button"); - manage.title = escaped`View ${identity.name} container`; - context.setAttribute("tabindex", "0"); - context.title = escaped`Create ${identity.name} tab`; - context.innerHTML = escaped` -
-
-
-
-
`; - context.querySelector(".container-name").textContent = identity.name; - manage.innerHTML = ""; - - fragment.appendChild(tr); - - tr.appendChild(context); - - 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); - } - }); - }); - - const list = document.querySelector(".identities-list tbody"); - - list.innerHTML = ""; - list.appendChild(fragment); /* Not sure why extensions require a focus for the doorhanger, however it allows us to have a tabindex before the first selected item */ const focusHandler = () => { - list.querySelector("tr .clickable").focus(); + listParentElement.querySelector("tr .clickable").focus(); document.removeEventListener("focus", focusHandler); }; document.addEventListener("focus", focusHandler); @@ -747,7 +784,7 @@ Logic.registerPanel(P_CONTAINER_INFO, { return; } else if (numTabs === 1) { Logic._disableMoveTabs("Cannot move a tab from a single-tab window."); - return; + return; } Logic.addEnterHandler(moveTabsEl, async () => { await browser.runtime.sendMessage({ @@ -808,7 +845,7 @@ Logic.registerPanel(P_CONTAINER_INFO, {
${tab.title}
`; tr.querySelector("td").appendChild(Utils.createFavIconElement(tab.favIconUrl)); document.getElementById("container-info-table").appendChild(fragment); - + // On click, we activate this tab. But only if this tab is active. if (!tab.hiddenState) { const closeImage = document.createElement("img"); @@ -842,7 +879,7 @@ Logic.registerPanel(P_CONTAINER_INFO, { }); } } - } + } }, }); diff --git a/src/popup.html b/src/popup.html index 4cd8219..e534c5b 100644 --- a/src/popup.html +++ b/src/popup.html @@ -109,6 +109,11 @@
Sort Tabs + + Sort Containers + + +