Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First stab at reverse hierarchical display (bug 106) #128

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/_locales/de/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,11 @@
},
"useLegacyShortcutsDone": {
"message": "Sie können nun ⇧M ⇧Y und ⇧G verwenden. Ändere die Tastenkürzel in der Erweiterungsverwaltung für Tastenkürzel."
},
"reverseHierarchyCompact": {
"message": "Hierarchieanzeige umkehren (nur kompakt)"
},
"reverseHierarchyCompact.title": {
"message": "Nur Kompaktmodus. Zeigen Sie zuerst den Ordnernamen in umgekehrter Hierarchie und am Ende den Kontonamen an. Für das Konto keine separate Zeile anzeigen. Die Liste ist nach dem Ordnernamen (Blattknoten) sortiert."
}
}
6 changes: 6 additions & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,11 @@
},
"useLegacyShortcutsDone": {
"message": "You can now use ⇧M ⇧Y and ⇧G. Change the keys in the extension shortcuts."
},
"reverseHierarchyCompact": {
"message": "Reverse hierarchy display (compact only)"
},
"reverseHierarchyCompact.title": {
"message": "Compact mode only. Show the folder name first, in a reverse hierarchy, with the account name at the end. Don't show a separate line for the account. The list is sorted by the folder name (leaf node)."
}
}
6 changes: 6 additions & 0 deletions src/_locales/fr/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,11 @@
},
"useLegacyShortcutsDone": {
"message": "Vous pouvez à présent utiliser ⇧M ⇧Y et ⇧G. Utilisez l'extention shortcut pour les modifier."
},
"reverseHierarchyCompact": {
"message": "Affichage de la hiérarchie inversée (compact uniquement)"
},
"reverseHierarchyCompact.title": {
"message": "Mode compact uniquement. Affichez d'abord le nom du dossier, dans une hiérarchie inversée, avec le nom du compte à la fin. N'affichez pas de ligne distincte pour le compte. La liste est triée par nom de dossier (nœud feuille)."
}
}
44 changes: 41 additions & 3 deletions src/common/foldernode.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,54 @@ export class FolderNode extends BaseNode {
return node;
}

