From 7545e5a870cb7cfd4be4b3de59d948d067a7629e Mon Sep 17 00:00:00 2001
From: "mr. m" <91018726+mr-cheffy@users.noreply.github.com>
Date: Mon, 21 Sep 2026 16:51:05 +0200
Subject: [PATCH] gh-15460: Fixed folder expansion expanding real folders on
library (gh-15498)
---
.../styles/zen-library-media-preview.css | 2 -
src/zen/common/styles/zen-library-widget.css | 2 +-
src/zen/folders/ZenFolders.mjs | 15 ++---
src/zen/library/ZenLibrary.mjs | 63 +++++++++++--------
src/zen/library/ZenLibraryMediaPreview.mjs | 57 ++++++++++++++---
.../sections/ZenLibraryMediaSection.mjs | 16 ++---
.../sections/ZenLibrarySpacesSection.mjs | 47 ++++++++++++--
src/zen/library/zen-library.css | 32 ++++------
src/zen/tabs/ZenPinnedTabManager.mjs | 11 ++--
9 files changed, 158 insertions(+), 87 deletions(-)
diff --git a/src/zen/common/styles/zen-library-media-preview.css b/src/zen/common/styles/zen-library-media-preview.css
index 0ea53bf8b..025f6701b 100644
--- a/src/zen/common/styles/zen-library-media-preview.css
+++ b/src/zen/common/styles/zen-library-media-preview.css
@@ -14,13 +14,11 @@
.zen-library-media-preview-backdrop {
position: absolute;
inset: 0;
- -moz-window-dragging: drag;
background: light-dark(rgba(255, 255, 255, 0.55), rgba(0, 0, 0, 0.45));
}
.zen-library-media-preview-panel {
position: relative;
- -moz-window-dragging: no-drag;
display: flex;
flex-direction: column;
width: min(78vw, 1100px);
diff --git a/src/zen/common/styles/zen-library-widget.css b/src/zen/common/styles/zen-library-widget.css
index 9ba4e5fec..9252b2a26 100644
--- a/src/zen/common/styles/zen-library-widget.css
+++ b/src/zen/common/styles/zen-library-widget.css
@@ -124,7 +124,7 @@
background-image: var(--download-image);
width: 20px;
height: 20px;
- border-radius: var(--border-radius-small);
+ border-radius: var(--border-radius-xsmall);
background-size: cover;
scale: 2;
diff --git a/src/zen/folders/ZenFolders.mjs b/src/zen/folders/ZenFolders.mjs
index 24ab45dd6..bb1deb731 100644
--- a/src/zen/folders/ZenFolders.mjs
+++ b/src/zen/folders/ZenFolders.mjs
@@ -100,7 +100,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
const folderActionsMenu = document.getElementById("zenFolderActions");
folderActionsMenu.addEventListener("popupshowing", event => {
- const target = event.explicitOriginalTarget;
+ const target =
+ event.target === folderActionsMenu
+ ? (folderActionsMenu.triggerNode ?? event.explicitOriginalTarget)
+ : event.explicitOriginalTarget;
let folder;
if (gBrowser.isTabGroupLabel(target)) {
folder = target.group;
@@ -498,16 +501,6 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
await this.animateCollapse(group);
}
- /**
- * Settles a collapsed folder's own height. The library toggles folders
- * through copies, so the real one needs telling once the dust settles.
- *
- * @param {Element} group - A folder
- */
- relayoutCollapsedFolder(group) {
- this.#queueCollapsedRelayout(group);
- }
-
#queueCollapsedRelayout(group) {
if (this.#collapsedRelayoutQueue.size === 0) {
requestAnimationFrame(() => this.#flushCollapsedRelayout());
diff --git a/src/zen/library/ZenLibrary.mjs b/src/zen/library/ZenLibrary.mjs
index e5686a3b8..e324e8612 100644
--- a/src/zen/library/ZenLibrary.mjs
+++ b/src/zen/library/ZenLibrary.mjs
@@ -33,6 +33,7 @@ ChromeUtils.defineESModuleGetters(
);
const LAST_TAB_PREF = "zen.library.last-tab";
+const CLEANUP_DELAY_MS = 30000;
ChromeUtils.defineLazyGetter(lazy, "appContentWrapper", function () {
return document.getElementById("zen-appcontent-wrapper");
@@ -183,18 +184,8 @@ export class ZenLibrary extends MozLitElement {
}
if (isOpen && !wasOpen) {
- this.setAttribute("open", "true");
- document
- .getElementById("zen-sidebar-splitter")
- .setAttribute("zen-library-open", "true");
this.#init();
} else if (!isOpen && wasOpen) {
- this.removeAttribute("open");
- this.#mounted = new Set([this.activeTab]);
- this.requestUpdate();
- document
- .getElementById("zen-sidebar-splitter")
- .removeAttribute("zen-library-open");
this.#cleanup();
}
@@ -293,20 +284,29 @@ export class ZenLibrary extends MozLitElement {
return this.#stylesLoaded;
}
+ #cleanupTimer = null;
#idleCleanup = null;
#scheduleIdleCleanup() {
- this.#idleCleanup = window.requestIdleCallback(() => {
- this.#idleCleanup = null;
- this.#stylesLoaded = null;
+ this.#cancelIdleCleanup();
+ this.#cleanupTimer = window.setTimeout(() => {
+ this.#cleanupTimer = null;
+ this.#idleCleanup = window.requestIdleCallback(() => {
+ this.#idleCleanup = null;
+ this.#stylesLoaded = null;
- this.#contentMounted = false;
- this.#mounted = new Set([this.activeTab]);
- this.requestUpdate();
- });
+ this.#contentMounted = false;
+ this.#mounted = new Set([this.activeTab]);
+ this.requestUpdate();
+ });
+ }, CLEANUP_DELAY_MS);
}
#cancelIdleCleanup() {
+ if (this.#cleanupTimer) {
+ window.clearTimeout(this.#cleanupTimer);
+ this.#cleanupTimer = null;
+ }
if (this.#idleCleanup) {
window.cancelIdleCallback(this.#idleCleanup);
this.#idleCleanup = null;
@@ -376,11 +376,6 @@ export class ZenLibrary extends MozLitElement {
lib.openProgress = target;
lib.#springControls = null;
lib.removeAttribute("transitioning");
- if (target === 0) {
- lib.#mounted = new Set([lib.activeTab]);
- lib.requestUpdate();
- lib.#scheduleIdleCleanup();
- }
},
}
);
@@ -401,12 +396,12 @@ export class ZenLibrary extends MozLitElement {
lib.#springControls = null;
}
- lib.style.setProperty("pointer-events", "none");
+ lib.style.pointerEvents = "none";
}
static stopSwipe(direction) {
const lib = this.getInstance();
- lib.style.setProperty("pointer-events", "unset");
+ lib.style.pointerEvents = "";
lib.#canSwipe = false;
if (lib.#libraryOnRight) {
@@ -418,7 +413,6 @@ export class ZenLibrary extends MozLitElement {
this.animateProgress(target);
}
- // Return library open state
return lib.#isOpen;
}
@@ -499,6 +493,15 @@ export class ZenLibrary extends MozLitElement {
}
#init() {
+ this.#cancelIdleCleanup();
+ if (!this.#contentMounted) {
+ this.#contentMounted = true;
+ this.requestUpdate();
+ }
+ this.setAttribute("open", "true");
+ document
+ .getElementById("zen-sidebar-splitter")
+ .setAttribute("zen-library-open", "true");
document.addEventListener("keydown", this, true);
window.addEventListener("TabOpen", this);
@@ -511,11 +514,18 @@ export class ZenLibrary extends MozLitElement {
}
#cleanup() {
- this.#cancelIdleCleanup();
+ this.removeAttribute("open");
+ this.#mounted = new Set([this.activeTab]);
+ this.requestUpdate();
+ document
+ .getElementById("zen-sidebar-splitter")
+ .removeAttribute("zen-library-open");
+
if (this.#springControls) {
this.#springControls.stop();
this.#springControls = null;
}
+ this.removeAttribute("transitioning");
this.#detachWrapperOfSwipe();
if (this.#gestureControl) {
@@ -531,6 +541,7 @@ export class ZenLibrary extends MozLitElement {
document.removeEventListener("keydown", this, true);
window.removeEventListener("TabOpen", this);
this.isHidden = true;
+ this.#scheduleIdleCleanup();
}
get #isCompactMode() {
diff --git a/src/zen/library/ZenLibraryMediaPreview.mjs b/src/zen/library/ZenLibraryMediaPreview.mjs
index 641a8daa4..cacc548a6 100644
--- a/src/zen/library/ZenLibraryMediaPreview.mjs
+++ b/src/zen/library/ZenLibraryMediaPreview.mjs
@@ -43,6 +43,8 @@ export class ZenLibraryMediaPreview {
#root = null;
#parts = {};
#menu = null;
+ /** @type {object|null} The media the open menu acts on */
+ #menuItem = null;
#items = [];
#index = -1;
#origin = null;
@@ -135,6 +137,9 @@ export class ZenLibraryMediaPreview {
openButton.addEventListener("click", () => this.#launch());
const stage = make("div", "zen-library-media-preview-stage", panel);
+ stage.addEventListener("contextmenu", event =>
+ this.openContextMenu(event, this.#item)
+ );
this.#parts = {
panel,
@@ -472,8 +477,7 @@ export class ZenLibraryMediaPreview {
event.dataTransfer.setData("text/uri-list", item.url);
}
- #launch() {
- const item = this.#item;
+ #launch(item = this.#item) {
if (!item) {
return;
}
@@ -484,15 +488,13 @@ export class ZenLibraryMediaPreview {
}
}
- #reveal() {
- const item = this.#item;
+ #reveal(item = this.#item) {
if (item) {
new lazy.FileUtils.File(item.path).reveal();
}
}
- #copy() {
- const item = this.#item;
+ #copy(item = this.#item) {
if (!item) {
return;
}
@@ -513,6 +515,40 @@ export class ZenLibraryMediaPreview {
}
#openMenu(event) {
+ this.#menuItem = this.#item;
+ this.#ensureMenu().openPopup(
+ event.currentTarget,
+ "after_end",
+ 0,
+ 0,
+ false,
+ false
+ );
+ }
+
+ /**
+ * Opens the same menu as the more button, at the pointer, for any media
+ * in the grid or the one on show.
+ *
+ * @param {MouseEvent} event - The right click
+ * @param {object} item - The media it was on
+ */
+ openContextMenu(event, item) {
+ event.preventDefault();
+ event.stopPropagation();
+ if (!item) {
+ return;
+ }
+ this.#menuItem = item;
+ this.#ensureMenu().openPopupAtScreen(
+ event.screenX,
+ event.screenY,
+ true,
+ event
+ );
+ }
+
+ #ensureMenu() {
if (!this.#menu) {
this.#menu = this.#window.MozXULElement.parseXULToFragment(`