Skip to content

Commit afe9e7a

Browse files
committed
feat: Added an option to limit the amount of subfolders there are, b=no-bug, c=folders
1 parent 82f30e1 commit afe9e7a

File tree

4 files changed

+68
-16
lines changed

4 files changed

+68
-16
lines changed

prefs/folders.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77

88
- name: zen.folders.search.hover-delay
99
value: 1000 # ms
10+
11+
- name: zen.folders.max-subfolders
12+
value: 5

src/browser/components/tabbrowser/content/tabbrowser-js.patch

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
2-
index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e73cb55a4b 100644
2+
index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..7bb218913170222d55e7b7bdf4ca08923f359862 100644
33
--- a/browser/components/tabbrowser/content/tabbrowser.js
44
+++ b/browser/components/tabbrowser/content/tabbrowser.js
55
@@ -422,15 +422,60 @@
@@ -391,10 +391,10 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
391391
+ gZenWorkspaces._initialTab._shouldRemove = true;
392392
+ }
393393
+ }
394-
}
394+
+ }
395395
+ else {
396396
+ gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab;
397-
+ }
397+
}
398398
+ this._hasAlreadyInitializedZenSessionStore = true;
399399

400400
if (tabs.length > 1 || !tabs[0].selected) {
@@ -672,7 +672,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
672672
moveBefore = false;
673673
} else if (!element.pinned && targetElement && targetElement.pinned) {
674674
// If the caller asks to move an unpinned element next to a pinned
675-
@@ -6145,7 +6290,7 @@
675+
@@ -6145,14 +6290,18 @@
676676
// move the tab group right before the first unpinned tab.
677677
// 4. Moving a tab group and the first unpinned tab is grouped:
678678
// move the tab group right before the first unpinned tab's tab group.
@@ -681,15 +681,18 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
681681
if (targetElement.group) {
682682
targetElement = targetElement.group;
683683
}
684-
@@ -6153,6 +6298,7 @@
684+
moveBefore = true;
685685
}
686+
+ if (!gZenFolders.canDropElement(element, targetElement)) {
687+
+ element = element.group;
688+
+ }
686689

687690
let getContainer = () =>
688691
+ element.hasAttribute("zen-essential") ? gZenWorkspaces.getEssentialsSection(element) :
689692
element.pinned
690693
? this.tabContainer.pinnedTabsContainer
691694
: this.tabContainer;
692-
@@ -6161,7 +6307,7 @@
695+
@@ -6161,7 +6310,7 @@
693696
element,
694697
() => {
695698
if (moveBefore) {
@@ -698,7 +701,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
698701
} else if (targetElement) {
699702
targetElement.after(element);
700703
} else {
701-
@@ -6210,7 +6356,7 @@
704+
@@ -6210,7 +6359,7 @@
702705
if (!this.isTab(aTab)) {
703706
throw new Error("Can only move a tab into a tab group");
704707
}
@@ -707,7 +710,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
707710
return;
708711
}
709712
if (aTab.group && aTab.group.id === aGroup.id) {
710-
@@ -6304,6 +6450,10 @@
713+
@@ -6304,6 +6453,10 @@
711714

712715
moveActionCallback();
713716

@@ -718,7 +721,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
718721
// Clear tabs cache after moving nodes because the order of tabs may have
719722
// changed.
720723
this.tabContainer._invalidateCachedTabs();
721-
@@ -7198,7 +7348,7 @@
724+
@@ -7198,7 +7351,7 @@
722725
// preventDefault(). It will still raise the window if appropriate.
723726
break;
724727
}
@@ -727,15 +730,15 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
727730
window.focus();
728731
aEvent.preventDefault();
729732
break;
730-
@@ -8143,6 +8293,7 @@
733+
@@ -8143,6 +8296,7 @@
731734
aWebProgress.isTopLevel
732735
) {
733736
this.mTab.setAttribute("busy", "true");
734737
+ if (!this.mTab.selected) this.mTab.setAttribute("unread", "true");
735738
gBrowser._tabAttrModified(this.mTab, ["busy"]);
736739
this.mTab._notselectedsinceload = !this.mTab.selected;
737740
}
738-
@@ -9108,7 +9259,7 @@ var TabContextMenu = {
741+
@@ -9108,7 +9262,7 @@ var TabContextMenu = {
739742
);
740743
contextUnpinSelectedTabs.hidden =
741744
!this.contextTab.pinned || !this.multiselected;
@@ -744,7 +747,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
744747
// Move Tab items
745748
let contextMoveTabOptions = document.getElementById(
746749
"context_moveTabOptions"
747-
@@ -9384,6 +9535,7 @@ var TabContextMenu = {
750+
@@ -9384,6 +9538,7 @@ var TabContextMenu = {
748751
)
749752
);
750753
} else {

src/zen/folders/ZenFolders.mjs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
return `${month} month${month === 1 ? '' : 's'} ago`;
3030
}
3131

32+
const ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref('zen.folders.max-subfolders');
33+
3234
class nsZenFolders extends nsZenPreloadedFeature {
3335
#popup = null;
3436
#popupTimer = null;
@@ -496,6 +498,13 @@
496498
gZenWorkspaces.changeWorkspaceWithID(workspaceId);
497499
}
498500

501+
canDropElement(element, targetElement) {
502+
if (element?.isZenFolder && targetElement?.group?.level >= ZEN_MAX_SUBFOLDERS) {
503+
return false;
504+
}
505+
return true;
506+
}
507+
499508
createFolder(tabs = [], options = {}) {
500509
for (const tab of tabs) {
501510
if (tab.hasAttribute('zen-essential')) return;
@@ -652,6 +661,32 @@
652661
};
653662
search.addEventListener('input', onSearchInput);
654663

664+
const onKeyDown = (event) => {
665+
// Arrow down and up to navigate through the list
666+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
667+
event.preventDefault();
668+
const items = Array.from(tabsList.children).filter((item) => !item.hidden);
669+
if (items.length === 0) return;
670+
let index = items.indexOf(tabsList.querySelector('.folders-tabs-list-item[selected]'));
671+
if (event.key === 'ArrowDown') {
672+
index = (index + 1) % items.length;
673+
} else if (event.key === 'ArrowUp') {
674+
index = (index - 1 + items.length) % items.length;
675+
}
676+
items.forEach((item) => item.removeAttribute('selected'));
677+
const targetItem = items[index];
678+
targetItem.setAttribute('selected', 'true');
679+
targetItem.scrollIntoView({ block: 'nearest' });
680+
} else if (event.key === 'Enter') {
681+
// Enter to select the currently highlighted item
682+
const highlightedItem = tabsList.querySelector('.folders-tabs-list-item[selected]');
683+
if (highlightedItem) {
684+
highlightedItem.click();
685+
}
686+
}
687+
};
688+
document.addEventListener('keydown', onKeyDown);
689+
655690
const target = event.target;
656691
target.setAttribute('open', true);
657692

@@ -660,6 +695,7 @@
660695
search.value = '';
661696
target.removeAttribute('open');
662697
search.removeEventListener('input', onSearchInput);
698+
document.removeEventListener('keydown', onKeyDown);
663699
};
664700

