diff --git a/locales/en-US/browser/browser/zen-folders.ftl b/locales/en-US/browser/browser/zen-folders.ftl index ebeeaf33c..93180f314 100644 --- a/locales/en-US/browser/browser/zen-folders.ftl +++ b/locales/en-US/browser/browser/zen-folders.ftl @@ -23,9 +23,6 @@ zen-folders-panel-convert-folder-to-space = zen-folders-panel-change-folder-space = .label = Change Space... -zen-folders-panel-change-icon-folder = - .label = Change Icon - zen-folders-unload-all-tooltip = .tooltiptext = Unload active in this folder diff --git a/locales/en-US/browser/browser/zen-general.ftl b/locales/en-US/browser/browser/zen-general.ftl index 07a7546c8..0eab050d6 100644 --- a/locales/en-US/browser/browser/zen-general.ftl +++ b/locales/en-US/browser/browser/zen-general.ftl @@ -18,6 +18,10 @@ tab-context-zen-remove-essential = tab-context-zen-replace-pinned-url-with-current = .label = Replace Pinned URL with Current .accesskey = C +tab-context-zen-edit-title = + .label = Change Label... +tab-context-zen-edit-icon = + .label = Change Icon... zen-themes-corrupted = Your { -brand-short-name } mods file is corrupted. They have been reset to the default theme. zen-shortcuts-corrupted = Your { -brand-short-name } shortcuts file is corrupted. They have been reset to the default shortcuts. diff --git a/locales/en-US/browser/browser/zen-workspaces.ftl b/locales/en-US/browser/browser/zen-workspaces.ftl index 9eea8c1be..c7a5b64fd 100644 --- a/locales/en-US/browser/browser/zen-workspaces.ftl +++ b/locales/en-US/browser/browser/zen-workspaces.ftl @@ -43,12 +43,8 @@ zen-workspaces-panel-context-edit = .label = Edit Space .accesskey = E -context-zen-change-workspace-tab = - .label = Change Tab(s) To Workspace - .accesskey = C - zen-bookmark-edit-panel-workspace-selector = - .value = Workspaces + .value = Spaces .accesskey = W zen-panel-ui-gradient-generator-algo-complementary = diff --git a/prefs/zen/view.yaml b/prefs/zen/view.yaml index 7f5939822..83d21386a 100644 --- a/prefs/zen/view.yaml +++ b/prefs/zen/view.yaml @@ -47,7 +47,7 @@ value: 25 - name: zen.view.context-menu.refresh - value: false + value: '@IS_TWILIGHT@' - name: zen.view.borderless-fullscreen value: true diff --git a/src/browser/base/content/zen-panels/popups.inc b/src/browser/base/content/zen-panels/popups.inc index b4ecd5e14..864d88e10 100644 --- a/src/browser/base/content/zen-panels/popups.inc +++ b/src/browser/base/content/zen-panels/popups.inc @@ -36,7 +36,7 @@ - + diff --git a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch index f354ceada..9253c8682 100644 --- a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch +++ b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs -index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832cee88ace 100644 +index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..4a229300d837ffead46a966ea23b37cd1ef01db2 100644 --- a/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs @@ -127,6 +127,8 @@ const TAB_EVENTS = [ @@ -119,7 +119,18 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 userContextId: state.userContextId, skipLoad: true, preferredRemoteType, -@@ -5374,7 +5399,7 @@ var SessionStoreInternal = { +@@ -5032,7 +5057,10 @@ var SessionStoreInternal = { + !activePageData || + (activePageData && activePageData.url != "about:blank") + ) { ++ let hadZenStaticFlag = tab.hasAttribute("zen-has-static-icon"); ++ tab.removeAttribute("zen-has-static-icon"); + win.gBrowser.setIcon(tab, tabData.image); ++ if (hadZenStaticFlag) tab.setAttribute("zen-has-static-icon", true); + } + lazy.TabStateCache.update(browser.permanentKey, { + image: null, +@@ -5374,7 +5402,7 @@ var SessionStoreInternal = { for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) { let tab = tabbrowser.tabs[i]; @@ -128,7 +139,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 removableTabs.push(tab); } } -@@ -5483,7 +5508,7 @@ var SessionStoreInternal = { +@@ -5483,7 +5511,7 @@ var SessionStoreInternal = { // collect the data for all windows for (ix in this._windows) { @@ -137,7 +148,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 // window data is still in _statesToRestore continue; } -@@ -5625,11 +5650,12 @@ var SessionStoreInternal = { +@@ -5625,11 +5653,12 @@ var SessionStoreInternal = { } let tabbrowser = aWindow.gBrowser; @@ -151,7 +162,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 // update the internal state data for this window for (let tab of tabs) { if (tab == aWindow.FirefoxViewHandler.tab) { -@@ -5640,6 +5666,9 @@ var SessionStoreInternal = { +@@ -5640,6 +5669,9 @@ var SessionStoreInternal = { tabsData.push(tabData); } @@ -161,7 +172,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 // update tab group state for this window winData.groups = []; for (let tabGroup of aWindow.gBrowser.tabGroups) { -@@ -5652,7 +5681,7 @@ var SessionStoreInternal = { +@@ -5652,7 +5684,7 @@ var SessionStoreInternal = { // a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab, // since it's only inserted into the tab strip after it's selected). if (aWindow.FirefoxViewHandler.tab?.selected) { @@ -170,7 +181,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 winData.title = tabbrowser.tabs[0].label; } winData.selected = selectedIndex; -@@ -5765,8 +5794,8 @@ var SessionStoreInternal = { +@@ -5765,8 +5797,8 @@ var SessionStoreInternal = { // selectTab represents. let selectTab = 0; if (overwriteTabs) { @@ -181,7 +192,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 selectTab = Math.min(selectTab, winData.tabs.length); } -@@ -5788,6 +5817,7 @@ var SessionStoreInternal = { +@@ -5788,6 +5820,7 @@ var SessionStoreInternal = { if (overwriteTabs) { for (let i = tabbrowser.browsers.length - 1; i >= 0; i--) { if (!tabbrowser.tabs[i].selected) { @@ -189,7 +200,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 tabbrowser.removeTab(tabbrowser.tabs[i]); } } -@@ -5821,6 +5851,9 @@ var SessionStoreInternal = { +@@ -5821,6 +5854,9 @@ var SessionStoreInternal = { savedTabGroup => !openTabGroupIdsInWindow.has(savedTabGroup.id) ); } @@ -199,7 +210,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 // Move the originally open tabs to the end. if (initialTabs) { -@@ -6372,6 +6405,25 @@ var SessionStoreInternal = { +@@ -6372,6 +6408,28 @@ var SessionStoreInternal = { // Most of tabData has been restored, now continue with restoring // attributes that may trigger external events. @@ -213,6 +224,9 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 + if (tabData.zenHasStaticLabel) { + tab.setAttribute("zen-has-static-label", "true"); + } ++ if (tabData.zenHasStaticIcon) { ++ tab.setAttribute("zen-has-static-icon", "true"); ++ } + if (tabData.zenSyncId) { + tab.setAttribute("id", tabData.zenSyncId); + } @@ -225,7 +239,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 if (tabData.pinned) { tabbrowser.pinTab(tab); -@@ -7290,7 +7342,7 @@ var SessionStoreInternal = { +@@ -7290,7 +7348,7 @@ var SessionStoreInternal = { let groupsToSave = new Map(); for (let tIndex = 0; tIndex < window.tabs.length; ) { @@ -234,7 +248,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..450316b7e18852cc088479e9a5fb5832 // Adjust window.selected if (tIndex + 1 < window.selected) { window.selected -= 1; -@@ -7305,7 +7357,7 @@ var SessionStoreInternal = { +@@ -7305,7 +7363,7 @@ var SessionStoreInternal = { ); // We don't want to increment tIndex here. continue; diff --git a/src/browser/components/sessionstore/TabState-sys-mjs.patch b/src/browser/components/sessionstore/TabState-sys-mjs.patch index 450c981c3..2d47a2417 100644 --- a/src/browser/components/sessionstore/TabState-sys-mjs.patch +++ b/src/browser/components/sessionstore/TabState-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs -index 82721356d191055bec0d4b0ca49e481221988801..80547ec951f881bef134b637730954eb1525c623 100644 +index 82721356d191055bec0d4b0ca49e481221988801..7b3ba1b3a6df2b5031d3d96579e564d9de38ba9c 100644 --- a/browser/components/sessionstore/TabState.sys.mjs +++ b/browser/components/sessionstore/TabState.sys.mjs -@@ -85,7 +85,24 @@ class _TabState { +@@ -85,7 +85,25 @@ class _TabState { tabData.groupId = tab.group.id; } @@ -15,6 +15,7 @@ index 82721356d191055bec0d4b0ca49e481221988801..80547ec951f881bef134b637730954eb + tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon"); + tabData.zenIsEmpty = tab.hasAttribute("zen-empty-tab"); + tabData.zenHasStaticLabel = tab.hasAttribute("zen-has-static-label"); ++ tabData.zenHasStaticIcon = tab.hasAttribute("zen-has-static-icon"); + tabData.zenGlanceId = tab.getAttribute("glance-id"); + tabData.zenIsGlance = tab.hasAttribute("zen-glance-tab"); + tabData._zenPinnedInitialState = tab._zenPinnedInitialState; @@ -27,7 +28,7 @@ index 82721356d191055bec0d4b0ca49e481221988801..80547ec951f881bef134b637730954eb tabData.userContextId = tab.userContextId || 0; -@@ -98,7 +115,7 @@ class _TabState { +@@ -98,7 +116,7 @@ class _TabState { // Copy data from the tab state cache only if the tab has fully finished // restoring. We don't want to overwrite data contained in __SS_data. diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 7327740e8..92b6d0167 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18e829ca07 100644 +index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..8916896fae6807fb4c033022f1f50e44c9fe0117 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -386,6 +386,7 @@ @@ -123,16 +123,19 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 }); aTab.style.marginInlineStart = ""; -@@ -1098,6 +1159,8 @@ +@@ -1098,6 +1159,11 @@ let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"]; + try { -+ gZenPinnedTabManager.onTabIconChanged(aTab, aIconURL); ++ if (aTab.hasAttribute("zen-has-static-icon")) { ++ return; ++ } ++ gZenPinnedTabManager.onTabIconChanged(aTab, aIconURL); if ( aIconURL && !LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol)) -@@ -1107,6 +1170,9 @@ +@@ -1107,6 +1173,9 @@ ); return; } @@ -142,7 +145,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1379,7 +1445,6 @@ +@@ -1379,7 +1448,6 @@ // Preview mode should not reset the owner if (!this._previewMode && !oldTab.selected) { @@ -150,7 +153,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } let lastRelatedTab = this._lastRelatedTabMap.get(oldTab); -@@ -1470,6 +1535,7 @@ +@@ -1470,6 +1538,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); newTab.updateLastAccessed(); @@ -158,7 +161,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 oldTab.updateLastAccessed(); // if this is the foreground window, update the last-seen timestamps. if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) { -@@ -1622,6 +1688,9 @@ +@@ -1622,6 +1691,9 @@ } let activeEl = document.activeElement; @@ -168,7 +171,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // If focus is on the old tab, move it to the new tab. if (activeEl == oldTab) { newTab.focus(); -@@ -1945,7 +2014,11 @@ +@@ -1945,7 +2017,11 @@ } _setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) { @@ -181,7 +184,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 return false; } -@@ -2053,7 +2126,7 @@ +@@ -2053,7 +2129,7 @@ newIndex = this.selectedTab._tPos + 1; } @@ -190,7 +193,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (this.isTabGroupLabel(targetTab)) { throw new Error( "Replacing a tab group label with a tab is not supported" -@@ -2328,6 +2401,7 @@ +@@ -2328,6 +2404,7 @@ uriIsAboutBlank, userContextId, skipLoad, @@ -198,7 +201,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } = {}) { let b = document.createXULElement("browser"); // Use the JSM global to create the permanentKey, so that if the -@@ -2401,8 +2475,7 @@ +@@ -2401,8 +2478,7 @@ // we use a different attribute name for this? b.setAttribute("name", name); } @@ -208,7 +211,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 b.setAttribute("transparent", "true"); } -@@ -2567,7 +2640,7 @@ +@@ -2567,7 +2643,7 @@ let panel = this.getPanel(browser); let uniqueId = this._generateUniquePanelID(); @@ -217,7 +220,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 aTab.linkedPanel = uniqueId; // Inject the into the DOM if necessary. -@@ -2626,8 +2699,8 @@ +@@ -2626,8 +2702,8 @@ // If we transitioned from one browser to two browsers, we need to set // hasSiblings=false on both the existing browser and the new browser. if (this.tabs.length == 2) { @@ -228,7 +231,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } else { aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1; } -@@ -2814,7 +2887,6 @@ +@@ -2814,7 +2890,6 @@ this.selectedTab = this.addTrustedTab(BROWSER_NEW_TAB_URL, { tabIndex: tab._tPos + 1, userContextId: tab.userContextId, @@ -236,7 +239,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 focusUrlBar: true, }); resolve(this.selectedBrowser); -@@ -2923,6 +2995,9 @@ +@@ -2923,6 +2998,9 @@ schemelessInput, hasValidUserGestureActivation = false, textDirectiveUserActivation = false, @@ -246,7 +249,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } = {} ) { // all callers of addTab that pass a params object need to pass -@@ -2933,10 +3008,17 @@ +@@ -2933,10 +3011,17 @@ ); } @@ -264,7 +267,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // If we're opening a foreground tab, set the owner by default. ownerTab ??= inBackground ? null : this.selectedTab; -@@ -2944,6 +3026,7 @@ +@@ -2944,6 +3029,7 @@ if (this.selectedTab.owner) { this.selectedTab.owner = null; } @@ -272,7 +275,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // Find the tab that opened this one, if any. This is used for // determining positioning, and inherited attributes such as the -@@ -2996,6 +3079,21 @@ +@@ -2996,6 +3082,21 @@ noInitialLabel, skipBackgroundNotify, }); @@ -294,7 +297,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (insertTab) { // Insert the tab into the tab container in the correct position. this.#insertTabAtIndex(t, { -@@ -3004,6 +3102,7 @@ +@@ -3004,6 +3105,7 @@ ownerTab, openerTab, pinned, @@ -302,7 +305,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 bulkOrderedOpen, tabGroup: tabGroup ?? openerTab?.group, }); -@@ -3022,6 +3121,7 @@ +@@ -3022,6 +3124,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -310,7 +313,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 })); if (focusUrlBar) { -@@ -3146,6 +3246,12 @@ +@@ -3146,6 +3249,12 @@ } } @@ -323,7 +326,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // Additionally send pinned tab events if (pinned) { this.#notifyPinnedStatus(t); -@@ -3349,10 +3455,10 @@ +@@ -3349,10 +3458,10 @@ isAdoptingGroup = false, isUserTriggered = false, telemetryUserCreateSource = "unknown", @@ -335,7 +338,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } if (!color) { -@@ -3373,9 +3479,14 @@ +@@ -3373,9 +3482,14 @@ label, isAdoptingGroup ); @@ -352,7 +355,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 ); group.addTabs(tabs); -@@ -3496,7 +3607,7 @@ +@@ -3496,7 +3610,7 @@ } this.#handleTabMove(tab, () => @@ -361,7 +364,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 ); } -@@ -3698,6 +3809,7 @@ +@@ -3698,6 +3812,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -369,7 +372,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } ) { // If we don't have a preferred remote type (or it is `NOT_REMOTE`), and -@@ -3767,6 +3879,7 @@ +@@ -3767,6 +3882,7 @@ openWindowInfo, name, skipLoad, @@ -377,7 +380,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 }); } -@@ -3955,7 +4068,7 @@ +@@ -3955,7 +4071,7 @@ // Add a new tab if needed. if (!tab) { let createLazyBrowser = @@ -386,7 +389,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 let url = "about:blank"; if (tabData.entries?.length) { -@@ -3992,8 +4105,10 @@ +@@ -3992,8 +4108,10 @@ insertTab: false, skipLoad: true, preferredRemoteType, @@ -398,7 +401,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (select) { tabToSelect = tab; } -@@ -4005,7 +4120,8 @@ +@@ -4005,7 +4123,8 @@ this.pinTab(tab); // Then ensure all the tab open/pinning information is sent. this._fireTabOpen(tab, {}); @@ -408,7 +411,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 let { groupId } = tabData; const tabGroup = tabGroupWorkingData.get(groupId); // if a tab refers to a tab group we don't know, skip any group -@@ -4019,7 +4135,10 @@ +@@ -4019,7 +4138,10 @@ tabGroup.stateData.id, tabGroup.stateData.color, tabGroup.stateData.collapsed, @@ -420,7 +423,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 ); tabsFragment.appendChild(tabGroup.node); } -@@ -4064,9 +4183,23 @@ +@@ -4064,9 +4186,23 @@ // to remove the old selected tab. if (tabToSelect) { let leftoverTab = this.selectedTab; @@ -436,15 +439,15 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 + gZenWorkspaces._initialTab._shouldRemove = true; + } + } - } ++ } + else { + gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab; -+ } + } + this._hasAlreadyInitializedZenSessionStore = true; if (tabs.length > 1 || !tabs[0].selected) { this._updateTabsAfterInsert(); -@@ -4257,11 +4390,14 @@ +@@ -4257,11 +4393,14 @@ if (ownerTab) { tab.owner = ownerTab; } @@ -460,7 +463,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if ( !bulkOrderedOpen && ((openerTab && -@@ -4273,7 +4409,7 @@ +@@ -4273,7 +4412,7 @@ let lastRelatedTab = openerTab && this._lastRelatedTabMap.get(openerTab); let previousTab = lastRelatedTab || openerTab || this.selectedTab; @@ -469,7 +472,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 tabGroup = previousTab.group; } if ( -@@ -4284,7 +4420,7 @@ +@@ -4284,7 +4423,7 @@ ) { elementIndex = Infinity; } else if (previousTab.visible) { @@ -478,7 +481,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } else if (previousTab == FirefoxViewHandler.tab) { elementIndex = 0; } -@@ -4312,14 +4448,14 @@ +@@ -4312,14 +4451,14 @@ } // Ensure index is within bounds. if (tab.pinned) { @@ -497,7 +500,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (pinned && !itemAfter?.pinned) { itemAfter = null; -@@ -4330,7 +4466,7 @@ +@@ -4330,7 +4469,7 @@ this.tabContainer._invalidateCachedTabs(); @@ -506,7 +509,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (this.isTab(itemAfter) && itemAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, itemAfter); -@@ -4358,7 +4494,11 @@ +@@ -4358,7 +4497,11 @@ const tabContainer = pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; @@ -518,7 +521,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } this._updateTabsAfterInsert(); -@@ -4366,6 +4506,7 @@ +@@ -4366,6 +4509,7 @@ if (pinned) { this._updateTabBarForPinnedTabs(); } @@ -526,7 +529,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 TabBarVisibility.update(); } -@@ -4916,6 +5057,7 @@ +@@ -4916,6 +5060,7 @@ telemetrySource, } = {} ) { @@ -534,7 +537,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // When 'closeWindowWithLastTab' pref is enabled, closing all tabs // can be considered equivalent to closing the window. if ( -@@ -5005,6 +5147,7 @@ +@@ -5005,6 +5150,7 @@ if (lastToClose) { this.removeTab(lastToClose, aParams); } @@ -542,7 +545,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } catch (e) { console.error(e); } -@@ -5043,6 +5186,12 @@ +@@ -5043,6 +5189,12 @@ aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); } @@ -555,7 +558,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -5057,6 +5206,9 @@ +@@ -5057,6 +5209,9 @@ // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; let isLastTab = this.#isLastTabInWindow(aTab); @@ -565,7 +568,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -5105,7 +5257,13 @@ +@@ -5105,7 +5260,13 @@ // We're not animating, so we can cancel the animation stopwatch. Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId); aTab._closeTimeAnimTimerId = null; @@ -580,7 +583,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 return; } -@@ -5239,7 +5397,7 @@ +@@ -5239,7 +5400,7 @@ closeWindowWithLastTab != null ? closeWindowWithLastTab : !window.toolbar.visible || @@ -589,7 +592,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -5263,6 +5421,7 @@ +@@ -5263,6 +5424,7 @@ newTab = true; } @@ -597,7 +600,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -5303,13 +5462,7 @@ +@@ -5303,13 +5465,7 @@ aTab._mouseleave(); if (newTab) { @@ -612,7 +615,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } else { TabBarVisibility.update(); } -@@ -5442,6 +5595,7 @@ +@@ -5442,6 +5598,7 @@ this.tabs[i]._tPos = i; } @@ -620,7 +623,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (!this._windowIsClosing) { // update tab close buttons state this.tabContainer._updateCloseButtons(); -@@ -5663,6 +5817,7 @@ +@@ -5663,6 +5820,7 @@ } let excludeTabs = new Set(aExcludeTabs); @@ -628,7 +631,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // If this tab has a successor, it should be selectable, since // hiding or closing a tab removes that tab as a successor. -@@ -5675,13 +5830,13 @@ +@@ -5675,13 +5833,13 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -644,7 +647,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 ); let tab = this.tabContainer.findNextTab(aTab, { -@@ -5697,7 +5852,7 @@ +@@ -5697,7 +5855,7 @@ } if (tab) { @@ -653,7 +656,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } // If no qualifying visible tab was found, see if there is a tab in -@@ -5718,7 +5873,7 @@ +@@ -5718,7 +5876,7 @@ }); } @@ -662,7 +665,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } _blurTab(aTab) { -@@ -5729,7 +5884,7 @@ +@@ -5729,7 +5887,7 @@ * @returns {boolean} * False if swapping isn't permitted, true otherwise. */ @@ -671,7 +674,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // Do not allow transfering a private tab to a non-private window // and vice versa. if ( -@@ -5783,6 +5938,7 @@ +@@ -5783,6 +5941,7 @@ // fire the beforeunload event in the process. Close the other // window if this was its last tab. if ( @@ -679,7 +682,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 !remoteBrowser._beginRemoveTab(aOtherTab, { adoptedByTab: aOurTab, closeWindowWithLastTab: true, -@@ -5794,7 +5950,7 @@ +@@ -5794,7 +5953,7 @@ // If this is the last tab of the window, hide the window // immediately without animation before the docshell swap, to avoid // about:blank being painted. @@ -688,7 +691,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (closeWindow) { let win = aOtherTab.ownerGlobal; win.windowUtils.suppressAnimation(true); -@@ -5918,11 +6074,13 @@ +@@ -5918,11 +6077,13 @@ } // Finish tearing down the tab that's going away. @@ -702,7 +705,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 this.setTabTitle(aOurTab); -@@ -6124,10 +6282,10 @@ +@@ -6124,10 +6285,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -715,7 +718,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -6185,7 +6343,8 @@ +@@ -6185,7 +6346,8 @@ * * @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab */ @@ -725,7 +728,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (this.tabs.length == 1) { return null; } -@@ -6209,12 +6368,14 @@ +@@ -6209,12 +6371,14 @@ } // tell a new window to take the "dropped" tab @@ -741,7 +744,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } /** -@@ -6319,7 +6480,7 @@ +@@ -6319,7 +6483,7 @@ * `true` if element is a `` */ isTabGroup(element) { @@ -750,7 +753,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } /** -@@ -6404,8 +6565,8 @@ +@@ -6404,8 +6568,8 @@ } // Don't allow mixing pinned and unpinned tabs. @@ -761,7 +764,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } else { tabIndex = Math.max(tabIndex, this.pinnedTabCount); } -@@ -6431,10 +6592,16 @@ +@@ -6431,10 +6595,16 @@ this.#handleTabMove( element, () => { @@ -780,7 +783,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 if (neighbor && this.isTab(element) && tabIndex > element._tPos) { neighbor.after(element); } else { -@@ -6492,23 +6659,28 @@ +@@ -6492,23 +6662,28 @@ #moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) { if (this.isTabGroupLabel(targetElement)) { targetElement = targetElement.group; @@ -815,7 +818,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } else if (!element.pinned && targetElement && targetElement.pinned) { // If the caller asks to move an unpinned element next to a pinned // tab, move the unpinned element to be the first unpinned element -@@ -6521,14 +6693,34 @@ +@@ -6521,14 +6696,34 @@ // 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. @@ -851,7 +854,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 element.pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; -@@ -6537,7 +6729,7 @@ +@@ -6537,7 +6732,7 @@ element, () => { if (moveBefore) { @@ -860,7 +863,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 } else if (targetElement) { targetElement.after(element); } else { -@@ -6607,10 +6799,10 @@ +@@ -6607,10 +6802,10 @@ * @param {TabMetricsContext} [metricsContext] */ moveTabToGroup(aTab, aGroup, metricsContext) { @@ -873,7 +876,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -6656,6 +6848,7 @@ +@@ -6656,6 +6851,7 @@ let state = { tabIndex: tab._tPos, @@ -881,7 +884,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 }; if (tab.visible) { state.elementIndex = tab.elementIndex; -@@ -6682,7 +6875,7 @@ +@@ -6682,7 +6878,7 @@ let changedTabGroup = previousTabState.tabGroupId != currentTabState.tabGroupId; @@ -890,7 +893,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 tab.dispatchEvent( new CustomEvent("TabMove", { bubbles: true, -@@ -6723,6 +6916,10 @@ +@@ -6723,6 +6919,10 @@ moveActionCallback(); @@ -901,7 +904,15 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -7623,7 +7820,7 @@ +@@ -6815,6 +7015,7 @@ + params.userContextId = aTab.getAttribute("usercontextid"); + } + let newTab = this.addWebTab("about:blank", params); ++ newTab._zenContentsVisible = true; + let newBrowser = this.getBrowserForTab(newTab); + + aTab.container.tabDragAndDrop.finishAnimateTabMove(); +@@ -7623,7 +7824,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -910,7 +921,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 window.focus(); aEvent.preventDefault(); break; -@@ -7640,7 +7837,6 @@ +@@ -7640,7 +7841,6 @@ } case "TabGroupCollapse": aEvent.target.tabs.forEach(tab => { @@ -918,7 +929,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 }); break; case "TabGroupCreateByUser": -@@ -8589,6 +8785,7 @@ +@@ -8589,6 +8789,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -926,7 +937,15 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..ebf699804db90e5509d1b1b704c95f18 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -9623,7 +9820,7 @@ var TabContextMenu = { +@@ -8670,6 +8871,7 @@ + // known defaults. Note we use the original URL since about:newtab + // redirects to a prerendered page. + const shouldRemoveFavicon = ++ !this.mTab.hasAttribute("zen-has-static-icon") && + !this.mBrowser.mIconURL && + !ignoreBlank && + !(originalLocation.spec in FAVICON_DEFAULTS); +@@ -9623,7 +9825,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !this.multiselected; diff --git a/src/browser/themes/shared/tabbrowser/tabs-css.patch b/src/browser/themes/shared/tabbrowser/tabs-css.patch index cd32f20e4..4b21400b2 100644 --- a/src/browser/themes/shared/tabbrowser/tabs-css.patch +++ b/src/browser/themes/shared/tabbrowser/tabs-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css -index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df432311b0081e1 100644 +index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..fef63d687ba4e816d3d36f34d4a39adef06359c9 100644 --- a/browser/themes/shared/tabbrowser/tabs.css +++ b/browser/themes/shared/tabbrowser/tabs.css @@ -21,7 +21,7 @@ @@ -39,12 +39,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 &::before { position: absolute; -@@ -498,14 +498,11 @@ - .tab-icon-image { - -moz-context-properties: fill, stroke; - fill: currentColor; -+ border-radius: 4px; - +@@ -502,10 +502,6 @@ /* stylelint-disable-next-line media-query-no-invalid */ @media -moz-pref("browser.tabs.fadeOutUnloadedTabs") { &[pending] { @@ -55,7 +50,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 opacity: 0.5; /* Fade the favicon out */ transition-property: filter, opacity; -@@ -522,10 +519,6 @@ +@@ -522,10 +518,6 @@ /* stylelint-disable-next-line media-query-no-invalid */ @media -moz-pref("browser.tabs.fadeOutExplicitlyUnloadedTabs") { &[pending][discarded] { @@ -66,7 +61,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 opacity: 0.5; /* Fade the favicon out */ transition-property: filter, opacity; -@@ -593,7 +586,7 @@ +@@ -593,7 +585,7 @@ z-index: 1; /* Overlay tab title */ #tabbrowser-tabs[orient="vertical"] & { @@ -75,7 +70,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 } &[crashed] { -@@ -601,7 +594,7 @@ +@@ -601,7 +593,7 @@ } #tabbrowser-tabs[orient="vertical"]:not([expanded]) &:not([crashed]), @@ -84,7 +79,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 &[soundplaying] { list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-playing-small.svg"); } -@@ -658,7 +651,7 @@ +@@ -658,7 +650,7 @@ } } @@ -93,7 +88,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 &[crashed] { display: revert; } -@@ -759,7 +752,7 @@ +@@ -759,7 +751,7 @@ has not been added to root. There are certain scenarios when that attribute is temporarily removed from root such as when toggling the sidebar to expand with the toolbar button. */ #tabbrowser-tabs[orient="horizontal"] &:not([pinned]):not([crashed]), @@ -102,7 +97,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 &:is([soundplaying], [muted], [activemedia-blocked]) { display: flex; } -@@ -1446,7 +1439,7 @@ tab-group { +@@ -1446,7 +1438,7 @@ tab-group { } #tabbrowser-tabs[orient="vertical"][expanded] { @@ -111,7 +106,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 &[movingtab][movingtab-addToGroup]:not([movingtab-group], [movingtab-ungroup]) .tabbrowser-tab:is(:active, [multiselected]) { margin-inline-start: var(--space-medium); } -@@ -1893,7 +1886,7 @@ tab-group { +@@ -1893,7 +1885,7 @@ tab-group { } } @@ -120,7 +115,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 #vertical-tabs-newtab-button { appearance: none; min-height: var(--tab-min-height); -@@ -1904,7 +1897,7 @@ tab-group { +@@ -1904,7 +1896,7 @@ tab-group { margin-inline: var(--tab-inner-inline-margin); #tabbrowser-tabs[orient="vertical"]:not([expanded]) & > .toolbarbutton-text { @@ -129,7 +124,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 } &:hover { -@@ -1928,7 +1921,7 @@ tab-group { +@@ -1928,7 +1920,7 @@ tab-group { * flex container. #tabs-newtab-button is a child of the arrowscrollbox where * we don't want a gap (between tabs), so we have to add some margin. */ @@ -138,7 +133,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 margin-block: var(--tab-block-margin); } -@@ -2116,7 +2109,6 @@ tab-group { +@@ -2116,7 +2108,6 @@ tab-group { &:not([expanded]) { .tabbrowser-tab[pinned] { @@ -146,7 +141,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 } .tab-background { -@@ -2156,8 +2148,8 @@ tab-group { +@@ -2156,8 +2147,8 @@ tab-group { display: block; position: absolute; inset: auto; @@ -157,7 +152,7 @@ index 8a4d3860b344e2dc2128cfc2b1673de582e19c7c..f8e108d2c1c71070375fdae12df43231 &:-moz-window-inactive { background-image: -@@ -2276,7 +2268,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button { +@@ -2276,7 +2267,6 @@ toolbar:not(#TabsToolbar) #firefox-view-button { list-style-image: url(chrome://global/skin/icons/plus.svg); } diff --git a/src/zen/common/emojis/ZenEmojiPicker.mjs b/src/zen/common/emojis/ZenEmojiPicker.mjs index 0f36a7caf..e20001d25 100644 --- a/src/zen/common/emojis/ZenEmojiPicker.mjs +++ b/src/zen/common/emojis/ZenEmojiPicker.mjs @@ -34,6 +34,7 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { #panel; #anchor; + #emojiAsSVG = false; #currentPromise = null; #currentPromiseResolve = null; @@ -199,14 +200,22 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature { } #selectEmoji(emoji) { + if (this.#emojiAsSVG && emoji && !emoji.startsWith('chrome://')) { + emoji = `data:image/svg+xml;base64,${btoa( + `${unescape( + encodeURIComponent(emoji) + )}` + )}`; + } this.#currentPromiseResolve?.(emoji); this.#panel.hidePopup(); } - open(anchor, { onlySvgIcons = false } = {}) { + open(anchor, { onlySvgIcons = false, emojiAsSVG = false } = {}) { if (this.#currentPromise) { return null; } + this.#emojiAsSVG = emojiAsSVG; this.#currentPromise = new Promise((resolve, reject) => { this.#currentPromiseResolve = resolve; this.#currentPromiseReject = reject; diff --git a/src/zen/common/modules/ZenSessionStore.mjs b/src/zen/common/modules/ZenSessionStore.mjs index 95b2aac20..54739450b 100644 --- a/src/zen/common/modules/ZenSessionStore.mjs +++ b/src/zen/common/modules/ZenSessionStore.mjs @@ -24,6 +24,9 @@ class ZenSessionStore extends nsZenPreloadedFeature { if (tabData.zenHasStaticLabel) { tab.setAttribute('zen-has-static-label', 'true'); } + if (tabData.zenHasStaticIcon) { + tab.setAttribute('zen-has-static-icon', 'true'); + } if (tabData.zenEssential) { tab.setAttribute('zen-essential', 'true'); } diff --git a/src/zen/common/modules/ZenUIManager.mjs b/src/zen/common/modules/ZenUIManager.mjs index 21c95a807..0a9c7fc78 100644 --- a/src/zen/common/modules/ZenUIManager.mjs +++ b/src/zen/common/modules/ZenUIManager.mjs @@ -125,6 +125,8 @@ window.gZenUIManager = { } menu.setAttribute('hidden', 'true'); } + // The first separator in the tab context menu is now useless. + document.getElementById('tabContextMenu').querySelector('menuseparator').remove(); }, _initCreateNewPopup() { @@ -1294,6 +1296,7 @@ window.gZenVerticalTabsManager = { : this._tabEdited; let input = document.getElementById('tab-label-input'); let newName = input.value.replace(/\s+/g, ' ').trim(); + const hasChanged = input.value !== input._originalValue && newName; document.documentElement.removeAttribute('zen-renaming-tab'); input.remove(); @@ -1304,7 +1307,7 @@ window.gZenVerticalTabsManager = { // Always remove, so we can always rename and if it's empty, // it will reset to the original name anyway this._tabEdited.removeAttribute('zen-has-static-label'); - if (newName) { + if (hasChanged) { gBrowser._setTabLabel(this._tabEdited, newName); this._tabEdited.setAttribute('zen-has-static-label', 'true'); gZenUIManager.showToast('zen-tabs-renamed'); @@ -1337,7 +1340,8 @@ window.gZenVerticalTabsManager = { }, renameTabStart(event) { - const isTab = !!event.target.closest('.tabbrowser-tab'); + let target = TabContextMenu.contextTab || event.target; + const isTab = !!target.closest('.tabbrowser-tab'); if ( this._tabEdited || ((!Services.prefs.getBoolPref('zen.tabs.rename-tabs') || @@ -1347,13 +1351,10 @@ window.gZenVerticalTabsManager = { ) return; this._tabEdited = - event.target.closest('.tabbrowser-tab') || - event.target.closest('.zen-current-workspace-indicator-name') || - (event.explicit && event.target.closest('.tab-group-label')); - if ( - !this._tabEdited || - ((!this._tabEdited.pinned || this._tabEdited.hasAttribute('zen-essential')) && isTab) - ) { + target.closest('.tabbrowser-tab') || + target.closest('.zen-current-workspace-indicator-name') || + (event.explicit && target.closest('.tab-group-label')); + if (!this._tabEdited || (this._tabEdited.hasAttribute('zen-essential') && isTab)) { this._tabEdited = null; return; } @@ -1370,8 +1371,10 @@ window.gZenVerticalTabsManager = { label.after(container); } const input = document.createElement('input'); + const content = isTab ? this._tabEdited.label : this._tabEdited.textContent; input.id = 'tab-label-input'; - input.value = isTab ? this._tabEdited.label : this._tabEdited.textContent; + input._originalValue = content; + input.value = content; input.addEventListener('keydown', this.renameTabKeydown.bind(this)); if (isTab) { diff --git a/src/zen/folders/ZenFolders.mjs b/src/zen/folders/ZenFolders.mjs index 01d9f1062..c60b163a0 100644 --- a/src/zen/folders/ZenFolders.mjs +++ b/src/zen/folders/ZenFolders.mjs @@ -100,7 +100,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature { .getElementById('context_zenChangeFolderSpace') .querySelector('menupopup'); changeFolderSpace.innerHTML = ''; - for (const workspace of [...gZenWorkspaces._workspaceCache.workspaces].reverse()) { + for (const workspace of [...gZenWorkspaces.getWorkspaces()].reverse()) { const item = gZenWorkspaces.generateMenuItemForWorkspace(workspace); item.addEventListener('command', (event) => { if (!this.#lastFolderContextMenu) return; @@ -189,7 +189,6 @@ class nsZenFolders extends nsZenDOMOperatedFeature { window.addEventListener('TabSelect', this); window.addEventListener('TabOpen', this); const onNewFolder = this.#onNewFolder.bind(this); - document.getElementById('zen-context-menu-new-folder').addEventListener('command', onNewFolder); document .getElementById('zen-context-menu-new-folder-toolbar') .addEventListener('command', onNewFolder); diff --git a/src/zen/sessionstore/ZenWindowSync.sys.mjs b/src/zen/sessionstore/ZenWindowSync.sys.mjs index e0b0b79d9..861b144cc 100644 --- a/src/zen/sessionstore/ZenWindowSync.sys.mjs +++ b/src/zen/sessionstore/ZenWindowSync.sys.mjs @@ -135,7 +135,9 @@ class nsZenWindowSync { // 1. We are passing `zen-unsynced` in the window arguments. // 2. We are trying to open a link in a new window where other synced // windows already exist - let forcedSync = false; + // Note, we force syncing if the window is private or workspaces is disabled + // to avoid confusing the old private window behavior. + let forcedSync = !aWindow.gZenWorkspaces?.privateWindowOrDisabled; let hasUnsyncedArg = false; if (aWindow._zenStartupSyncFlag === 'synced') { forcedSync = true; @@ -308,12 +310,14 @@ class nsZenWindowSync { } const { gBrowser, gZenFolders } = aWindow; if (flags & SYNC_FLAG_ICON) { + aTargetItem.removeAttribute('zen-has-static-icon'); if (gBrowser.isTab(aOriginalItem)) { gBrowser.setIcon(aTargetItem, gBrowser.getIcon(aOriginalItem)); } else if (aOriginalItem.isZenFolder) { // Icons are a zen-only feature for tab groups. gZenFolders.setFolderUserIcon(aTargetItem, aOriginalItem.iconURL); } + this.#maybeSyncAttributeChange(aOriginalItem, aTargetItem, 'zen-has-static-icon'); } if (flags & SYNC_FLAG_LABEL) { if (gBrowser.isTab(aOriginalItem)) { @@ -797,8 +801,6 @@ class nsZenWindowSync { success = false; continue; } - newTab._zenContentsVisible = true; - gBrowser.setTabTitle(newTab); gZenWorkspaces.moveTabToWorkspace(newTab, aWorkspaceId); } } diff --git a/src/zen/tabs/ZenPinnedTabManager.mjs b/src/zen/tabs/ZenPinnedTabManager.mjs index 182fa63eb..69dde99fe 100644 --- a/src/zen/tabs/ZenPinnedTabManager.mjs +++ b/src/zen/tabs/ZenPinnedTabManager.mjs @@ -463,43 +463,70 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature { data-lazy-l10n-id="tab-context-zen-remove-essential" hidden="true" command="cmd_contextZenRemoveFromEssentials"/> + +