added code to sort the containers list including icons (feathericons.com)

This commit is contained in:
George Vlachos 2019-02-24 11:53:44 +02:00
parent 41686fdf6c
commit 977617c132
5 changed files with 129 additions and 63 deletions

View file

@ -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;
}

1
src/img/chevron-down.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-down"><polyline points="6 9 12 15 18 9"></polyline></svg>

After

Width:  |  Height:  |  Size: 269 B

1
src/img/chevron-up.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>

After

Width:  |  Height:  |  Size: 268 B

View file

@ -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`
<div class="userContext-icon-wrapper open-newtab">
<div class="usercontext-icon"
data-identity-icon="${identity.icon}"
data-identity-color="${identity.color}">
</div>
</div>
<div class="container-name truncate-text"></div>`;
context.querySelector(".container-name").textContent = identity.name;
manage.innerHTML = "<img src='/img/container-arrow.svg' class='show-tabs pop-button-image-small' />";
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`
<div class="userContext-icon-wrapper open-newtab">
<div class="usercontext-icon"
data-identity-icon="${identity.icon}"
data-identity-color="${identity.color}">
</div>
</div>
<div class="container-name truncate-text"></div>`;
context.querySelector(".container-name").textContent = identity.name;
manage.innerHTML = "<img src='/img/container-arrow.svg' class='show-tabs pop-button-image-small' />";
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, {
<td class="container-info-tab-title truncate-text" title="${tab.url}" ><div class="container-tab-title">${tab.title}</div></td>`;
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, {
});
}
}
}
}
},
});

View file

@ -109,6 +109,11 @@
</div>
<div class="container-panel-controls">
<a href="#" class="action-link" id="sort-containers-link" title="Sort tabs into container order">Sort Tabs</a>
<a href="#" class="action-link" id="sort-containers-list-link" title="Sort containers alphabetically">
<span>Sort Containers </span>
<img alt="Panel Back Arrow" src="/img/chevron-up.svg" class="up-arrow-img" style="display: none;"/>
<img alt="Panel Back Arrow" src="/img/chevron-down.svg" class="down-arrow-img" style="display: none;" />
</a>
</div>
<div class="scrollable panel-content" tabindex="-1">
<table class="identities-list">