From b801685494f901c15cef51a47cca630cc7a564ed Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Tue, 13 May 2025 22:16:36 +0800 Subject: [PATCH 01/23] Attempt to add keybind for tabs-search --- src/browser/base/content/zen-keysets.inc.xhtml | 1 + src/zen/common/zen-sets.js | 3 +++ src/zen/kbs/ZenKeyboardShortcuts.mjs | 12 ++++++++++++ 3 files changed, 16 insertions(+) diff --git a/src/browser/base/content/zen-keysets.inc.xhtml b/src/browser/base/content/zen-keysets.inc.xhtml index 1b3c25f231..58f3e37f03 100644 --- a/src/browser/base/content/zen-keysets.inc.xhtml +++ b/src/browser/base/content/zen-keysets.inc.xhtml @@ -47,6 +47,7 @@ + diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index 1a8a697d33..d2ead354c3 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -97,6 +97,9 @@ document.addEventListener( case 'cmd_zenIgnoreUnloadTab': gZenTabUnloader.ignoreUnloadTab(); break; + case 'cmd_zenSearchTabs': + gURLBar.search("%"); + break; default: if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) { const index = parseInt(event.target.id.replace('cmd_zenWorkspaceSwitch', ''), 10) - 1; diff --git a/src/zen/kbs/ZenKeyboardShortcuts.mjs b/src/zen/kbs/ZenKeyboardShortcuts.mjs index 9feec1f7e2..ac72d973a0 100644 --- a/src/zen/kbs/ZenKeyboardShortcuts.mjs +++ b/src/zen/kbs/ZenKeyboardShortcuts.mjs @@ -77,6 +77,7 @@ const defaultKeyboardGroups = { ], searchAndFind: [ 'zen-search-focus-shortcut', + 'zen-search-tabs-shortcut', 'zen-search-focus-shortcut-alt', 'zen-find-shortcut', 'zen-search-find-again-shortcut-2', @@ -733,6 +734,17 @@ class ZenKeyboardShortcutsLoader { 'zen-split-view-shortcut-unsplit' ) ); + newShortcutList.push( + new KeyShortcut( + 'zen-search-tabs', + 'J', + '', + ZEN_WORKSPACE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'cmd_zenSearchTabs', + 'zen-search-shortcut-tabs' + ) + ); return newShortcutList; } From d0c8a8683eb1e5f77b647f7783bed31cafeae83b Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Wed, 14 May 2025 15:24:22 +0800 Subject: [PATCH 02/23] Replace focus search (alt) with tabs search --- src/browser/base/content/zen-keysets.inc.xhtml | 2 ++ src/zen/common/zen-sets.js | 2 +- src/zen/kbs/ZenKeyboardShortcuts.mjs | 15 ++++++++++++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/browser/base/content/zen-keysets.inc.xhtml b/src/browser/base/content/zen-keysets.inc.xhtml index 58f3e37f03..a2023b891c 100644 --- a/src/browser/base/content/zen-keysets.inc.xhtml +++ b/src/browser/base/content/zen-keysets.inc.xhtml @@ -47,6 +47,8 @@ + + diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index d2ead354c3..e270d9dd0e 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -98,7 +98,7 @@ document.addEventListener( gZenTabUnloader.ignoreUnloadTab(); break; case 'cmd_zenSearchTabs': - gURLBar.search("%"); + gURLBar.search("% "); break; default: if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) { diff --git a/src/zen/kbs/ZenKeyboardShortcuts.mjs b/src/zen/kbs/ZenKeyboardShortcuts.mjs index ac72d973a0..1296fc5c9f 100644 --- a/src/zen/kbs/ZenKeyboardShortcuts.mjs +++ b/src/zen/kbs/ZenKeyboardShortcuts.mjs @@ -734,15 +734,24 @@ class ZenKeyboardShortcutsLoader { 'zen-split-view-shortcut-unsplit' ) ); + + //tabs search + { + const index = newShortcutList.findIndex(item => item.getID() === 'key_search2'); + if (index !== -1) { + newShortcutList.splice(index, 1); + } + } + newShortcutList.push( new KeyShortcut( 'zen-search-tabs', 'J', '', - ZEN_WORKSPACE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'searchAndFind', + KeyShortcutModifiers.fromObject({ accel: true, alt: false }), 'cmd_zenSearchTabs', - 'zen-search-shortcut-tabs' + 'zen-search-focus-shortcut-alt' ) ); From baea2b5031806a9b9fea8f84b38700a022521b5a Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Wed, 14 May 2025 15:52:34 +0800 Subject: [PATCH 03/23] Update keybind to Alt+Q --- src/zen/kbs/ZenKeyboardShortcuts.mjs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/zen/kbs/ZenKeyboardShortcuts.mjs b/src/zen/kbs/ZenKeyboardShortcuts.mjs index 1296fc5c9f..34db19d7d4 100644 --- a/src/zen/kbs/ZenKeyboardShortcuts.mjs +++ b/src/zen/kbs/ZenKeyboardShortcuts.mjs @@ -736,22 +736,15 @@ class ZenKeyboardShortcutsLoader { ); //tabs search - { - const index = newShortcutList.findIndex(item => item.getID() === 'key_search2'); - if (index !== -1) { - newShortcutList.splice(index, 1); - } - } - newShortcutList.push( new KeyShortcut( 'zen-search-tabs', - 'J', + 'Q', '', 'searchAndFind', - KeyShortcutModifiers.fromObject({ accel: true, alt: false }), + KeyShortcutModifiers.fromObject({ accel: false, alt: true }), 'cmd_zenSearchTabs', - 'zen-search-focus-shortcut-alt' + 'zen-search-shortcut-tabs' ) ); From 59e1d145914bf9286db024aefad8cba96cf5d9d3 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 15 May 2025 16:16:10 +0800 Subject: [PATCH 04/23] Select the first element after envoking keybind --- src/zen/common/zen-sets.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index e270d9dd0e..da8fb88087 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -99,6 +99,14 @@ document.addEventListener( break; case 'cmd_zenSearchTabs': gURLBar.search("% "); + document.activeElement.dispatchEvent( + new KeyboardEvent('keydown', { + keyCode: 40, // keycode for ArrowDown + bubbles: true, + cancelable: true + }) + ); + setTimeout(() => document.activeElement.select(), 100); break; default: if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) { From 7a99f0f9b31cb622e998ed3372c96942bb182433 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 15 May 2025 20:14:22 +0800 Subject: [PATCH 05/23] Fix selecting unloaded tabs will no longer open new tab --- src/zen/workspaces/ZenWorkspaces.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index 06ffab3c71..e353b6ba13 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -3205,7 +3205,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if (!this._hasInitializedTabsStrip) { return gBrowser.browsers; } - const browsers = Array.from(gBrowser.tabpanels.querySelectorAll('browser')); + const browsers = Array.from(this.allStoredTabs).map(tab => tab.linkedBrowser); // Sort browsers by making the current workspace first const currentWorkspace = this.activeWorkspace; const sortedBrowsers = browsers.sort((a, b) => { From 30541aa6933760df7ff04c5888ac9f7438b0d396 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Fri, 16 May 2025 01:02:24 +0800 Subject: [PATCH 06/23] Sort the tabs suggestion by last time tab being opened --- .../tabbrowser/content/tabbrowser-js.patch | 143 ++++++++++-------- .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 24 ++- .../UrlbarProviderOpenTabs-sys-mjs.patch | 120 +++++++++++++++ .../urlbar/UrlbarProviderPlaces-sys-mjs.patch | 44 +++++- .../urlbar/UrlbarUtils-sys-mjs.patch | 14 ++ .../places/PlacesUtils-sys-mjs.patch | 12 ++ .../components/places/nsPlacesTables-h.patch | 12 ++ 7 files changed, 301 insertions(+), 68 deletions(-) create mode 100644 src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch create mode 100644 src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch create mode 100644 src/toolkit/components/places/PlacesUtils-sys-mjs.patch create mode 100644 src/toolkit/components/places/nsPlacesTables-h.patch diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 5bc395be0f..cf47ad6d70 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,8 +1,33 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb6c1a0cf3 100644 +index 6dece2b9d04..4b03c9fef56 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js -@@ -415,11 +415,45 @@ +@@ -117,6 +117,24 @@ + UrlbarProviderOpenTabs: + "resource:///modules/UrlbarProviderOpenTabs.sys.mjs", + }); ++ // Add TabSelect event listener to update open tab information ++ this.tabContainer.addEventListener("TabSelect", async event => { ++ let tab = event.target; ++ let browser = tab.linkedBrowser; ++ let url = browser.currentURI.spec; ++ let userContextId = tab.getAttribute("usercontextid") || 0; ++ let isInPrivateWindow = PrivateBrowsingUtils.isWindowPrivate(window); ++ ++ try { ++ await this.UrlbarProviderOpenTabs.updateOpenTab( ++ url, ++ parseInt(userContextId), ++ isInPrivateWindow ++ ); ++ } catch (error) { ++ console.error("Failed to update open tab:", error); ++ } ++ }); + ChromeUtils.defineLazyGetter(this, "tabLocalization", () => { + return new Localization( + ["browser/tabbrowser.ftl", "branding/brand.ftl"], +@@ -415,11 +433,45 @@ return this.tabContainer.visibleTabs; } @@ -50,7 +75,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } return i; } -@@ -571,6 +605,7 @@ +@@ -571,6 +623,7 @@ this.tabpanels.appendChild(panel); let tab = this.tabs[0]; @@ -58,7 +83,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb tab.linkedPanel = uniqueId; this._selectedTab = tab; this._selectedBrowser = browser; -@@ -836,11 +871,13 @@ +@@ -836,11 +889,13 @@ } this.showTab(aTab); @@ -75,7 +100,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb this.moveTabTo(aTab, { tabIndex: this.pinnedTabCount, forceUngrouped: true, -@@ -857,12 +894,15 @@ +@@ -857,12 +912,15 @@ } if (this.tabContainer.verticalMode) { @@ -92,7 +117,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb }); } else { this.moveTabTo(aTab, { -@@ -1046,6 +1086,8 @@ +@@ -1046,6 +1104,8 @@ let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"]; @@ -101,7 +126,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if ( aIconURL && !aLoadingPrincipal && -@@ -1056,6 +1098,9 @@ +@@ -1056,6 +1116,9 @@ ); return; } @@ -111,7 +136,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1305,6 +1350,7 @@ +@@ -1305,6 +1368,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); newTab.updateLastAccessed(); @@ -119,7 +144,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb oldTab.updateLastAccessed(); // if this is the foreground window, update the last-seen timestamps. if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) { -@@ -1457,6 +1503,9 @@ +@@ -1457,6 +1521,9 @@ } let activeEl = document.activeElement; @@ -129,7 +154,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // If focus is on the old tab, move it to the new tab. if (activeEl == oldTab) { newTab.focus(); -@@ -1780,7 +1829,8 @@ +@@ -1780,7 +1847,8 @@ } _setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) { @@ -139,7 +164,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb return false; } -@@ -1888,7 +1938,7 @@ +@@ -1888,7 +1956,7 @@ newIndex = this.selectedTab._tPos + 1; } @@ -148,7 +173,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (this.isTabGroupLabel(targetTab)) { throw new Error( "Replacing a tab group label with a tab is not supported" -@@ -2152,6 +2202,7 @@ +@@ -2152,6 +2220,7 @@ uriIsAboutBlank, userContextId, skipLoad, @@ -156,7 +181,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } = {}) { let b = document.createXULElement("browser"); // Use the JSM global to create the permanentKey, so that if the -@@ -2225,8 +2276,7 @@ +@@ -2225,8 +2294,7 @@ // we use a different attribute name for this? b.setAttribute("name", name); } @@ -166,7 +191,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb b.setAttribute("transparent", "true"); } -@@ -2391,7 +2441,7 @@ +@@ -2391,7 +2459,7 @@ let panel = this.getPanel(browser); let uniqueId = this._generateUniquePanelID(); @@ -175,7 +200,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb aTab.linkedPanel = uniqueId; // Inject the into the DOM if necessary. -@@ -2450,8 +2500,8 @@ +@@ -2450,8 +2518,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) { @@ -186,7 +211,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } else { aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1; } -@@ -2679,6 +2729,7 @@ +@@ -2679,6 +2747,7 @@ schemelessInput, hasValidUserGestureActivation = false, textDirectiveUserActivation = false, @@ -194,7 +219,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } = {} ) { // all callers of addTab that pass a params object need to pass -@@ -2689,6 +2740,12 @@ +@@ -2689,6 +2758,12 @@ ); } @@ -207,7 +232,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (!UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.start("browser.tabs.opening", "initting", window); } -@@ -2752,6 +2809,16 @@ +@@ -2752,6 +2827,16 @@ noInitialLabel, skipBackgroundNotify, }); @@ -224,7 +249,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (insertTab) { if (typeof index == "number") { elementIndex = this.#tabIndexToElementIndex(index); -@@ -2779,6 +2846,7 @@ +@@ -2779,6 +2864,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -232,7 +257,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb })); if (focusUrlBar) { -@@ -2898,6 +2966,12 @@ +@@ -2898,6 +2984,12 @@ } } @@ -245,7 +270,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // Additionally send pinned tab events if (pinned) { this._notifyPinnedStatus(t); -@@ -2945,12 +3019,15 @@ +@@ -2945,12 +3037,15 @@ * @param {string} [label=] * @returns {MozTabbrowserTabGroup} */ @@ -262,7 +287,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb return group; } -@@ -2993,6 +3070,7 @@ +@@ -2993,6 +3088,7 @@ insertBefore = null, isUserTriggered = false, telemetryUserCreateSource = "unknown", @@ -270,7 +295,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } = {} ) { if (!tabs?.length) { -@@ -3011,7 +3089,12 @@ +@@ -3011,7 +3107,12 @@ id = `${Date.now()}-${Math.round(Math.random() * 100)}`; } let group = this._createTabGroup(id, color, false, label); @@ -284,7 +309,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb group, insertBefore?.group ?? insertBefore ); -@@ -3342,6 +3425,7 @@ +@@ -3342,6 +3443,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -292,7 +317,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } ) { // If we don't have a preferred remote type (or it is `NOT_REMOTE`), and -@@ -3411,6 +3495,7 @@ +@@ -3411,6 +3513,7 @@ openWindowInfo, name, skipLoad, @@ -300,7 +325,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb }); } -@@ -3599,7 +3684,7 @@ +@@ -3599,7 +3702,7 @@ // Add a new tab if needed. if (!tab) { let createLazyBrowser = @@ -309,7 +334,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb let url = "about:blank"; if (tabData.entries?.length) { -@@ -3637,7 +3722,29 @@ +@@ -3637,7 +3740,29 @@ skipLoad: true, preferredRemoteType, }); @@ -339,7 +364,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (select) { tabToSelect = tab; } -@@ -3661,7 +3768,8 @@ +@@ -3661,7 +3786,8 @@ // needs calling: shouldUpdateForPinnedTabs = true; } @@ -349,7 +374,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb let { groupId } = tabData; const tabGroup = tabGroupWorkingData.get(groupId); // if a tab refers to a tab group we don't know, skip any group -@@ -3675,7 +3783,10 @@ +@@ -3675,7 +3801,10 @@ tabGroup.stateData.id, tabGroup.stateData.color, tabGroup.stateData.collapsed, @@ -361,7 +386,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb ); tabsFragment.appendChild(tabGroup.node); } -@@ -3723,8 +3834,16 @@ +@@ -3723,8 +3852,16 @@ // to remove the old selected tab. if (tabToSelect) { let leftoverTab = this.selectedTab; @@ -380,7 +405,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } if (tabs.length > 1 || !tabs[0].selected) { -@@ -3912,7 +4031,7 @@ +@@ -3912,7 +4049,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { // Move the new tab after another tab if needed, to the end otherwise. @@ -389,7 +414,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if ( !bulkOrderedOpen && ((openerTab && -@@ -3935,7 +4054,7 @@ +@@ -3935,7 +4072,7 @@ ) { index = Infinity; } else if (previousTab.visible) { @@ -398,7 +423,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } else if (previousTab == FirefoxViewHandler.tab) { index = 0; } -@@ -3958,18 +4077,18 @@ +@@ -3958,18 +4095,18 @@ // Ensure index is within bounds. if (tab.pinned) { @@ -422,7 +447,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb 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); -@@ -4290,6 +4409,9 @@ +@@ -4290,6 +4427,9 @@ return; } @@ -432,7 +457,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb this.removeTabs(selectedTabs, { telemetrySource }); } -@@ -4542,6 +4664,7 @@ +@@ -4542,6 +4682,7 @@ telemetrySource, } = {} ) { @@ -440,7 +465,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // When 'closeWindowWithLastTab' pref is enabled, closing all tabs // can be considered equivalent to closing the window. if ( -@@ -4626,6 +4749,7 @@ +@@ -4626,6 +4767,7 @@ if (lastToClose) { this.removeTab(lastToClose, aParams); } @@ -448,7 +473,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } catch (e) { console.error(e); } -@@ -4650,6 +4774,7 @@ +@@ -4650,6 +4792,7 @@ telemetrySource, } = {} ) { @@ -456,7 +481,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4663,6 +4788,12 @@ +@@ -4663,6 +4806,12 @@ aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); } @@ -469,7 +494,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4677,7 +4808,9 @@ +@@ -4677,7 +4826,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -480,7 +505,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4840,7 +4973,7 @@ +@@ -4840,7 +4991,7 @@ closeWindowWithLastTab != null ? closeWindowWithLastTab : !window.toolbar.visible || @@ -489,7 +514,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4864,6 +4997,7 @@ +@@ -4864,6 +5015,7 @@ newTab = true; } @@ -497,7 +522,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4903,9 +5037,7 @@ +@@ -4903,9 +5055,7 @@ aTab._mouseleave(); if (newTab) { @@ -508,7 +533,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } else { TabBarVisibility.update(); } -@@ -5034,6 +5166,8 @@ +@@ -5034,6 +5184,8 @@ this.tabs[i]._tPos = i; } @@ -517,7 +542,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -5159,8 +5293,8 @@ +@@ -5159,8 +5311,8 @@ return closedCount; } @@ -528,7 +553,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (unloadBlocked) { return; } -@@ -5248,6 +5382,7 @@ +@@ -5248,6 +5400,7 @@ } let excludeTabs = new Set(aExcludeTabs); @@ -536,7 +561,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // If this tab has a successor, it should be selectable, since // hiding or closing a tab removes that tab as a successor. -@@ -5260,13 +5395,13 @@ +@@ -5260,13 +5413,13 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -552,7 +577,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb ); let tab = this.tabContainer.findNextTab(aTab, { -@@ -5282,7 +5417,7 @@ +@@ -5282,7 +5435,7 @@ } if (tab) { @@ -561,7 +586,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } // If no qualifying visible tab was found, see if there is a tab in -@@ -5303,7 +5438,7 @@ +@@ -5303,7 +5456,7 @@ }); } @@ -570,7 +595,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } _blurTab(aTab) { -@@ -5704,10 +5839,10 @@ +@@ -5704,10 +5857,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -583,7 +608,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -6001,7 +6136,7 @@ +@@ -6001,7 +6154,7 @@ // Don't allow mixing pinned and unpinned tabs. if (this.isTab(element) && element.pinned) { @@ -592,7 +617,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb } else { tabIndex = Math.max(tabIndex, this.pinnedTabCount); } -@@ -6028,9 +6163,16 @@ +@@ -6028,9 +6181,16 @@ element, () => { let neighbor = this.tabs[tabIndex]; @@ -610,7 +635,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (neighbor && this.isTab(element) && tabIndex > element._tPos) { neighbor.after(element); } else { -@@ -6099,7 +6241,9 @@ +@@ -6099,7 +6259,9 @@ targetElement = targetElement.group; } } @@ -621,7 +646,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // Don't allow mixing pinned and unpinned tabs. if (element.pinned && !targetElement?.pinned) { targetElement = this.tabs[this.pinnedTabCount - 1]; -@@ -6109,7 +6253,13 @@ +@@ -6109,7 +6271,13 @@ moveBefore = true; } @@ -635,7 +660,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb if (element.pinned && this.tabContainer.verticalMode) { return this.tabContainer.verticalPinnedTabsContainer; } -@@ -6169,7 +6319,7 @@ +@@ -6169,7 +6337,7 @@ if (!this.isTab(aTab)) { throw new Error("Can only move a tab into a tab group"); } @@ -644,7 +669,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -6263,6 +6413,10 @@ +@@ -6263,6 +6431,10 @@ moveActionCallback(); @@ -655,7 +680,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -7080,7 +7234,7 @@ +@@ -7080,7 +7252,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -664,7 +689,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb window.focus(); aEvent.preventDefault(); break; -@@ -7981,6 +8135,7 @@ +@@ -7981,6 +8153,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -672,7 +697,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8954,7 +9109,7 @@ var TabContextMenu = { +@@ -8954,7 +9127,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !this.multiselected; @@ -681,7 +706,7 @@ index 6dece2b9d0462d90a28e75350ce983d87816ef73..e54e815b04c311464ed53364007d99bb // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -9223,6 +9378,7 @@ var TabContextMenu = { +@@ -9223,6 +9396,7 @@ var TabContextMenu = { telemetrySource: gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP, }); } else { diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 2d6f456e28..c9b4e76df1 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -1,8 +1,28 @@ diff --git a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..8879d657b99cb20cd657c2e4841738ffaa09c658 100644 +index dcf1af43d62..e31b06580cf 100644 --- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs +++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -@@ -794,6 +794,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer { +@@ -117,6 +117,19 @@ class MuxerUnifiedComplete extends UrlbarMuxer { + // When you add state, update _copyState() as necessary. + }; + ++ const allFromPlaces = unsortedResults.every( ++ result => result.providerName === "Places" ++ ); ++ ++ // If all results are from "Places", sort by lastOpened ++ if (allFromPlaces) { ++ unsortedResults.sort((a, b) => { ++ const lastOpenedA = a.payload?.lastOpened || 0; ++ const lastOpenedB = b.payload?.lastOpened|| 0; ++ return lastOpenedB - lastOpenedA; // Descending order ++ }); ++ } ++ + // Do the first pass over all results to build some state. + for (let result of unsortedResults) { + // Add each result to the appropriate `resultsByGroup` map. +@@ -794,6 +807,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer { } if (result.providerName == lazy.UrlbarProviderTabToSearch.name) { diff --git a/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch b/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch new file mode 100644 index 0000000000..0942974ddd --- /dev/null +++ b/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch @@ -0,0 +1,120 @@ +diff --git a/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs b/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs +index 8e76ad53dbc..a4a2663793a 100644 +--- a/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs ++++ b/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs +@@ -241,6 +241,53 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { + await addToMemoryTable(url, userContextId).catch(console.error); + } + ++ /** ++ * Updates the last_opened timestamp for an open tab and ensures it is registered. ++ * ++ * @param {string} url Address of the tab ++ * @param {integer|string} userContextId Containers user context id ++ * @param {boolean} isInPrivateWindow In private browsing window or not ++ * @returns {Promise} resolved after the update. ++ */ ++ static async updateOpenTab(url, userContextId, isInPrivateWindow) { ++ // Ensure userContextId is consistently treated as an integer. ++ userContextId = parseInt(userContextId); ++ if (!Number.isInteger(userContextId)) { ++ lazy.logger.error("Invalid userContextId while updating openTab: ", { ++ url, ++ userContextId, ++ isInPrivateWindow, ++ }); ++ return; ++ } ++ ++ lazy.logger.info("Updating openTab: ", { ++ url, ++ userContextId, ++ isInPrivateWindow, ++ }); ++ ++ // Adjust userContextId for private windows. ++ userContextId = UrlbarProviderOpenTabs.getUserContextIdForOpenPagesTable( ++ userContextId, ++ isInPrivateWindow ++ ); ++ ++ // Ensure the tab is registered in the memory table. ++ let entries = gOpenTabUrls.get(userContextId); ++ if (!entries) { ++ entries = new Map(); ++ gOpenTabUrls.set(userContextId, entries); ++ } ++ if (!entries.has(url)) { ++ entries.set(url, 1); // Register the tab if not already present. ++ await addToMemoryTable(url, userContextId).catch(console.error); ++ } ++ ++ // Update the last_opened timestamp for the tab. ++ await updateLastOpened(url, userContextId).catch(console.error); ++ } ++ + /** + * Unregisters a previously registered open tab. + * +@@ -300,8 +347,9 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { + await UrlbarProviderOpenTabs.promiseDBPopulated; + await conn.executeCached( + ` +- SELECT url, userContextId ++ SELECT url, userContextId, last_opened + FROM moz_openpages_temp ++ ORDER BY last_opened DESC + `, + {}, + (row, cancel) => { +@@ -341,7 +389,7 @@ async function addToMemoryTable(url, userContextId, count = 1) { + let conn = await lazy.PlacesUtils.promiseLargeCacheDBConnection(); + await conn.executeCached( + ` +- INSERT OR REPLACE INTO moz_openpages_temp (url, userContextId, open_count) ++ INSERT OR REPLACE INTO moz_openpages_temp (url, userContextId, open_count, last_opened) + VALUES ( :url, + :userContextId, + IFNULL( ( SELECT open_count + 1 +@@ -349,7 +397,8 @@ async function addToMemoryTable(url, userContextId, count = 1) { + WHERE url = :url + AND userContextId = :userContextId ), + :count +- ) ++ ), ++ strftime('%s', 'now') -- Update the last_opened timestamp + ) + `, + { url, userContextId, count } +@@ -357,6 +406,31 @@ async function addToMemoryTable(url, userContextId, count = 1) { + }); + } + ++/** ++ * Updates the last_opened timestamp for a tab in the memory table. ++ * ++ * @param {string} url Address of the tab ++ * @param {number} userContextId Containers user context id ++ * @returns {Promise} resolved after the update. ++ */ ++async function updateLastOpened(url, userContextId) { ++ if (!UrlbarProviderOpenTabs.memoryTableInitialized) { ++ return; ++ } ++ await lazy.UrlbarProvidersManager.runInCriticalSection(async () => { ++ let conn = await lazy.PlacesUtils.promiseLargeCacheDBConnection(); ++ await conn.executeCached( ++ ` ++ UPDATE moz_openpages_temp ++ SET last_opened = strftime('%s', 'now') -- Update to current timestamp ++ WHERE url = :url ++ AND userContextId = :userContextId ++ `, ++ { url, userContextId } ++ ); ++ }); ++} ++ + /** + * Removes an open page from the memory table. + * diff --git a/src/browser/components/urlbar/UrlbarProviderPlaces-sys-mjs.patch b/src/browser/components/urlbar/UrlbarProviderPlaces-sys-mjs.patch index 089a06c199..e37b8fe311 100644 --- a/src/browser/components/urlbar/UrlbarProviderPlaces-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarProviderPlaces-sys-mjs.patch @@ -1,23 +1,24 @@ diff --git a/browser/components/urlbar/UrlbarProviderPlaces.sys.mjs b/browser/components/urlbar/UrlbarProviderPlaces.sys.mjs -index b1481a11ef..925f0dc34b 100644 +index b1481a11ef3..1697ec38b45 100644 --- a/browser/components/urlbar/UrlbarProviderPlaces.sys.mjs +++ b/browser/components/urlbar/UrlbarProviderPlaces.sys.mjs -@@ -35,6 +35,8 @@ const QUERYINDEX_SWITCHTAB = 9; +@@ -35,6 +35,9 @@ const QUERYINDEX_SWITCHTAB = 9; const QUERYINDEX_FRECENCY = 10; const QUERYINDEX_USERCONTEXTID = 11; const QUERYINDEX_LASTVIST = 12; +const QUERYINDEX_PINNEDTITLE = 13; +const QUERYINDEX_PINNEDURL = 14; ++const QUERYINDEX_LASTOPENED = 15; // Constants to support an alternative frecency algorithm. const PAGES_USE_ALT_FRECENCY = Services.prefs.getBoolPref( -@@ -65,11 +67,14 @@ const SQL_BOOKMARK_TAGS_FRAGMENT = `EXISTS(SELECT 1 FROM moz_bookmarks WHERE fk +@@ -65,11 +68,14 @@ const SQL_BOOKMARK_TAGS_FRAGMENT = `EXISTS(SELECT 1 FROM moz_bookmarks WHERE fk // condition once, and avoid evaluating "btitle" and "tags" when it is false. function defaultQuery(conditions = "") { let query = `SELECT :query_type, h.url, h.title, ${SQL_BOOKMARK_TAGS_FRAGMENT}, - h.visit_count, h.typed, h.id, t.open_count, ${PAGES_FRECENCY_FIELD}, t.userContextId, h.last_visit_date + h.visit_count, h.typed, h.id, t.open_count, ${PAGES_FRECENCY_FIELD}, t.userContextId, h.last_visit_date, -+ zp.title AS pinned_title, zp.url AS pinned_url ++ zp.title AS pinned_title, zp.url AS pinned_url, t.last_opened FROM moz_places h LEFT JOIN moz_openpages_temp t ON t.url = h.url @@ -27,7 +28,7 @@ index b1481a11ef..925f0dc34b 100644 WHERE ( (:switchTabsEnabled AND t.open_count > 0) OR ${PAGES_FRECENCY_FIELD} <> 0 -@@ -83,7 +88,7 @@ function defaultQuery(conditions = "") { +@@ -83,7 +89,7 @@ function defaultQuery(conditions = "") { :matchBehavior, :searchBehavior, NULL) ELSE AUTOCOMPLETE_MATCH(:searchString, h.url, @@ -36,14 +37,38 @@ index b1481a11ef..925f0dc34b 100644 h.visit_count, h.typed, 0, t.open_count, :matchBehavior, :searchBehavior, NULL) -@@ -1132,11 +1137,14 @@ Search.prototype = { +@@ -293,6 +299,7 @@ function convertLegacyMatches(context, matches, urls) { + firstToken: context.tokens[0], + userContextId: match.userContextId, + lastVisit: match.lastVisit, ++ lastOpened: match.lastOpened, + }); + // Should not happen, but better safe than sorry. + if (!result) { +@@ -342,6 +349,7 @@ function makeUrlbarResult(tokens, info) { + icon: info.icon, + userContextId: info.userContextId, + lastVisit: info.lastVisit, ++ lastOpened: info.lastOpened + }); + if (lazy.UrlbarPrefs.get("secondaryActions.switchToTab")) { + payload[0].action = UrlbarUtils.createTabSwitchSecondaryAction( +@@ -414,6 +422,7 @@ function makeUrlbarResult(tokens, info) { + blockL10n, + helpUrl, + lastVisit: info.lastVisit, ++ lastOpened: info.lastOpened, + }) + ); + } +@@ -1132,15 +1141,19 @@ Search.prototype = { let lastVisit = lastVisitPRTime ? lazy.PlacesUtils.toDate(lastVisitPRTime).getTime() : undefined; - + let pinnedTitle = row.getResultByIndex(QUERYINDEX_PINNEDTITLE); + let pinnedUrl = row.getResultByIndex(QUERYINDEX_PINNEDURL); -+ ++ let lastOpened = row.getResultByIndex(QUERYINDEX_LASTOPENED); + let match = { placeId, @@ -54,3 +79,8 @@ index b1481a11ef..925f0dc34b 100644 icon: UrlbarUtils.getIconForUrl(url), frecency: frecency || FRECENCY_DEFAULT, userContextId, + lastVisit, ++ lastOpened: lastOpened || 0 + }; + if (openPageCount > 0 && this.hasBehavior("openpage")) { + if ( diff --git a/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch b/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch new file mode 100644 index 0000000000..ccfbe21d08 --- /dev/null +++ b/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch @@ -0,0 +1,14 @@ +diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs +index 0968dfa8855..a584de03086 100644 +--- a/browser/components/urlbar/UrlbarUtils.sys.mjs ++++ b/browser/components/urlbar/UrlbarUtils.sys.mjs +@@ -1775,6 +1775,9 @@ UrlbarUtils.RESULT_PAYLOAD_SCHEMA = { + lastVisit: { + type: "number", + }, ++ lastOpened: { ++ type: "number", ++ }, + title: { + type: "string", + }, diff --git a/src/toolkit/components/places/PlacesUtils-sys-mjs.patch b/src/toolkit/components/places/PlacesUtils-sys-mjs.patch new file mode 100644 index 0000000000..dd364dd65c --- /dev/null +++ b/src/toolkit/components/places/PlacesUtils-sys-mjs.patch @@ -0,0 +1,12 @@ +diff --git a/toolkit/components/places/PlacesUtils.sys.mjs b/toolkit/components/places/PlacesUtils.sys.mjs +index 572d8678994..618878321bc 100644 +--- a/toolkit/components/places/PlacesUtils.sys.mjs ++++ b/toolkit/components/places/PlacesUtils.sys.mjs +@@ -2248,6 +2248,7 @@ ChromeUtils.defineLazyGetter(lazy, "gAsyncDBLargeCacheConnPromised", () => + url TEXT, + userContextId INTEGER, + open_count INTEGER, ++ last_opened INTEGER, + PRIMARY KEY (url, userContextId) + )`); + await conn.execute(` diff --git a/src/toolkit/components/places/nsPlacesTables-h.patch b/src/toolkit/components/places/nsPlacesTables-h.patch new file mode 100644 index 0000000000..80701009f8 --- /dev/null +++ b/src/toolkit/components/places/nsPlacesTables-h.patch @@ -0,0 +1,12 @@ +diff --git a/toolkit/components/places/nsPlacesTables.h b/toolkit/components/places/nsPlacesTables.h +index bfcc0c24aca..0ad78a3e1cd 100644 +--- a/toolkit/components/places/nsPlacesTables.h ++++ b/toolkit/components/places/nsPlacesTables.h +@@ -196,6 +196,7 @@ + " url TEXT" \ + ", userContextId INTEGER" \ + ", open_count INTEGER" \ ++ ", last_opened INTEGER" \ + ", PRIMARY KEY (url, userContextId)" \ + ")") + From 540da7d406b8ac36f14838250c0d3c31ed739b1d Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Fri, 16 May 2025 01:59:23 +0800 Subject: [PATCH 07/23] Fix schema for url --- .../components/urlbar/UrlbarUtils-sys-mjs.patch | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch b/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch index ccfbe21d08..b058c11cfc 100644 --- a/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs -index 0968dfa8855..a584de03086 100644 +index 0968dfa8855..87974b95053 100644 --- a/browser/components/urlbar/UrlbarUtils.sys.mjs +++ b/browser/components/urlbar/UrlbarUtils.sys.mjs @@ -1775,6 +1775,9 @@ UrlbarUtils.RESULT_PAYLOAD_SCHEMA = { @@ -12,3 +12,13 @@ index 0968dfa8855..a584de03086 100644 title: { type: "string", }, +@@ -1908,6 +1911,9 @@ UrlbarUtils.RESULT_PAYLOAD_SCHEMA = { + lastVisit: { + type: "number", + }, ++ lastOpened: { ++ type: "number", ++ }, + originalUrl: { + type: "string", + }, From cc12958d3bcf62a5091b5af4d77841e836546b8e Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Fri, 16 May 2025 16:07:45 +0800 Subject: [PATCH 08/23] Enable reverse search as well --- .../base/content/zen-keysets.inc.xhtml | 1 + .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 6 ++++-- src/zen/common/zen-sets.js | 21 +++++++++++-------- src/zen/kbs/ZenKeyboardShortcuts.mjs | 12 +++++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/browser/base/content/zen-keysets.inc.xhtml b/src/browser/base/content/zen-keysets.inc.xhtml index a2023b891c..62a0d490ac 100644 --- a/src/browser/base/content/zen-keysets.inc.xhtml +++ b/src/browser/base/content/zen-keysets.inc.xhtml @@ -50,6 +50,7 @@ + diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index c9b4e76df1..5c03b0079f 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -index dcf1af43d62..e31b06580cf 100644 +index dcf1af43d62..17dbaaa66aa 100644 --- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs +++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -@@ -117,6 +117,19 @@ class MuxerUnifiedComplete extends UrlbarMuxer { +@@ -117,6 +117,21 @@ class MuxerUnifiedComplete extends UrlbarMuxer { // When you add state, update _copyState() as necessary. }; @@ -17,6 +17,8 @@ index dcf1af43d62..e31b06580cf 100644 + const lastOpenedB = b.payload?.lastOpened|| 0; + return lastOpenedB - lastOpenedA; // Descending order + }); ++ unsortedResults[0].heuristic = true ++ unsortedResults[0].providerName = "HeuristicFallback" + } + // Do the first pass over all results to build some state. diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index da8fb88087..5eff2b37e4 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -98,15 +98,18 @@ document.addEventListener( gZenTabUnloader.ignoreUnloadTab(); break; case 'cmd_zenSearchTabs': - gURLBar.search("% "); - document.activeElement.dispatchEvent( - new KeyboardEvent('keydown', { - keyCode: 40, // keycode for ArrowDown - bubbles: true, - cancelable: true - }) - ); - setTimeout(() => document.activeElement.select(), 100); + if (!gURLBar.view.isOpen) { + gURLBar.search("% "); + } else { + gURLBar.view.selectBy(1); + } + break; + case 'cmd_zenBackSearchTabs': + if (!gURLBar.view.isOpen) { + gURLBar.search("% "); + } else { + gURLBar.view.selectBy(1, {reverse: true}); + } break; default: if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) { diff --git a/src/zen/kbs/ZenKeyboardShortcuts.mjs b/src/zen/kbs/ZenKeyboardShortcuts.mjs index 34db19d7d4..61cb872ae5 100644 --- a/src/zen/kbs/ZenKeyboardShortcuts.mjs +++ b/src/zen/kbs/ZenKeyboardShortcuts.mjs @@ -748,6 +748,18 @@ class ZenKeyboardShortcutsLoader { ) ); + newShortcutList.push( + new KeyShortcut( + 'zen-back-search-tabs', + 'Q', + '', + 'searchAndFind', + KeyShortcutModifiers.fromObject({ accel: false, alt: true, shift: true }), + 'cmd_zenBackSearchTabs', + 'zen-back-search-shortcut-tabs' + ) + ); + return newShortcutList; } From 4927e12bf48a3592105ad8fcf874104a3ab8b675 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Fri, 16 May 2025 16:37:05 +0800 Subject: [PATCH 09/23] Fix typo --- src/browser/base/content/zen-keysets.inc.xhtml | 2 +- src/zen/common/zen-sets.js | 2 +- src/zen/kbs/ZenKeyboardShortcuts.mjs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/browser/base/content/zen-keysets.inc.xhtml b/src/browser/base/content/zen-keysets.inc.xhtml index 62a0d490ac..51f8147e77 100644 --- a/src/browser/base/content/zen-keysets.inc.xhtml +++ b/src/browser/base/content/zen-keysets.inc.xhtml @@ -50,7 +50,7 @@ - + diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index 5eff2b37e4..0d76c75670 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -104,7 +104,7 @@ document.addEventListener( gURLBar.view.selectBy(1); } break; - case 'cmd_zenBackSearchTabs': + case 'cmd_zenBackwardSearchTabs': if (!gURLBar.view.isOpen) { gURLBar.search("% "); } else { diff --git a/src/zen/kbs/ZenKeyboardShortcuts.mjs b/src/zen/kbs/ZenKeyboardShortcuts.mjs index 61cb872ae5..359c6ff34f 100644 --- a/src/zen/kbs/ZenKeyboardShortcuts.mjs +++ b/src/zen/kbs/ZenKeyboardShortcuts.mjs @@ -750,13 +750,13 @@ class ZenKeyboardShortcutsLoader { newShortcutList.push( new KeyShortcut( - 'zen-back-search-tabs', + 'zen-backward-search-tabs', 'Q', '', 'searchAndFind', KeyShortcutModifiers.fromObject({ accel: false, alt: true, shift: true }), - 'cmd_zenBackSearchTabs', - 'zen-back-search-shortcut-tabs' + 'cmd_zenBackwardSearchTabs', + 'zen-backward-search-shortcut-tabs' ) ); From 564d2b22a647823e7b9e1105a82e97d9c144170a Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Fri, 16 May 2025 18:55:45 +0800 Subject: [PATCH 10/23] Fix tab search selection logic --- src/zen/common/zen-sets.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index 0d76c75670..683e1b1e2e 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -98,17 +98,17 @@ document.addEventListener( gZenTabUnloader.ignoreUnloadTab(); break; case 'cmd_zenSearchTabs': - if (!gURLBar.view.isOpen) { - gURLBar.search("% "); - } else { + if (gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { gURLBar.view.selectBy(1); + } else { + gURLBar.search("% "); } break; case 'cmd_zenBackwardSearchTabs': - if (!gURLBar.view.isOpen) { - gURLBar.search("% "); - } else { + if (gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { gURLBar.view.selectBy(1, {reverse: true}); + } else { + gURLBar.search("% "); } break; default: From d3933853ba31b08c220dedc40cc2d1e12d38c126 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Fri, 16 May 2025 20:59:12 +0800 Subject: [PATCH 11/23] Update heuristic logic for tab search --- .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 5c03b0079f..9d9c9422c2 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -1,17 +1,13 @@ diff --git a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -index dcf1af43d62..17dbaaa66aa 100644 +index dcf1af43d62..116865b068a 100644 --- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs +++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -@@ -117,6 +117,21 @@ class MuxerUnifiedComplete extends UrlbarMuxer { +@@ -117,6 +117,17 @@ class MuxerUnifiedComplete extends UrlbarMuxer { // When you add state, update _copyState() as necessary. }; -+ const allFromPlaces = unsortedResults.every( -+ result => result.providerName === "Places" -+ ); -+ -+ // If all results are from "Places", sort by lastOpened -+ if (allFromPlaces) { ++ let window = Services.wm.getMostRecentWindow("navigator:browser"); ++ if (window && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { + unsortedResults.sort((a, b) => { + const lastOpenedA = a.payload?.lastOpened || 0; + const lastOpenedB = b.payload?.lastOpened|| 0; @@ -24,11 +20,3 @@ index dcf1af43d62..17dbaaa66aa 100644 // Do the first pass over all results to build some state. for (let result of unsortedResults) { // Add each result to the appropriate `resultsByGroup` map. -@@ -794,6 +807,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer { - } - - if (result.providerName == lazy.UrlbarProviderTabToSearch.name) { -+ return false; - // Discard the result if a tab-to-search result was added already. - if (!state.canAddTabToSearch) { - return false; From b6b8a79c25b6cd9374e2c55bd68ea6261ba41c94 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 16:36:30 +0800 Subject: [PATCH 12/23] fix: Update diff into full-index --- .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 14 +++++++++++--- .../urlbar/UrlbarProviderOpenTabs-sys-mjs.patch | 2 +- .../components/urlbar/UrlbarUtils-sys-mjs.patch | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 9d9c9422c2..e1510b204c 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -index dcf1af43d62..116865b068a 100644 +index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac407b03f9 100644 --- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs +++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs @@ -117,6 +117,17 @@ class MuxerUnifiedComplete extends UrlbarMuxer { @@ -7,16 +7,24 @@ index dcf1af43d62..116865b068a 100644 }; + let window = Services.wm.getMostRecentWindow("navigator:browser"); -+ if (window && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { ++ if (window && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode === 4) { + unsortedResults.sort((a, b) => { + const lastOpenedA = a.payload?.lastOpened || 0; + const lastOpenedB = b.payload?.lastOpened|| 0; + return lastOpenedB - lastOpenedA; // Descending order + }); + unsortedResults[0].heuristic = true -+ unsortedResults[0].providerName = "HeuristicFallback" ++ unsortedResults[0].providerName = UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK + } + // Do the first pass over all results to build some state. for (let result of unsortedResults) { // Add each result to the appropriate `resultsByGroup` map. +@@ -794,6 +805,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer { + } + + if (result.providerName == lazy.UrlbarProviderTabToSearch.name) { ++ return false; + // Discard the result if a tab-to-search result was added already. + if (!state.canAddTabToSearch) { + return false; diff --git a/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch b/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch index 0942974ddd..dbc5e21693 100644 --- a/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarProviderOpenTabs-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs b/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs -index 8e76ad53dbc..a4a2663793a 100644 +index 8e76ad53dbc9af7a748b6eecf6ccf7984c61b0b6..a4a2663793a4dcd38fa88fa88c2f30993ba4e49f 100644 --- a/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs +++ b/browser/components/urlbar/UrlbarProviderOpenTabs.sys.mjs @@ -241,6 +241,53 @@ export class UrlbarProviderOpenTabs extends UrlbarProvider { diff --git a/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch b/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch index b058c11cfc..655523a708 100644 --- a/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarUtils-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/urlbar/UrlbarUtils.sys.mjs b/browser/components/urlbar/UrlbarUtils.sys.mjs -index 0968dfa8855..87974b95053 100644 +index 0968dfa885512096f1e58ec898eda139d9aea217..87974b95053bbb2b359bdcf6cf645104314abdca 100644 --- a/browser/components/urlbar/UrlbarUtils.sys.mjs +++ b/browser/components/urlbar/UrlbarUtils.sys.mjs @@ -1775,6 +1775,9 @@ UrlbarUtils.RESULT_PAYLOAD_SCHEMA = { From 0b11190e9404cad6687a548c8d19feee8c6533a9 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 16:38:32 +0800 Subject: [PATCH 13/23] fix: Changed diff into full-index --- src/toolkit/components/places/PlacesUtils-sys-mjs.patch | 2 +- src/toolkit/components/places/nsPlacesTables-h.patch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/toolkit/components/places/PlacesUtils-sys-mjs.patch b/src/toolkit/components/places/PlacesUtils-sys-mjs.patch index dd364dd65c..8e4e808cc6 100644 --- a/src/toolkit/components/places/PlacesUtils-sys-mjs.patch +++ b/src/toolkit/components/places/PlacesUtils-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/toolkit/components/places/PlacesUtils.sys.mjs b/toolkit/components/places/PlacesUtils.sys.mjs -index 572d8678994..618878321bc 100644 +index 572d8678994b338e62f46869a2840948a74a6b1c..618878321bc605fb01d8caba466ff81ccc39fcb8 100644 --- a/toolkit/components/places/PlacesUtils.sys.mjs +++ b/toolkit/components/places/PlacesUtils.sys.mjs @@ -2248,6 +2248,7 @@ ChromeUtils.defineLazyGetter(lazy, "gAsyncDBLargeCacheConnPromised", () => diff --git a/src/toolkit/components/places/nsPlacesTables-h.patch b/src/toolkit/components/places/nsPlacesTables-h.patch index 80701009f8..34a01ed6fb 100644 --- a/src/toolkit/components/places/nsPlacesTables-h.patch +++ b/src/toolkit/components/places/nsPlacesTables-h.patch @@ -1,5 +1,5 @@ diff --git a/toolkit/components/places/nsPlacesTables.h b/toolkit/components/places/nsPlacesTables.h -index bfcc0c24aca..0ad78a3e1cd 100644 +index bfcc0c24aca4fcd951d66bd96c13ebe1a7df32eb..0ad78a3e1cd68b6efc3ea0adbb2553085fec1ef1 100644 --- a/toolkit/components/places/nsPlacesTables.h +++ b/toolkit/components/places/nsPlacesTables.h @@ -196,6 +196,7 @@ From 796adb68182013a25df5837dc2d704722df881dc Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 17:59:37 +0800 Subject: [PATCH 14/23] Add ZenTabSearch --- src/browser/base/content/zen-assets.inc.xhtml | 1 + .../base/content/zen-assets.jar.inc.mn | 2 + src/zen/common/zen-sets.js | 13 +------ src/zen/tabsearch/ZenTabSearch.mjs | 38 +++++++++++++++++++ 4 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 src/zen/tabsearch/ZenTabSearch.mjs diff --git a/src/browser/base/content/zen-assets.inc.xhtml b/src/browser/base/content/zen-assets.inc.xhtml index a22c866350..acb2a69612 100644 --- a/src/browser/base/content/zen-assets.inc.xhtml +++ b/src/browser/base/content/zen-assets.inc.xhtml @@ -44,4 +44,5 @@ Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/Zen Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenGlanceManager.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenMediaController.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenDownloadAnimation.mjs", this); +Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenTabSearch.mjs", this); diff --git a/src/browser/base/content/zen-assets.jar.inc.mn b/src/browser/base/content/zen-assets.jar.inc.mn index b083e20ef2..90ee0206a4 100644 --- a/src/browser/base/content/zen-assets.jar.inc.mn +++ b/src/browser/base/content/zen-assets.jar.inc.mn @@ -61,6 +61,8 @@ content/browser/zen-components/actors/ZenGlanceChild.sys.mjs (../../zen/glance/actors/ZenGlanceChild.sys.mjs) content/browser/zen-components/actors/ZenGlanceParent.sys.mjs (../../zen/glance/actors/ZenGlanceParent.sys.mjs) + content/browser/zen-components/ZenTabSearch.mjs (../../zen/tabsearch/ZenTabSearch.mjs) + content/browser/zen-components/ZenFolders.mjs (../../zen/folders/ZenFolders.mjs) content/browser/zen-styles/zen-folders.css (../../zen/folders/zen-folders.css) diff --git a/src/zen/common/zen-sets.js b/src/zen/common/zen-sets.js index 99fcdacf6a..49670293c1 100644 --- a/src/zen/common/zen-sets.js +++ b/src/zen/common/zen-sets.js @@ -98,19 +98,10 @@ document.addEventListener( gZenTabUnloader.ignoreUnloadTab(); break; case 'cmd_zenSearchTabs': - if (gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { - gURLBar.view.selectBy(1); - } else { - gURLBar.search("% "); - } + gZenTabSearch.searchTabsShortcut(); break; case 'cmd_zenBackwardSearchTabs': - if (gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { - gURLBar.view.selectBy(1, {reverse: true}); - } else { - gURLBar.search("% "); - } - break; + gZenTabSearch.searchTabsShortcut(-1); default: if (event.target.id.startsWith('cmd_zenWorkspaceSwitch')) { const index = parseInt(event.target.id.replace('cmd_zenWorkspaceSwitch', ''), 10) - 1; diff --git a/src/zen/tabsearch/ZenTabSearch.mjs b/src/zen/tabsearch/ZenTabSearch.mjs new file mode 100644 index 0000000000..c46b756f0a --- /dev/null +++ b/src/zen/tabsearch/ZenTabSearch.mjs @@ -0,0 +1,38 @@ +{ + class ZenTabSearch extends ZenDOMOperatedFeature { + init() { + this._counter = 0; + window.addEventListener('keyup', this._handleKeyUp, true); + } + + _handleKeyUp(event) { + console.log('Key up event:', event); + if (event.key === 'Alt' || event.key === 'Control') { + if (window.gZenTabSearch > 0 && gURLBar.view.isOpen && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { + // simulate enter key press + const enterEvent = new KeyboardEvent('keydown', { + key: 'Enter', + code: 'Enter', + keyCode: 13, + which: 13, + bubbles: true, + cancelable: true, + }); + gURLBar.handleCommand(enterEvent); + } + } + } + + async searchTabsShortcut(offset = 1) { + if (gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { + this._counter += 1; + gURLBar.view.selectBy(offset); + } else { + gURLBar.search("% "); + this._counter = 0; + } + } + } + + window.gZenTabSearch = new ZenTabSearch(); +} From bfeb730249622954f32f8d30f223a1e1e37f7d7c Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 18:24:15 +0800 Subject: [PATCH 15/23] style: Format code --- src/zen/tabsearch/ZenTabSearch.mjs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/zen/tabsearch/ZenTabSearch.mjs b/src/zen/tabsearch/ZenTabSearch.mjs index c46b756f0a..1883d6824b 100644 --- a/src/zen/tabsearch/ZenTabSearch.mjs +++ b/src/zen/tabsearch/ZenTabSearch.mjs @@ -6,9 +6,12 @@ } _handleKeyUp(event) { - console.log('Key up event:', event); if (event.key === 'Alt' || event.key === 'Control') { - if (window.gZenTabSearch > 0 && gURLBar.view.isOpen && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { + if ( + window.gZenTabSearch._counter > 0 && + gURLBar.view.isOpen && + gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ + ) { // simulate enter key press const enterEvent = new KeyboardEvent('keydown', { key: 'Enter', @@ -19,16 +22,28 @@ cancelable: true, }); gURLBar.handleCommand(enterEvent); + this._counter = 0; + event.preventDefault(); + event.stopImmediatePropagation(); + return; } } } async searchTabsShortcut(offset = 1) { - if (gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */) { + if ( + gURLBar.view.isOpen && + gURLBar.searchMode && + gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ + ) { this._counter += 1; - gURLBar.view.selectBy(offset); + if (offset > 0) { + gURLBar.view.selectBy(offset); + } else if (offset < 0) { + gURLBar.view.selectBy(-offset, {reverse: true}); + } } else { - gURLBar.search("% "); + gURLBar.search('% '); this._counter = 0; } } From 555d84732b9f91e99859e78c1b9a39d9a6dd4868 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 19:21:10 +0800 Subject: [PATCH 16/23] fix: Change tab result to heuristic --- .../components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index e1510b204c..7e16603840 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -7,7 +7,7 @@ index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac }; + let window = Services.wm.getMostRecentWindow("navigator:browser"); -+ if (window && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode === 4) { ++ if (window && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { + unsortedResults.sort((a, b) => { + const lastOpenedA = a.payload?.lastOpened || 0; + const lastOpenedB = b.payload?.lastOpened|| 0; From d4c0571167ce879a95324b7e9c48d6f7ae5e9766 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 19:53:05 +0800 Subject: [PATCH 17/23] fix: Change heuristic provider name --- .../components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 7e16603840..53f18e502f 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -14,7 +14,7 @@ index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac + return lastOpenedB - lastOpenedA; // Descending order + }); + unsortedResults[0].heuristic = true -+ unsortedResults[0].providerName = UrlbarUtils.RESULT_GROUP.HEURISTIC_FALLBACK ++ unsortedResults[0].providerName = "HeuristicFallback" + } + // Do the first pass over all results to build some state. From 036aab6f0745a6146bbce3e8162f815134766325 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 20:18:19 +0800 Subject: [PATCH 18/23] feat: Add auto select tab prefs --- src/browser/app/profile/features.inc | 2 + .../components/preferences/zen-settings.js | 5 ++ .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 10 ++-- src/zen/tabsearch/ZenTabSearch.mjs | 53 ++++++++++++++----- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/browser/app/profile/features.inc b/src/browser/app/profile/features.inc index 83993709f1..ca809dc697 100644 --- a/src/browser/app/profile/features.inc +++ b/src/browser/app/profile/features.inc @@ -78,6 +78,8 @@ pref('zen.glance.hold-duration', 300); // in ms pref('zen.glance.open-essential-external-links', true); pref('zen.glance.activation-method', 'alt'); // ctrl, alt, shift, none, hold +pref('zen.tabsearch.auto-select-result', false); + pref('zen.view.sidebar-height-throttle', 200); // in ms pref('zen.view.sidebar-expanded.max-width', 500); diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index 512d2e91d0..1fad4b814e 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -1169,6 +1169,11 @@ Preferences.addAll([ type: 'bool', default: true, }, + { + id: 'zen.tabsearch.auto-select-result', + type: 'bool', + default: false, + }, { id: 'zen.theme.color-prefs.use-workspace-colors', type: 'bool', diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 53f18e502f..6e9145f118 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -2,19 +2,21 @@ diff --git a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs b/brow index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac407b03f9 100644 --- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs +++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.sys.mjs -@@ -117,6 +117,17 @@ class MuxerUnifiedComplete extends UrlbarMuxer { +@@ -117,6 +117,19 @@ class MuxerUnifiedComplete extends UrlbarMuxer { // When you add state, update _copyState() as necessary. }; + let window = Services.wm.getMostRecentWindow("navigator:browser"); -+ if (window && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { ++ if (window && window.gZenTabSearch && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { + unsortedResults.sort((a, b) => { + const lastOpenedA = a.payload?.lastOpened || 0; + const lastOpenedB = b.payload?.lastOpened|| 0; + return lastOpenedB - lastOpenedA; // Descending order + }); -+ unsortedResults[0].heuristic = true -+ unsortedResults[0].providerName = "HeuristicFallback" ++ if (window.gZenTabSearch._autoSelectResult === false || window.gZenTabSearch._counter > 0) { ++ unsortedResults[0].heuristic = true ++ unsortedResults[0].providerName = "HeuristicFallback" ++ } + } + // Do the first pass over all results to build some state. diff --git a/src/zen/tabsearch/ZenTabSearch.mjs b/src/zen/tabsearch/ZenTabSearch.mjs index 1883d6824b..0abe87c808 100644 --- a/src/zen/tabsearch/ZenTabSearch.mjs +++ b/src/zen/tabsearch/ZenTabSearch.mjs @@ -2,26 +2,49 @@ class ZenTabSearch extends ZenDOMOperatedFeature { init() { this._counter = 0; + this._updateAutoSelectResult = this._updateAutoSelectResult.bind(this); + this._handleKeyUp = this._handleKeyUp.bind(this); + this._autoSelectResult = Services.prefs.getBoolPref( + 'zen.tabsearch.auto-select-result', + false + ); + window.addEventListener('keyup', this._handleKeyUp, true); + + Services.prefs.addObserver( + 'zen.tabsearch.auto-select-result', + this._updateAutoSelectResult, + false + ); + this._updateAutoSelectResult(); + } + + _updateAutoSelectResult() { + this._autoSelectResult = Services.prefs.getBoolPref( + 'zen.tabsearch.auto-select-result', + false + ); } _handleKeyUp(event) { if (event.key === 'Alt' || event.key === 'Control') { if ( - window.gZenTabSearch._counter > 0 && + this._counter > 0 && gURLBar.view.isOpen && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ ) { // simulate enter key press - const enterEvent = new KeyboardEvent('keydown', { - key: 'Enter', - code: 'Enter', - keyCode: 13, - which: 13, - bubbles: true, - cancelable: true, - }); - gURLBar.handleCommand(enterEvent); + if (this._autoSelectResult) { + const enterEvent = new KeyboardEvent('keydown', { + key: 'Enter', + code: 'Enter', + keyCode: 13, + which: 13, + bubbles: true, + cancelable: true, + }); + gURLBar.handleCommand(enterEvent); + } this._counter = 0; event.preventDefault(); event.stopImmediatePropagation(); @@ -37,10 +60,12 @@ gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ ) { this._counter += 1; - if (offset > 0) { - gURLBar.view.selectBy(offset); - } else if (offset < 0) { - gURLBar.view.selectBy(-offset, {reverse: true}); + if (gURLBar.view.visibleRowCount > 0) { + if (offset > 0) { + gURLBar.view.selectBy(offset); + } else if (offset < 0) { + gURLBar.view.selectBy(-offset, { reverse: true }); + } } } else { gURLBar.search('% '); From 628a47f5e722c0e37644595307fe5a82a3b71d77 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 21:22:27 +0800 Subject: [PATCH 19/23] fix: Try change logic of tab search --- .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 4 +-- src/zen/tabsearch/ZenTabSearch.mjs | 28 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 6e9145f118..9c6938cf09 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -13,10 +13,10 @@ index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac + const lastOpenedB = b.payload?.lastOpened|| 0; + return lastOpenedB - lastOpenedA; // Descending order + }); -+ if (window.gZenTabSearch._autoSelectResult === false || window.gZenTabSearch._counter > 0) { ++ if (!window.gZenTabSearch.autoSelectResult || window.gZenTabSearch.shouldInjectHeuristic ) { + unsortedResults[0].heuristic = true + unsortedResults[0].providerName = "HeuristicFallback" -+ } ++ } else { window.gZenTabSearch.shouldInjectHeuristic = true; } + } + // Do the first pass over all results to build some state. diff --git a/src/zen/tabsearch/ZenTabSearch.mjs b/src/zen/tabsearch/ZenTabSearch.mjs index 0abe87c808..985f0608b9 100644 --- a/src/zen/tabsearch/ZenTabSearch.mjs +++ b/src/zen/tabsearch/ZenTabSearch.mjs @@ -1,13 +1,11 @@ { class ZenTabSearch extends ZenDOMOperatedFeature { init() { - this._counter = 0; + this._triggerCounter = 0; + this.shouldInjectHeuristic = true; this._updateAutoSelectResult = this._updateAutoSelectResult.bind(this); this._handleKeyUp = this._handleKeyUp.bind(this); - this._autoSelectResult = Services.prefs.getBoolPref( - 'zen.tabsearch.auto-select-result', - false - ); + this.autoSelectResult = Services.prefs.getBoolPref('zen.tabsearch.auto-select-result', false); window.addEventListener('keyup', this._handleKeyUp, true); @@ -20,21 +18,18 @@ } _updateAutoSelectResult() { - this._autoSelectResult = Services.prefs.getBoolPref( - 'zen.tabsearch.auto-select-result', - false - ); + this.autoSelectResult = Services.prefs.getBoolPref('zen.tabsearch.auto-select-result', false); } _handleKeyUp(event) { if (event.key === 'Alt' || event.key === 'Control') { if ( - this._counter > 0 && + this._triggerCounter > 0 && gURLBar.view.isOpen && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ ) { // simulate enter key press - if (this._autoSelectResult) { + if (this.autoSelectResult) { const enterEvent = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', @@ -44,8 +39,9 @@ cancelable: true, }); gURLBar.handleCommand(enterEvent); + this.shouldInjectHeuristic = false; } - this._counter = 0; + this._triggerCounter = 0; event.preventDefault(); event.stopImmediatePropagation(); return; @@ -54,12 +50,13 @@ } async searchTabsShortcut(offset = 1) { + // if the search is already open, we just need to select the next result if ( gURLBar.view.isOpen && gURLBar.searchMode && gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ ) { - this._counter += 1; + this._triggerCounter += 1; if (gURLBar.view.visibleRowCount > 0) { if (offset > 0) { gURLBar.view.selectBy(offset); @@ -68,8 +65,11 @@ } } } else { + this._triggerCounter = 0; + if (this.autoSelectResult) { + this.shouldInjectHeuristic = false; + } gURLBar.search('% '); - this._counter = 0; } } } From 5d3e6d2607b673c520744096a8c598f291ef0fe5 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 23:25:28 +0800 Subject: [PATCH 20/23] feat: Add new prefs to enable tab search --- src/browser/app/profile/features.inc | 1 + src/browser/components/preferences/zen-settings.js | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/browser/app/profile/features.inc b/src/browser/app/profile/features.inc index ca809dc697..4db348e569 100644 --- a/src/browser/app/profile/features.inc +++ b/src/browser/app/profile/features.inc @@ -78,6 +78,7 @@ pref('zen.glance.hold-duration', 300); // in ms pref('zen.glance.open-essential-external-links', true); pref('zen.glance.activation-method', 'alt'); // ctrl, alt, shift, none, hold +pref('zen.tabsearch.enabled', true); pref('zen.tabsearch.auto-select-result', false); pref('zen.view.sidebar-height-throttle', 200); // in ms diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index 1fad4b814e..b6db55d1e7 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -1169,6 +1169,11 @@ Preferences.addAll([ type: 'bool', default: true, }, + { + id: 'zen.tabsearch.enabled', + type: 'bool', + default: true, + }, { id: 'zen.tabsearch.auto-select-result', type: 'bool', From 5874711db2f573992be92ee08c08fd985d299ccb Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 23:26:14 +0800 Subject: [PATCH 21/23] fix: Changed logic for tab search --- .../UrlbarMuxerUnifiedComplete-sys-mjs.patch | 4 +- src/zen/tabsearch/ZenTabSearch.mjs | 75 ++++++++++++++----- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 9c6938cf09..47f9baafe3 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -13,10 +13,10 @@ index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac + const lastOpenedB = b.payload?.lastOpened|| 0; + return lastOpenedB - lastOpenedA; // Descending order + }); -+ if (!window.gZenTabSearch.autoSelectResult || window.gZenTabSearch.shouldInjectHeuristic ) { ++ if (window.gZenTabSearch.shouldInjectHeuristic()) { + unsortedResults[0].heuristic = true + unsortedResults[0].providerName = "HeuristicFallback" -+ } else { window.gZenTabSearch.shouldInjectHeuristic = true; } ++ } + } + // Do the first pass over all results to build some state. diff --git a/src/zen/tabsearch/ZenTabSearch.mjs b/src/zen/tabsearch/ZenTabSearch.mjs index 985f0608b9..d57fe56be8 100644 --- a/src/zen/tabsearch/ZenTabSearch.mjs +++ b/src/zen/tabsearch/ZenTabSearch.mjs @@ -1,30 +1,64 @@ { class ZenTabSearch extends ZenDOMOperatedFeature { init() { - this._triggerCounter = 0; - this.shouldInjectHeuristic = true; + this._heuristic = false; this._updateAutoSelectResult = this._updateAutoSelectResult.bind(this); this._handleKeyUp = this._handleKeyUp.bind(this); - this.autoSelectResult = Services.prefs.getBoolPref('zen.tabsearch.auto-select-result', false); - - window.addEventListener('keyup', this._handleKeyUp, true); - Services.prefs.addObserver( 'zen.tabsearch.auto-select-result', this._updateAutoSelectResult, false ); this._updateAutoSelectResult(); + window.setTimeout(() => { + this._setupListener(); + }, 500); } _updateAutoSelectResult() { this.autoSelectResult = Services.prefs.getBoolPref('zen.tabsearch.auto-select-result', false); } + _setupListener() { + // Ensure gURLBar, its panel, and inputField are available + if (typeof gURLBar !== 'undefined') { + console.log('gURLBar or its components are not yet initialized'); + // Bind the handlers to this instance for correct 'this' and removal + const self = this; // Capture the correct 'this' context + gURLBar.controller.addQueryListener({ + onViewOpen() { + window.addEventListener('keyup', self._handleKeyUp, true); + self._heuristic = false; + }, + onViewClose() { + window.removeEventListener('keyup', self._handleKeyUp, true); + self._heuristic = false; + }, + onQueryStarted() { + window.removeEventListener('keyup', self._handleKeyUp, true); + }, + onQueryFinished() { + self._heuristic = true; + }, + + }); + } else { + // Retry if gURLBar or its components are not yet initialized + window.setTimeout(() => { + // 'this' here will refer to the ZenTabSearch instance because + // setTimeout is called on 'window', and the callback is an arrow function, + // which lexically captures 'this' from the surrounding scope (the catch block). + // In the catch block, 'this' is the ZenTabSearch instance. + this._setupListener(); + }, 500); + } + } + _handleKeyUp(event) { if (event.key === 'Alt' || event.key === 'Control') { if ( - this._triggerCounter > 0 && + this._heuristic && + this.autoSelectResult && gURLBar.view.isOpen && gURLBar.searchMode?.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ ) { @@ -39,16 +73,21 @@ cancelable: true, }); gURLBar.handleCommand(enterEvent); - this.shouldInjectHeuristic = false; + event.preventDefault(); + event.stopImmediatePropagation(); } - this._triggerCounter = 0; - event.preventDefault(); - event.stopImmediatePropagation(); - return; + } else { + // window.removeEventListener('keyup', this._handleKeyUp, true); } } } + shouldInjectHeuristic() { + if (!this.autoSelectResult) return true; + if (this._heuristic) return true; + return false; + } + async searchTabsShortcut(offset = 1) { // if the search is already open, we just need to select the next result if ( @@ -56,23 +95,23 @@ gURLBar.searchMode && gURLBar.searchMode.source === 4 /* URLBarUtils.RESULT_SOURCE.TABS */ ) { - this._triggerCounter += 1; if (gURLBar.view.visibleRowCount > 0) { if (offset > 0) { gURLBar.view.selectBy(offset); } else if (offset < 0) { gURLBar.view.selectBy(-offset, { reverse: true }); } + window.addEventListener('keyup', this._handleKeyUp, true); + this._heuristic = true; } } else { - this._triggerCounter = 0; - if (this.autoSelectResult) { - this.shouldInjectHeuristic = false; - } gURLBar.search('% '); + this._heuristic = false; } } } - window.gZenTabSearch = new ZenTabSearch(); + if (Services.prefs.getBoolPref('zen.tabsearch.enabled', true)) { + window.gZenTabSearch = new ZenTabSearch(); + } } From 4e8308414afaee7259da839570e4f98078dfbed3 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 23:26:45 +0800 Subject: [PATCH 22/23] fix: Changed the order of the shortcuts in settings --- src/zen/kbs/ZenKeyboardShortcuts.mjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/zen/kbs/ZenKeyboardShortcuts.mjs b/src/zen/kbs/ZenKeyboardShortcuts.mjs index 359c6ff34f..ca088946f9 100644 --- a/src/zen/kbs/ZenKeyboardShortcuts.mjs +++ b/src/zen/kbs/ZenKeyboardShortcuts.mjs @@ -738,25 +738,25 @@ class ZenKeyboardShortcutsLoader { //tabs search newShortcutList.push( new KeyShortcut( - 'zen-search-tabs', + 'zen-backward-search-tabs', 'Q', '', 'searchAndFind', - KeyShortcutModifiers.fromObject({ accel: false, alt: true }), - 'cmd_zenSearchTabs', - 'zen-search-shortcut-tabs' + KeyShortcutModifiers.fromObject({ accel: false, alt: true, shift: true }), + 'cmd_zenBackwardSearchTabs', + 'zen-backward-search-shortcut-tabs' ) ); - + newShortcutList.push( new KeyShortcut( - 'zen-backward-search-tabs', + 'zen-search-tabs', 'Q', '', 'searchAndFind', - KeyShortcutModifiers.fromObject({ accel: false, alt: true, shift: true }), - 'cmd_zenBackwardSearchTabs', - 'zen-backward-search-shortcut-tabs' + KeyShortcutModifiers.fromObject({ accel: false, alt: true }), + 'cmd_zenSearchTabs', + 'zen-search-shortcut-tabs' ) ); From 9b3439467ed76dacb56b6eaaebd1a2b201dba105 Mon Sep 17 00:00:00 2001 From: Stefan Tanuwijaya Date: Thu, 22 May 2025 23:37:24 +0800 Subject: [PATCH 23/23] fix: Avoid error when pref is not enabled --- src/browser/components/preferences/zen-settings.js | 1 + .../components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index b6db55d1e7..31ec22939b 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -777,6 +777,7 @@ var gZenWorkspacesSettings = { }; Services.prefs.addObserver('zen.tab-unloader.enabled', tabsUnloaderPrefListener); Services.prefs.addObserver('zen.glance.enabled', tabsUnloaderPrefListener); // We can use the same listener for both prefs + Services.prefs.addObserver('zen.tabsearch.enabled', tabsUnloaderPrefListener); // We can use the same listener for both prefs Services.prefs.addObserver( 'zen.workspaces.container-specific-essentials-enabled', tabsUnloaderPrefListener diff --git a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch index 47f9baafe3..bcd54408c6 100644 --- a/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarMuxerUnifiedComplete-sys-mjs.patch @@ -7,7 +7,7 @@ index dcf1af43d62979d3226d7f704c51a2f0bb935cc0..a8271ac083c54947756e6ef35a3b4eac }; + let window = Services.wm.getMostRecentWindow("navigator:browser"); -+ if (window && window.gZenTabSearch && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { ++ if (window && typeof window.gZenTabSearch !== "undefined" && window.gURLBar && window.gURLBar.searchMode && window.gURLBar.searchMode.source === 4) { + unsortedResults.sort((a, b) => { + const lastOpenedA = a.payload?.lastOpened || 0; + const lastOpenedB = b.payload?.lastOpened|| 0;