get fullNameParts() {
getFullNameParts(includeAccountNode) {
let parts = [];
let node = this; // eslint-disable-line consistent-this
while (node && !(node instanceof AccountNode)) {
parts.unshift(node.item.name);
while (node) {
let isAcctNode = node instanceof AccountNode;
if (includeAccountNode || !isAcctNode) {
parts.unshift(node.item.name);
}
if (isAcctNode) {
break;
}
node = node.parent;
Comment on lines +147 to 155
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
while (node) {
let isAcctNode = node instanceof AccountNode;
if (includeAccountNode || !isAcctNode) {
parts.unshift(node.item.name);
}
if (isAcctNode) {
break;
}
node = node.parent;
while (node && (!(node instanceof AccountNode) || includeAccountNode)) {
parts.unshift(node.item.name);
node = node.parent;
}

(untested)

}

return parts;
}

get fullPathReversed() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should separate the display and data aspects. We can get the reversed parts with getFullNameParts(true).reverse(), then in the folder nodes we can use templating and css to set the styles.

On the gmail and empty components thing, I think we could generally filter out empty components in getFullNameparts, and maybe add an option skipGmail that would then always skip [Gmail] folders.

let fullFolderPathComponents = this.getFullNameParts(true).filter((val) => {
// Filter out [Gmail] and empty path components.
return val !== "" && !val.includes("[");
});

if (fullFolderPathComponents.length === 0) {
return '';
}

let display = '';
for (var i = fullFolderPathComponents.length - 1; i >= 1; i--) {
if (display !== '') {
display += ' ← ';
}
display += fullFolderPathComponents[i];
}

if (display !== '') {
display += ' ← ';
}

display += '<b>' + fullFolderPathComponents[0] + '</b>';

return display;
}

get fullNameParts() {
return this.getFullNameParts(false);
}

}

export class AccountNode extends FolderNode {
Expand Down
3 changes: 2 additions & 1 deletion src/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export const DEFAULT_PREFERENCES = {
showFolderPath: false,
useLegacyShortcuts: false,
skipArchive: true,
defaultFolderSetting: "recent"
defaultFolderSetting: "recent",
reverseHierarchyCompact: false
};

export async function getValidatedDefaultFolders(accountNodes) {
Expand Down
4 changes: 4 additions & 0 deletions src/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
<input type="checkbox" id="useLegacyShortcuts">
<label for="useLegacyShortcuts" data-l10n-id="useLegacyShortcuts"></label>
</div>
<div class="preference">
<input type="checkbox" id="reverseHierarchyCompact">
<label for="reverseHierarchyCompact" data-l10n-id="reverseHierarchyCompact"></label>
</div>
<div class="preference">
<span></span>
<div>
Expand Down
26 changes: 19 additions & 7 deletions src/popup/baseItemList.js
Original file line number Diff line number Diff line change
Expand Up @@ -479,9 +479,13 @@ export default class BaseItemList extends HTMLElement {
repopulate() {
let lowerSearchTerm = this.searchValue.toLowerCase();
this.#clearItems();
let addMode;
let itemsToAdd;

if (lowerSearchTerm) {
let searchWords = lowerSearchTerm.split(/\s+/);
addMode = BaseItemList.MODE_SEARCH;
itemsToAdd = [];

for (let item of this.allItems) {
let itemText = this.getItemText(item).toLowerCase();
Expand All @@ -494,18 +498,26 @@ export default class BaseItemList extends HTMLElement {
}

if (!mismatch) {
this._addItem(item, BaseItemList.MODE_SEARCH);
itemsToAdd.push(item);
}
}
} else if (this.defaultItems) {
for (let item of this.defaultItems) {
this._addItem(item, BaseItemList.MODE_DEFAULT);
}
addMode = BaseItemList.MODE_DEFAULT;
itemsToAdd = this.defaultItems;
} else {
for (let item of this.allItems) {
this._addItem(item, BaseItemList.MODE_ALL);
}
addMode = BaseItemList.MODE_ALL;
itemsToAdd = this.allItems;
}

itemsToAdd = this.sortItems(itemsToAdd);

for (let item of itemsToAdd) {
this._addItem(item, addMode);
}
}

sortItems(items) {
return items;
}
}

Expand Down
30 changes: 26 additions & 4 deletions src/popup/folderList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BaseItemList from "./baseItemList.js";

class TBFolderList extends BaseItemList {
#showFolderPath = false;
#reverseHierarchyCompact = false;
#accounts = {};

static get style() {
Expand Down Expand Up @@ -70,6 +71,22 @@ class TBFolderList extends BaseItemList {
return folderNode.item.name;
}

sortItems(items) {
if (this.#reverseHierarchyCompact) {
// sort in a new array
let sorted = [];
for (let item of items) {
sorted.push(item);
}

sorted.sort(function(a,b){
return a.fullPathReversed.toLowerCase().localeCompare(b.fullPathReversed.toLowerCase());
});
items = sorted;
}
return items;
}

_addItem(folderNode, mode) {
// let depth = mode == BaseItemList.MODE_ALL ? (folderNode.path.match(/\//g) || []).length - 1 : 0;
let depth = 0;
Expand All @@ -84,11 +101,15 @@ class TBFolderList extends BaseItemList {
// Filter out [Gmail] and empty path components.
return val !== "" && !val.includes("[");
});

let compact = this.hasAttribute("compact");
let addAccountNode = true;

if (compact) {
if (this.#showFolderPath) {
if (this.#reverseHierarchyCompact) {
addAccountNode = false;
item.querySelector(".text").innerHTML = folderNode.fullPathReversed;
} else if (this.#showFolderPath) {
item.querySelector(".text").textContent = prettyFolderPathComponents.join("→");
} else {
item.querySelector(".text").textContent = folderNode.name;
Expand All @@ -104,7 +125,7 @@ class TBFolderList extends BaseItemList {

item.querySelector(".item").item = folderNode.item;

if (!body.lastElementChild || body.lastElementChild.item.accountId != folderNode.accountId) {
if (addAccountNode && (!body.lastElementChild || body.lastElementChild.item.accountId != folderNode.accountId)) {
let accountTemplate = this.shadowRoot.querySelector(".header-item-template");
let accountItem = this.shadowRoot.ownerDocument.importNode(accountTemplate.content, true);
let account = this.#accounts[folderNode.accountId];
Expand All @@ -129,10 +150,11 @@ class TBFolderList extends BaseItemList {
this.#accounts = Object.fromEntries(val.map(account => [account.id, account]));
}

initItems(allItems, defaultItems, showFolderPath) {
initItems(allItems, defaultItems, showFolderPath, reverseHierarchyCompact) {
this._allItems = allItems;
this._defaultItems = defaultItems;
this.#showFolderPath = showFolderPath;
this.#reverseHierarchyCompact = reverseHierarchyCompact;
this.repopulate();
}

Expand Down
6 changes: 3 additions & 3 deletions src/popup/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ function switchList(action) {
}

async function load() {
let { maxRecentFolders, showFolderPath, skipArchive, layout, defaultFolderSetting } = await browser.storage.local.get({ maxRecentFolders: 15, showFolderPath: true, layout: "auto", skipArchive: true, defaultFolderSetting: "recent" });

let { maxRecentFolders, showFolderPath, skipArchive, layout, defaultFolderSetting, reverseHierarchyCompact } = await browser.storage.local.get({ maxRecentFolders: 15, showFolderPath: true, layout: "auto", skipArchive: true, defaultFolderSetting: "recent", reverseHierarchyCompact: false });
if (layout == "wide" || (layout == "auto" && window.outerWidth > 1400)) {
document.documentElement.removeAttribute("compact");
document.getElementById("folder-list").removeAttribute("compact");
Expand Down Expand Up @@ -97,7 +97,7 @@ async function load() {

let folderList = document.getElementById("folder-list");
folderList.accounts = accounts;
folderList.initItems(folders, defaultFolders, showFolderPath);
folderList.initItems(folders, defaultFolders, showFolderPath, reverseHierarchyCompact);
folderList.ignoreFocus = true;
folderList.addEventListener("item-selected", async (event) => {
let operation = document.querySelector("input[name='action']:checked").value;
Expand Down