665701
this.#popup.addEventListener(
@@ -854,12 +890,19 @@
854890
itemHeight += item.getBoundingClientRect().height;
855891
if (item.hasAttribute('folder-active')) {
856892
item.removeAttribute('folder-active');
857-
item.setAttribute('was-folder-active', 'true');
893+
if (!onlyIfActive) {
894+
item.setAttribute('was-folder-active', 'true');
895+
}
858896
}
859897
}
860898
const newMargin = -(itemHeight + 4);
861899
groupStart.setAttribute('new-margin', newMargin);
862900

901+
if (onlyIfActive) {
902+
group.removeAttribute('has-active');
903+
this.updateFolderIcon(group, 'close', false);
904+
}
905+
863906
gZenUIManager.motion.animate(
864907
groupStart,
865908
{
@@ -1183,7 +1226,10 @@
11831226
if (
11841227
folder &&
11851228
(!folder.hasAttribute('split-view-group') || !folder.hasAttribute('selected')) &&
1186-
folder !== tab?.group
1229+
folder !== tab?.group &&
1230+
!(
1231+
folder.level >= ZEN_MAX_SUBFOLDERS && movingTabs?.some((t) => gBrowser.isTabGroupLabel(t))
1232+
)
11871233
) {
11881234
folder.setAttribute('selected', 'true');
11891235
folder.style.transform = '';
@@ -1236,7 +1282,6 @@
12361282
const isSplitGroup = dropElement?.group?.hasAttribute('split-view-group');
12371283
let firstGroupElem =
12381284
dropElementGroup.querySelector('.zen-tab-group-start').nextElementSibling;
1239-
// let lastGroupElem = dropElementGroup?.group?.allItems?.filter(tab => tab.visible)?.at(-1);
12401285

12411286
const isRestrictedGroup = isSplitGroup || dropElementGroup.collapsed;
12421287

src/zen/folders/zen-folders.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ zen-folder {
421421
padding: 0 var(--tab-inline-padding);
422422
border-radius: 4px;
423423

424-
&:hover {
424+
&:hover,
425+
.folders-tabs-list-item[selected] & {
425426
background-color: color-mix(in srgb, currentColor, transparent 90%);
426427
}
427428

0 commit comments

Comments
 (0)