added code to sort the containers list including icons (feathericons.com)
This commit is contained in:
parent
41686fdf6c
commit
977617c132
5 changed files with 129 additions and 63 deletions
|
@ -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
1
src/img/chevron-down.svg
Normal 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
1
src/img/chevron-up.svg
Normal 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 |
157
src/js/popup.js
157
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`
|
||||
<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, {
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Add table
Reference in a new issue