From bdf8bc6b3305cc6eb9e6a3c93ad61ba5b3f13fff Mon Sep 17 00:00:00 2001 From: Andre Nijman Date: Wed, 25 Feb 2026 07:34:22 +0800 Subject: [PATCH] fix: Hide folder icon remove action when no icon is set, b=closes #12401, p=#12481, c=folders, common Co-authored-by: andre Co-authored-by: mr. m <91018726+mr-cheffy@users.noreply.github.com> --- src/zen/common/emojis/ZenEmojiPicker.mjs | 45 +++++++++++++++++-- .../common/styles/zen-single-components.css | 8 ++++ src/zen/folders/ZenFolders.mjs | 14 +++--- src/zen/tabs/ZenPinnedTabManager.mjs | 14 +++--- src/zen/workspaces/ZenWorkspaceCreation.mjs | 18 ++++---- src/zen/workspaces/ZenWorkspaces.mjs | 18 +++----- 6 files changed, 79 insertions(+), 38 deletions(-) diff --git a/src/zen/common/emojis/ZenEmojiPicker.mjs b/src/zen/common/emojis/ZenEmojiPicker.mjs index bdbf02f8c..c734f91a0 100644 --- a/src/zen/common/emojis/ZenEmojiPicker.mjs +++ b/src/zen/common/emojis/ZenEmojiPicker.mjs @@ -35,6 +35,10 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { #anchor; #emojiAsSVG = false; + #closeOnSelect = true; + #onSelect = null; + #hasSelection = false; + #lastSelectedEmoji = null; #currentPromise = null; #currentPromiseResolve = null; @@ -120,6 +124,14 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { delete this._emojis; } + #setAllowNone(allowNone) { + if (allowNone) { + this.#panel.removeAttribute("hide-none-option"); + return; + } + this.#panel.setAttribute("hide-none-option", "true"); + } + #onSearchInput(event) { const input = event.target; const value = input.value.trim().toLowerCase(); @@ -192,13 +204,19 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { this.svgList.innerHTML = ""; - if (this.#currentPromiseReject) { - this.#currentPromiseReject(new Error("Emoji picker closed without selection")); + if (!this.#hasSelection) { + this.#currentPromiseReject?.(new Error("Emoji picker closed without selection")); + } else if (!this.#closeOnSelect) { + this.#currentPromiseResolve?.(this.#lastSelectedEmoji); } this.#currentPromise = null; this.#currentPromiseResolve = null; this.#currentPromiseReject = null; + this.#onSelect = null; + this.#closeOnSelect = true; + this.#hasSelection = false; + this.#lastSelectedEmoji = null; this.#anchor.removeAttribute("zen-emoji-open"); this.#anchor.parentElement.removeAttribute("zen-emoji-open"); @@ -213,15 +231,35 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { )}` )}`; } + this.#setAllowNone(Boolean(emoji)); + this.#hasSelection = true; + this.#lastSelectedEmoji = emoji; + this.#onSelect?.(emoji); + if (!this.#closeOnSelect) { + return; + } this.#currentPromiseResolve?.(emoji); this.#panel.hidePopup(); } - open(anchor, { onlySvgIcons = false, emojiAsSVG = false } = {}) { + open( + anchor, + { + onlySvgIcons = false, + emojiAsSVG = false, + allowNone = true, + closeOnSelect = true, + onSelect = null, + } = {} + ) { if (this.#currentPromise) { return null; } this.#emojiAsSVG = emojiAsSVG; + this.#closeOnSelect = closeOnSelect; + this.#onSelect = onSelect; + this.#hasSelection = false; + this.#lastSelectedEmoji = null; this.#currentPromise = new Promise((resolve, reject) => { this.#currentPromiseResolve = resolve; this.#currentPromiseReject = reject; @@ -234,6 +272,7 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { } else { this.#panel.removeAttribute("only-svg-icons"); } + this.#setAllowNone(allowNone); this.#panel.openPopup(anchor, "after_start", 0, 0, false, false); return this.#currentPromise; } diff --git a/src/zen/common/styles/zen-single-components.css b/src/zen/common/styles/zen-single-components.css index 675beb8d2..23c7fe73b 100644 --- a/src/zen/common/styles/zen-single-components.css +++ b/src/zen/common/styles/zen-single-components.css @@ -87,6 +87,13 @@ } } + &[hide-none-option="true"] { + & #PanelUI-zen-emojis-picker-none { + opacity: 0; + pointer-events: none; + } + } + #PanelUI-zen-emojis-picker-none label { display: none; } @@ -164,6 +171,7 @@ width: 22px; height: 22px; appearance: none; + transition: opacity 0.08s ease-in-out; &:hover { background-color: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); diff --git a/src/zen/folders/ZenFolders.mjs b/src/zen/folders/ZenFolders.mjs index 5e412f0fe..ffdede9a1 100644 --- a/src/zen/folders/ZenFolders.mjs +++ b/src/zen/folders/ZenFolders.mjs @@ -903,15 +903,15 @@ class nsZenFolders extends nsZenDOMOperatedFeature { return; } - gZenEmojiPicker - .open(group.icon, { onlySvgIcons: true }) - .then((icon) => { + gZenEmojiPicker.open(group.icon, { + onlySvgIcons: true, + allowNone: Boolean(group.iconURL), + closeOnSelect: false, + onSelect: (icon) => { this.setFolderUserIcon(group, icon); group.dispatchEvent(new CustomEvent("TabGroupUpdate", { bubbles: true })); - }) - .catch((err) => { - console.error(err); - }); + }, + }); } setFolderUserIcon(group, icon) { diff --git a/src/zen/tabs/ZenPinnedTabManager.mjs b/src/zen/tabs/ZenPinnedTabManager.mjs index b1282ce3b..8bf52f019 100644 --- a/src/zen/tabs/ZenPinnedTabManager.mjs +++ b/src/zen/tabs/ZenPinnedTabManager.mjs @@ -504,9 +504,11 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature { }); document.getElementById("context_zen-edit-tab-icon").addEventListener("command", () => { const tab = TabContextMenu.contextTab; - gZenEmojiPicker - .open(tab.iconImage, { emojiAsSVG: true }) - .then((icon) => { + gZenEmojiPicker.open(tab.iconImage, { + emojiAsSVG: true, + closeOnSelect: false, + allowNone: Boolean(tab.zenStaticIcon), + onSelect: (icon) => { if (icon) { tab.zenStaticIcon = icon; } else { @@ -516,10 +518,8 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature { lazy.TabStateCache.update(tab.permanentKey, { image: null, }); - }) - .catch((err) => { - console.error(err); - }); + }, + }); }); } diff --git a/src/zen/workspaces/ZenWorkspaceCreation.mjs b/src/zen/workspaces/ZenWorkspaceCreation.mjs index 05db95c35..98904dd09 100644 --- a/src/zen/workspaces/ZenWorkspaceCreation.mjs +++ b/src/zen/workspaces/ZenWorkspaceCreation.mjs @@ -218,23 +218,21 @@ class nsZenWorkspaceCreation extends MozXULElement { } onIconCommand(event) { - gZenEmojiPicker - .open(event.target) - .then(async (emoji) => { - const isSvg = emoji && emoji.endsWith(".svg"); + gZenEmojiPicker.open(event.target, { + closeOnSelect: false, + onSelect: async (icon) => { + const isSvg = icon && icon.endsWith(".svg"); if (isSvg) { this.inputIcon.label = ""; - this.inputIcon.image = emoji; + this.inputIcon.image = icon; this.inputIcon.setAttribute("has-svg-icon", "true"); } else { this.inputIcon.image = ""; - this.inputIcon.label = emoji || ""; + this.inputIcon.label = icon || ""; this.inputIcon.removeAttribute("has-svg-icon"); } - }) - .catch((error) => { - console.warn("Error changing workspace icon:", error); - }); + }, + }); } set currentProfile(profile) { diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index 52cd3c798..135a2bd98 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -1085,23 +1085,19 @@ class nsZenWorkspaces { if (hasNoIcon) { anchor.textContent = ""; } - gZenEmojiPicker - .open(anchor) - .then(async (emoji) => { + gZenEmojiPicker.open(anchor, { + closeOnSelect: false, + allowNone: hasNoIcon, + onSelect: async (icon) => { const workspace = this.getWorkspaceFromId(workspaceId); if (!workspace) { console.warn("No active workspace found to change icon"); return; } - workspace.icon = emoji; + workspace.icon = icon; await this.saveWorkspace(workspace); - }) - .catch((error) => { - console.warn("Error changing workspace icon:", error); - if (hasNoIcon) { - anchor.setAttribute("no-icon", "true"); - } - }); + }, + }); } shouldCloseWindow() {