feat: Added an option to limit the amount of subfolders there are, b=no-bug, c=folders

This commit is contained in:
Mr. M
2025-08-07 19:09:33 +02:00
parent 82f30e1820
commit afe9e7a85c
4 changed files with 68 additions and 16 deletions

View File

@@ -7,3 +7,6 @@
- name: zen.folders.search.hover-delay
value: 1000 # ms
- name: zen.folders.max-subfolders
value: 5

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e73cb55a4b 100644
index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..7bb218913170222d55e7b7bdf4ca08923f359862 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -422,15 +422,60 @@
@@ -391,10 +391,10 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
+ gZenWorkspaces._initialTab._shouldRemove = true;
+ }
+ }
}
+ }
+ else {
+ gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab;
+ }
}
+ this._hasAlreadyInitializedZenSessionStore = true;
if (tabs.length > 1 || !tabs[0].selected) {
@@ -672,7 +672,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
moveBefore = false;
} else if (!element.pinned && targetElement && targetElement.pinned) {
// If the caller asks to move an unpinned element next to a pinned
@@ -6145,7 +6290,7 @@
@@ -6145,14 +6290,18 @@
// move the tab group right before the first unpinned tab.
// 4. Moving a tab group and the first unpinned tab is grouped:
// move the tab group right before the first unpinned tab's tab group.
@@ -681,15 +681,18 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
if (targetElement.group) {
targetElement = targetElement.group;
}
@@ -6153,6 +6298,7 @@
moveBefore = true;
}
+ if (!gZenFolders.canDropElement(element, targetElement)) {
+ element = element.group;
+ }
let getContainer = () =>
+ element.hasAttribute("zen-essential") ? gZenWorkspaces.getEssentialsSection(element) :
element.pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
@@ -6161,7 +6307,7 @@
@@ -6161,7 +6310,7 @@
element,
() => {
if (moveBefore) {
@@ -698,7 +701,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
} else if (targetElement) {
targetElement.after(element);
} else {
@@ -6210,7 +6356,7 @@
@@ -6210,7 +6359,7 @@
if (!this.isTab(aTab)) {
throw new Error("Can only move a tab into a tab group");
}
@@ -707,7 +710,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
return;
}
if (aTab.group && aTab.group.id === aGroup.id) {
@@ -6304,6 +6450,10 @@
@@ -6304,6 +6453,10 @@
moveActionCallback();
@@ -718,7 +721,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
// Clear tabs cache after moving nodes because the order of tabs may have
// changed.
this.tabContainer._invalidateCachedTabs();
@@ -7198,7 +7348,7 @@
@@ -7198,7 +7351,7 @@
// preventDefault(). It will still raise the window if appropriate.
break;
}
@@ -727,7 +730,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
window.focus();
aEvent.preventDefault();
break;
@@ -8143,6 +8293,7 @@
@@ -8143,6 +8296,7 @@
aWebProgress.isTopLevel
) {
this.mTab.setAttribute("busy", "true");
@@ -735,7 +738,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected;
}
@@ -9108,7 +9259,7 @@ var TabContextMenu = {
@@ -9108,7 +9262,7 @@ var TabContextMenu = {
);
contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected;
@@ -744,7 +747,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..17e35b5d793064d099938c28d8f975e7
// Move Tab items
let contextMoveTabOptions = document.getElementById(
"context_moveTabOptions"
@@ -9384,6 +9535,7 @@ var TabContextMenu = {
@@ -9384,6 +9538,7 @@ var TabContextMenu = {
)
);
} else {

View File

@@ -29,6 +29,8 @@
return `${month} month${month === 1 ? '' : 's'} ago`;
}
const ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref('zen.folders.max-subfolders');
class nsZenFolders extends nsZenPreloadedFeature {
#popup = null;
#popupTimer = null;
@@ -496,6 +498,13 @@
gZenWorkspaces.changeWorkspaceWithID(workspaceId);
}
canDropElement(element, targetElement) {
if (element?.isZenFolder && targetElement?.group?.level >= ZEN_MAX_SUBFOLDERS) {
return false;
}
return true;
}
createFolder(tabs = [], options = {}) {
for (const tab of tabs) {
if (tab.hasAttribute('zen-essential')) return;
@@ -652,6 +661,32 @@
};
search.addEventListener('input', onSearchInput);
const onKeyDown = (event) => {
// Arrow down and up to navigate through the list
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
event.preventDefault();
const items = Array.from(tabsList.children).filter((item) => !item.hidden);
if (items.length === 0) return;
let index = items.indexOf(tabsList.querySelector('.folders-tabs-list-item[selected]'));
if (event.key === 'ArrowDown') {
index = (index + 1) % items.length;
} else if (event.key === 'ArrowUp') {
index = (index - 1 + items.length) % items.length;
}
items.forEach((item) => item.removeAttribute('selected'));
const targetItem = items[index];
targetItem.setAttribute('selected', 'true');
targetItem.scrollIntoView({ block: 'nearest' });
} else if (event.key === 'Enter') {
// Enter to select the currently highlighted item
const highlightedItem = tabsList.querySelector('.folders-tabs-list-item[selected]');
if (highlightedItem) {
highlightedItem.click();
}
}
};
document.addEventListener('keydown', onKeyDown);
const target = event.target;
target.setAttribute('open', true);
@@ -660,6 +695,7 @@
search.value = '';
target.removeAttribute('open');
search.removeEventListener('input', onSearchInput);
document.removeEventListener('keydown', onKeyDown);
};
this.#popup.addEventListener(
@@ -854,12 +890,19 @@
itemHeight += item.getBoundingClientRect().height;
if (item.hasAttribute('folder-active')) {
item.removeAttribute('folder-active');
item.setAttribute('was-folder-active', 'true');
if (!onlyIfActive) {
item.setAttribute('was-folder-active', 'true');
}
}
}
const newMargin = -(itemHeight + 4);
groupStart.setAttribute('new-margin', newMargin);
if (onlyIfActive) {
group.removeAttribute('has-active');
this.updateFolderIcon(group, 'close', false);
}
gZenUIManager.motion.animate(
groupStart,
{
@@ -1183,7 +1226,10 @@
if (
folder &&
(!folder.hasAttribute('split-view-group') || !folder.hasAttribute('selected')) &&
folder !== tab?.group
folder !== tab?.group &&
!(
folder.level >= ZEN_MAX_SUBFOLDERS && movingTabs?.some((t) => gBrowser.isTabGroupLabel(t))
)
) {
folder.setAttribute('selected', 'true');
folder.style.transform = '';
@@ -1236,7 +1282,6 @@
const isSplitGroup = dropElement?.group?.hasAttribute('split-view-group');
let firstGroupElem =
dropElementGroup.querySelector('.zen-tab-group-start').nextElementSibling;
// let lastGroupElem = dropElementGroup?.group?.allItems?.filter(tab => tab.visible)?.at(-1);
const isRestrictedGroup = isSplitGroup || dropElementGroup.collapsed;

View File

@@ -421,7 +421,8 @@ zen-folder {
padding: 0 var(--tab-inline-padding);
border-radius: 4px;
&:hover {
&:hover,
.folders-tabs-list-item[selected] & {
background-color: color-mix(in srgb, currentColor, transparent 90%);
}