diff --git a/README.md b/README.md index 4211fac39..538f3a383 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ Zen is a firefox-based browser with the aim of pushing your productivity to a ne ### Firefox Versions -- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `145.0`! 🚀 -- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 145.0`! +- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `145.0.1`! 🚀 +- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 145.0.1`! ### Contributing diff --git a/build/firefox-cache/l10n-last-commit-hash b/build/firefox-cache/l10n-last-commit-hash index c1019bcb9..9839d1fa1 100644 --- a/build/firefox-cache/l10n-last-commit-hash +++ b/build/firefox-cache/l10n-last-commit-hash @@ -1 +1 @@ -1e325bc45d9111518958446ac966fd4e4136d6d5 \ No newline at end of file +99a389c2413be0374ee04b10021ed269c0387b45 \ No newline at end of file diff --git a/locales/id/browser/browser/preferences/zen-preferences.ftl b/locales/id/browser/browser/preferences/zen-preferences.ftl index 545fe2901..71e6c6754 100644 --- a/locales/id/browser/browser/preferences/zen-preferences.ftl +++ b/locales/id/browser/browser/preferences/zen-preferences.ftl @@ -45,9 +45,9 @@ pane-settings-workspaces-title = Ruang Kerja zen-tabs-unloader-enabled = .label = Aktifkan Pelepas Tab zen-tabs-close-on-back-with-no-history = - .label = Close tab and switch to its owner tab (or most recently used tab) when going back with no history + .label = Tutup tab dan beralih ke tab pemiliknya (atau tab yang terakhir digunakan) saat kembali tanpa riwayat zen-tabs-cycle-by-attribute = - .label = Ctrl+Tab cycles within Essential or Workspace tabs only + .label = Ctrl+Tab berputar hanya dalam tab Esensial atau Ruang Kerja zen-tabs-cycle-ignore-pending-tabs = .label = Ignore Pending tabs when cycling with Ctrl+Tab zen-tabs-cycle-by-attribute-warning = Ctrl+Tab will cycle by recently used order, as it is enabled @@ -311,4 +311,4 @@ zen-devtools-toggle-performance-shortcut = Ubah Performance zen-devtools-toggle-storage-shortcut = Ubah Penyimpanan zen-devtools-toggle-dom-shortcut = Ubah DOM zen-devtools-toggle-accessibility-shortcut = Ubah Aksesibilitas -zen-close-all-unpinned-tabs-shortcut = Close All Unpinned Tabs +zen-close-all-unpinned-tabs-shortcut = Tutup Semua Tab yang Tidak Disematkan diff --git a/locales/id/browser/browser/zen-general.ftl b/locales/id/browser/browser/zen-general.ftl index 4451a416f..90d834f96 100644 --- a/locales/id/browser/browser/zen-general.ftl +++ b/locales/id/browser/browser/zen-general.ftl @@ -8,9 +8,9 @@ tab-context-zen-reset-pinned-tab = .label = Kembalikan ke URL Awal .accesskey = R tab-context-zen-add-essential = - .label = Add to Essentials + .label = Tambahkan ke Essentials .accesskey = E -tab-context-zen-add-essential-badge = { $num } / { $max } slots filled +tab-context-zen-add-essential-badge = { $num } / { $max } slot terisi tab-context-zen-remove-essential = .label = Hapus dari Essentials .accesskey = R @@ -96,5 +96,5 @@ zen-site-data-setting-site-protection = Perlindungan Pelacakan zen-site-data-panel-feature-callout-title = Rumah baru untuk add-on, izin, dan lainnya zen-site-data-panel-feature-callout-subtitle = Klik ikon untuk mengelola pengaturan situs, melihat info keamanan, mengakses ekstensi, dan melakukan tindakan umum. zen-open-link-in-glance = - .label = Open Link in Glance + .label = Buka Tautan di Glance .accesskey = G diff --git a/locales/id/browser/browser/zen-workspaces.ftl b/locales/id/browser/browser/zen-workspaces.ftl index 25a94b3c3..dd99d5d3b 100644 --- a/locales/id/browser/browser/zen-workspaces.ftl +++ b/locales/id/browser/browser/zen-workspaces.ftl @@ -59,7 +59,7 @@ zen-workspaces-delete-workspace-title = Delete Workspace? zen-workspaces-delete-workspace-body = Apakah Anda yakin ingin menghapus { $name }? Tindakan ini tidak bisa dibatalkan. # Note that the html tag MUST not be changed or removed, as it is used to better # display the shortcut in the toast notification. -zen-workspaces-close-all-unpinned-tabs-toast = Tabs Closed! Use { $shortcut } to undo. +zen-workspaces-close-all-unpinned-tabs-toast = Tab Ditutup! Gunakan { $shortcut } untuk membatalkan. zen-workspaces-close-all-unpinned-tabs-title = - .label = Clear - .tooltiptext = Close all unpinned tabs + .label = Bersihkan + .tooltiptext = Tutup semua tab yang tidak disematkan diff --git a/prefs/zen/view.yaml b/prefs/zen/view.yaml index 8235e67fe..334de94da 100644 --- a/prefs/zen/view.yaml +++ b/prefs/zen/view.yaml @@ -43,11 +43,8 @@ - name: zen.view.drag-and-drop.move-over-threshold value: 70 -- name: zen.view.drag-and-drop.drop-inside-upper-threshold - value: 80 - -- name: zen.view.drag-and-drop.drop-inside-lower-threshold - value: 30 +- name: zen.view.drag-and-drop.edge-zone-threshold + value: 25 - name: zen.view.context-menu.refresh value: false diff --git a/src/browser/components/tabbrowser/AsyncTabSwitcher-sys-mjs.patch b/src/browser/components/tabbrowser/AsyncTabSwitcher-sys-mjs.patch index eba2ec3d1..e8d761cb5 100644 --- a/src/browser/components/tabbrowser/AsyncTabSwitcher-sys-mjs.patch +++ b/src/browser/components/tabbrowser/AsyncTabSwitcher-sys-mjs.patch @@ -1,12 +1,12 @@ diff --git a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs -index bcd7689e9d68ef8b171c327188174334c4271e21..f69180acb87644f109aa91b871e347f1b1835f53 100644 +index bcd7689e9d68ef8b171c327188174334c4271e21..0a95e1137fdf4b63e0d841776ad934da1a513c6f 100644 --- a/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs +++ b/browser/components/tabbrowser/AsyncTabSwitcher.sys.mjs @@ -938,6 +938,7 @@ export class AsyncTabSwitcher { this.tabbrowser._printPreviewBrowsers.has(browser) || this.tabbrowser.splitViewBrowsers.includes(browser) || lazy.PictureInPicture.isOriginatingBrowser(browser) -+ || browser?.parentNode?.parentNode?.parentNode?.classList?.contains("zen-glance-background") ++ || browser?.zenModeActive ); } diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 740b71372..1bb770059 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,8 +1,16 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326cbd973686 100644 +index c0eafd4faf8d57b8486c5bf8917375850ec8147e..cead9e6e52f7354e20b8b64ad06a075e6923fe5f 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js -@@ -450,15 +450,64 @@ +@@ -386,6 +386,7 @@ + * @type {MozBrowser[]} + */ + get splitViewBrowsers() { ++ return gZenViewSplitter.splitViewBrowsers; + const browsers = []; + if (this.#activeSplitView) { + for (const tab of this.#activeSplitView.tabs) { +@@ -450,15 +451,64 @@ return this.tabContainer.visibleTabs; } @@ -69,7 +77,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c set selectedTab(val) { if ( gSharedTabWarning.willShowSharedTabWarning(val) || -@@ -613,6 +662,7 @@ +@@ -613,6 +663,7 @@ this.tabpanels.appendChild(panel); let tab = this.tabs[0]; @@ -77,7 +85,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c tab.linkedPanel = uniqueId; this._selectedTab = tab; this._selectedBrowser = browser; -@@ -898,13 +948,17 @@ +@@ -898,13 +949,17 @@ } this.showTab(aTab); @@ -96,7 +104,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c aTab.setAttribute("pinned", "true"); this._updateTabBarForPinnedTabs(); -@@ -917,11 +971,15 @@ +@@ -917,11 +972,15 @@ } this.#handleTabMove(aTab, () => { @@ -113,7 +121,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c }); aTab.style.marginInlineStart = ""; -@@ -1098,6 +1156,8 @@ +@@ -1098,6 +1157,8 @@ let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"]; @@ -122,7 +130,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if ( aIconURL && !LOCAL_PROTOCOLS.some(protocol => aIconURL.startsWith(protocol)) -@@ -1107,6 +1167,9 @@ +@@ -1107,6 +1168,9 @@ ); return; } @@ -132,7 +140,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1379,7 +1442,6 @@ +@@ -1379,7 +1443,6 @@ // Preview mode should not reset the owner if (!this._previewMode && !oldTab.selected) { @@ -140,7 +148,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } let lastRelatedTab = this._lastRelatedTabMap.get(oldTab); -@@ -1470,6 +1532,7 @@ +@@ -1470,6 +1533,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); newTab.updateLastAccessed(); @@ -148,7 +156,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c oldTab.updateLastAccessed(); // if this is the foreground window, update the last-seen timestamps. if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) { -@@ -1622,6 +1685,9 @@ +@@ -1622,6 +1686,9 @@ } let activeEl = document.activeElement; @@ -158,7 +166,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // If focus is on the old tab, move it to the new tab. if (activeEl == oldTab) { newTab.focus(); -@@ -1945,7 +2011,8 @@ +@@ -1945,7 +2012,8 @@ } _setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) { @@ -168,7 +176,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c return false; } -@@ -2053,7 +2120,7 @@ +@@ -2053,7 +2121,7 @@ newIndex = this.selectedTab._tPos + 1; } @@ -177,7 +185,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (this.isTabGroupLabel(targetTab)) { throw new Error( "Replacing a tab group label with a tab is not supported" -@@ -2328,6 +2395,7 @@ +@@ -2328,6 +2396,7 @@ uriIsAboutBlank, userContextId, skipLoad, @@ -185,7 +193,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } = {}) { let b = document.createXULElement("browser"); // Use the JSM global to create the permanentKey, so that if the -@@ -2401,8 +2469,7 @@ +@@ -2401,8 +2470,7 @@ // we use a different attribute name for this? b.setAttribute("name", name); } @@ -195,7 +203,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c b.setAttribute("transparent", "true"); } -@@ -2567,7 +2634,7 @@ +@@ -2567,7 +2635,7 @@ let panel = this.getPanel(browser); let uniqueId = this._generateUniquePanelID(); @@ -204,7 +212,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c aTab.linkedPanel = uniqueId; // Inject the into the DOM if necessary. -@@ -2626,8 +2693,8 @@ +@@ -2626,8 +2694,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) { @@ -215,7 +223,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } else { aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1; } -@@ -2814,7 +2881,6 @@ +@@ -2814,7 +2882,6 @@ this.selectedTab = this.addTrustedTab(BROWSER_NEW_TAB_URL, { tabIndex: tab._tPos + 1, userContextId: tab.userContextId, @@ -223,7 +231,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c focusUrlBar: true, }); resolve(this.selectedBrowser); -@@ -2923,6 +2989,8 @@ +@@ -2923,6 +2990,8 @@ schemelessInput, hasValidUserGestureActivation = false, textDirectiveUserActivation = false, @@ -232,7 +240,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } = {} ) { // all callers of addTab that pass a params object need to pass -@@ -2933,10 +3001,17 @@ +@@ -2933,10 +3002,17 @@ ); } @@ -250,7 +258,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // If we're opening a foreground tab, set the owner by default. ownerTab ??= inBackground ? null : this.selectedTab; -@@ -2944,6 +3019,7 @@ +@@ -2944,6 +3020,7 @@ if (this.selectedTab.owner) { this.selectedTab.owner = null; } @@ -258,7 +266,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // Find the tab that opened this one, if any. This is used for // determining positioning, and inherited attributes such as the -@@ -2996,6 +3072,19 @@ +@@ -2996,6 +3073,19 @@ noInitialLabel, skipBackgroundNotify, }); @@ -278,7 +286,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (insertTab) { // Insert the tab into the tab container in the correct position. this.#insertTabAtIndex(t, { -@@ -3004,6 +3093,7 @@ +@@ -3004,6 +3094,7 @@ ownerTab, openerTab, pinned, @@ -286,7 +294,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c bulkOrderedOpen, tabGroup: tabGroup ?? openerTab?.group, }); -@@ -3022,6 +3112,7 @@ +@@ -3022,6 +3113,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -294,7 +302,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c })); if (focusUrlBar) { -@@ -3146,6 +3237,12 @@ +@@ -3146,6 +3238,12 @@ } } @@ -307,7 +315,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // Additionally send pinned tab events if (pinned) { this.#notifyPinnedStatus(t); -@@ -3330,10 +3427,10 @@ +@@ -3330,10 +3428,10 @@ isAdoptingGroup = false, isUserTriggered = false, telemetryUserCreateSource = "unknown", @@ -319,7 +327,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } if (!color) { -@@ -3354,9 +3451,14 @@ +@@ -3354,9 +3452,14 @@ label, isAdoptingGroup ); @@ -336,7 +344,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c ); group.addTabs(tabs); -@@ -3477,7 +3579,7 @@ +@@ -3477,7 +3580,7 @@ } this.#handleTabMove(tab, () => @@ -345,7 +353,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c ); } -@@ -3679,6 +3781,7 @@ +@@ -3679,6 +3782,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -353,7 +361,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } ) { // If we don't have a preferred remote type (or it is `NOT_REMOTE`), and -@@ -3748,6 +3851,7 @@ +@@ -3748,6 +3852,7 @@ openWindowInfo, name, skipLoad, @@ -361,7 +369,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c }); } -@@ -3935,7 +4039,7 @@ +@@ -3935,7 +4040,7 @@ // Add a new tab if needed. if (!tab) { let createLazyBrowser = @@ -370,7 +378,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c let url = "about:blank"; if (tabData.entries?.length) { -@@ -3972,8 +4076,10 @@ +@@ -3972,8 +4077,10 @@ insertTab: false, skipLoad: true, preferredRemoteType, @@ -382,7 +390,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (select) { tabToSelect = tab; } -@@ -3985,7 +4091,8 @@ +@@ -3985,7 +4092,8 @@ this.pinTab(tab); // Then ensure all the tab open/pinning information is sent. this._fireTabOpen(tab, {}); @@ -392,7 +400,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c let { groupId } = tabData; const tabGroup = tabGroupWorkingData.get(groupId); // if a tab refers to a tab group we don't know, skip any group -@@ -3999,7 +4106,10 @@ +@@ -3999,7 +4107,10 @@ tabGroup.stateData.id, tabGroup.stateData.color, tabGroup.stateData.collapsed, @@ -404,7 +412,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c ); tabsFragment.appendChild(tabGroup.node); } -@@ -4044,9 +4154,23 @@ +@@ -4044,9 +4155,23 @@ // to remove the old selected tab. if (tabToSelect) { let leftoverTab = this.selectedTab; @@ -428,7 +436,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (tabs.length > 1 || !tabs[0].selected) { this._updateTabsAfterInsert(); -@@ -4237,11 +4361,14 @@ +@@ -4237,11 +4362,14 @@ if (ownerTab) { tab.owner = ownerTab; } @@ -444,7 +452,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if ( !bulkOrderedOpen && ((openerTab && -@@ -4253,7 +4380,7 @@ +@@ -4253,7 +4381,7 @@ let lastRelatedTab = openerTab && this._lastRelatedTabMap.get(openerTab); let previousTab = lastRelatedTab || openerTab || this.selectedTab; @@ -453,7 +461,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c tabGroup = previousTab.group; } if ( -@@ -4264,7 +4391,7 @@ +@@ -4264,7 +4392,7 @@ ) { elementIndex = Infinity; } else if (previousTab.visible) { @@ -462,7 +470,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } else if (previousTab == FirefoxViewHandler.tab) { elementIndex = 0; } -@@ -4292,14 +4419,14 @@ +@@ -4292,14 +4420,14 @@ } // Ensure index is within bounds. if (tab.pinned) { @@ -481,7 +489,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (pinned && !itemAfter?.pinned) { itemAfter = null; -@@ -4310,7 +4437,7 @@ +@@ -4310,7 +4438,7 @@ this.tabContainer._invalidateCachedTabs(); @@ -490,7 +498,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c 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); -@@ -4338,7 +4465,11 @@ +@@ -4338,7 +4466,11 @@ const tabContainer = pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; @@ -502,7 +510,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } this._updateTabsAfterInsert(); -@@ -4346,6 +4477,7 @@ +@@ -4346,6 +4478,7 @@ if (pinned) { this._updateTabBarForPinnedTabs(); } @@ -510,7 +518,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c TabBarVisibility.update(); } -@@ -4635,6 +4767,9 @@ +@@ -4635,6 +4768,9 @@ return; } @@ -520,7 +528,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource }); } -@@ -4896,6 +5031,7 @@ +@@ -4896,6 +5032,7 @@ telemetrySource, } = {} ) { @@ -528,7 +536,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // When 'closeWindowWithLastTab' pref is enabled, closing all tabs // can be considered equivalent to closing the window. if ( -@@ -4985,6 +5121,7 @@ +@@ -4985,6 +5122,7 @@ if (lastToClose) { this.removeTab(lastToClose, aParams); } @@ -536,7 +544,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } catch (e) { console.error(e); } -@@ -5023,6 +5160,12 @@ +@@ -5023,6 +5161,12 @@ aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); } @@ -549,7 +557,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -5037,6 +5180,9 @@ +@@ -5037,6 +5181,9 @@ // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; let isLastTab = this.#isLastTabInWindow(aTab); @@ -559,7 +567,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -5085,7 +5231,13 @@ +@@ -5085,7 +5232,13 @@ // We're not animating, so we can cancel the animation stopwatch. Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId); aTab._closeTimeAnimTimerId = null; @@ -574,7 +582,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c return; } -@@ -5219,7 +5371,7 @@ +@@ -5219,7 +5372,7 @@ closeWindowWithLastTab != null ? closeWindowWithLastTab : !window.toolbar.visible || @@ -583,7 +591,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -5243,6 +5395,7 @@ +@@ -5243,6 +5396,7 @@ newTab = true; } @@ -591,7 +599,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -5283,13 +5436,7 @@ +@@ -5283,13 +5437,7 @@ aTab._mouseleave(); if (newTab) { @@ -606,7 +614,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } else { TabBarVisibility.update(); } -@@ -5422,6 +5569,7 @@ +@@ -5422,6 +5570,7 @@ this.tabs[i]._tPos = i; } @@ -614,7 +622,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (!this._windowIsClosing) { // update tab close buttons state this.tabContainer._updateCloseButtons(); -@@ -5643,6 +5791,7 @@ +@@ -5643,6 +5792,7 @@ } let excludeTabs = new Set(aExcludeTabs); @@ -622,7 +630,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // If this tab has a successor, it should be selectable, since // hiding or closing a tab removes that tab as a successor. -@@ -5655,13 +5804,13 @@ +@@ -5655,13 +5805,13 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -638,7 +646,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c ); let tab = this.tabContainer.findNextTab(aTab, { -@@ -5677,7 +5826,7 @@ +@@ -5677,7 +5827,7 @@ } if (tab) { @@ -647,7 +655,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } // If no qualifying visible tab was found, see if there is a tab in -@@ -5698,7 +5847,7 @@ +@@ -5698,7 +5848,7 @@ }); } @@ -656,7 +664,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } _blurTab(aTab) { -@@ -6104,10 +6253,10 @@ +@@ -6104,10 +6254,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -669,7 +677,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -6166,6 +6315,7 @@ +@@ -6166,6 +6316,7 @@ * @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab */ replaceTabWithWindow(aTab, aOptions) { @@ -677,7 +685,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (this.tabs.length == 1) { return null; } -@@ -6299,7 +6449,7 @@ +@@ -6299,7 +6450,7 @@ * `true` if element is a `` */ isTabGroup(element) { @@ -686,7 +694,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } /** -@@ -6375,8 +6525,8 @@ +@@ -6375,8 +6526,8 @@ } // Don't allow mixing pinned and unpinned tabs. @@ -697,7 +705,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } else { tabIndex = Math.max(tabIndex, this.pinnedTabCount); } -@@ -6402,10 +6552,16 @@ +@@ -6402,10 +6553,16 @@ this.#handleTabMove( element, () => { @@ -716,7 +724,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c if (neighbor && this.isTab(element) && tabIndex > element._tPos) { neighbor.after(element); } else { -@@ -6463,23 +6619,28 @@ +@@ -6463,23 +6620,28 @@ #moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) { if (this.isTabGroupLabel(targetElement)) { targetElement = targetElement.group; @@ -751,7 +759,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } 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 -@@ -6492,14 +6653,34 @@ +@@ -6492,14 +6654,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. @@ -787,7 +795,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c element.pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; -@@ -6508,7 +6689,7 @@ +@@ -6508,7 +6690,7 @@ element, () => { if (moveBefore) { @@ -796,7 +804,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c } else if (targetElement) { targetElement.after(element); } else { -@@ -6580,10 +6761,10 @@ +@@ -6580,10 +6762,10 @@ * @param {TabMetricsContext} [metricsContext] */ moveTabToGroup(aTab, aGroup, metricsContext) { @@ -809,7 +817,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -6613,6 +6794,7 @@ +@@ -6613,6 +6795,7 @@ let state = { tabIndex: tab._tPos, @@ -817,7 +825,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c }; if (tab.visible) { state.elementIndex = tab.elementIndex; -@@ -6639,7 +6821,7 @@ +@@ -6639,7 +6822,7 @@ let changedTabGroup = previousTabState.tabGroupId != currentTabState.tabGroupId; @@ -826,7 +834,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c tab.dispatchEvent( new CustomEvent("TabMove", { bubbles: true, -@@ -6676,6 +6858,10 @@ +@@ -6676,6 +6859,10 @@ moveActionCallback(); @@ -837,7 +845,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -7576,7 +7762,7 @@ +@@ -7576,7 +7763,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -846,7 +854,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c window.focus(); aEvent.preventDefault(); break; -@@ -7593,7 +7779,6 @@ +@@ -7593,7 +7780,6 @@ } case "TabGroupCollapse": aEvent.target.tabs.forEach(tab => { @@ -854,7 +862,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c }); break; case "TabGroupCreateByUser": -@@ -8542,6 +8727,7 @@ +@@ -8542,6 +8728,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -862,7 +870,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -9543,7 +9729,7 @@ var TabContextMenu = { +@@ -9543,7 +9730,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !this.multiselected; @@ -871,7 +879,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c // Build Ask Chat items TabContextMenu.GenAI.buildTabMenu( document.getElementById("context_askChat"), -@@ -9863,6 +10049,7 @@ var TabContextMenu = { +@@ -9863,6 +10050,7 @@ var TabContextMenu = { ) ); } else { diff --git a/src/firefox-patches/bug_1993474.patch b/src/firefox-patches/bug_1993474.patch new file mode 100644 index 000000000..11ebfc044 --- /dev/null +++ b/src/firefox-patches/bug_1993474.patch @@ -0,0 +1,107 @@ +diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp +index 2a17159215d107f6e4b09cf3a63ab0fff2c2ee70..15dffb83dbac8c6aa9b3dfa388b66874d5b05a7e 100644 +--- a/widget/windows/nsWindow.cpp ++++ b/widget/windows/nsWindow.cpp +@@ -2848,6 +2848,25 @@ void nsWindow::SetCustomTitlebar(bool aCustomTitlebar) { + + mCustomNonClient = aCustomTitlebar; + ++ // Because of bug 1993474, we want to properly set the WS_BORDER style ++ // when the titlebar is turned on or off. ++ // ++ // The documentation for window styles says that most styles can't be ++ // modified after the window is created. Testing shows that WS_BORDER ++ // seems to be OK, but make sure this is the only style we try to change ++ // here. ++ const LONG_PTR actualStyle = ::GetWindowLongPtrW(mWnd, GWL_STYLE); ++ LONG_PTR newStyle = actualStyle; ++ if (mCustomNonClient) { ++ newStyle &= ~WS_BORDER; ++ } else { ++ newStyle |= WS_BORDER; ++ } ++ if (newStyle != actualStyle) { ++ VERIFY_WINDOW_STYLE(newStyle); ++ ::SetWindowLongPtrW(mWnd, GWL_STYLE, newStyle); ++ } ++ + // Force a reflow of content based on the new client dimensions. + if (mCustomNonClient) { + UpdateNonClientMargins(); +@@ -8792,9 +8811,10 @@ void nsWindow::FrameState::CheckInvariant() const { + mPreFullscreenSizeMode < nsSizeMode_Invalid); + MOZ_ASSERT(mWindow); + +- // We should never observe fullscreen sizemode unless fullscreen is enabled +- MOZ_ASSERT_IF(mSizeMode == nsSizeMode_Fullscreen, mFullscreenMode); +- MOZ_ASSERT_IF(!mFullscreenMode, mSizeMode != nsSizeMode_Fullscreen); ++ // Unfortunately this can happen now with the hack fix in ++ // SetSizeModeInternal() ++ // MOZ_ASSERT_IF(mSizeMode == nsSizeMode_Fullscreen, mFullscreenMode); ++ // MOZ_ASSERT_IF(!mFullscreenMode, mSizeMode != nsSizeMode_Fullscreen); + + // Something went wrong if we somehow saved fullscreen mode when we are + // changing into fullscreen mode +@@ -8902,6 +8922,62 @@ void nsWindow::FrameState::SetSizeModeInternal(nsSizeMode aMode, + mSizeMode == nsSizeMode_Fullscreen || aMode == nsSizeMode_Fullscreen; + const bool maximized = aMode == nsSizeMode_Maximized; + const bool fullscreen = aMode == nsSizeMode_Fullscreen; ++ const bool wasMaximized = mSizeMode == nsSizeMode_Maximized; ++ const bool wasFullscreen = mSizeMode == nsSizeMode_Fullscreen; ++ ++ // Maximizing a window without the WS_BORDER style set will make Windows ++ // display it over the taskbar, even if we tell it not to. So if we're ++ // becoming maximized, make sure WS_BORDER is set, then clear it after a ++ // short time if necessary (to avoid issues like bug 1993474). Conversely, ++ // for becoming fullscreen make sure WS_BORDER is cleared. Yes, this is a ++ // hack. ++ if ((maximized && !wasMaximized) || (fullscreen && !wasFullscreen)) { ++ const LONG_PTR actualStyle = ::GetWindowLongPtrW(mWindow->mWnd, GWL_STYLE); ++ LONG_PTR newStyle = actualStyle; ++ if (maximized) { ++ newStyle |= WS_BORDER; ++ } else { ++ newStyle &= ~WS_BORDER; ++ } ++ if (newStyle != actualStyle) { ++ VERIFY_WINDOW_STYLE(newStyle); ++ MOZ_LOG( ++ gWindowsLog, LogLevel::Info, ++ ("window style is %d, temporarily fixing up WS_BORDER", mSizeMode)); ++ ::SetWindowLongPtrW(mWindow->mWnd, GWL_STYLE, newStyle); ++ ::SetWindowPos(mWindow->mWnd, nullptr, 0, 0, 0, 0, ++ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ++ SWP_NOACTIVATE | SWP_NOOWNERZORDER); ++ } ++ NS_DispatchToMainThread(NS_NewRunnableFunction( ++ "nsWindow::FrameState::SetSizeModeInternal", ++ [expectedMode = aMode, window = RefPtr(this->mWindow)]() { ++ // Make sure we're still in the same state (i.e. the user hasn't ++ // un-maximized or un-fullscreened the window in the meantime) ++ if (window->SizeMode() != expectedMode) { ++ return; ++ } ++ const LONG_PTR actualStyle = ++ ::GetWindowLongPtrW(window->mWnd, GWL_STYLE); ++ LONG_PTR newStyle = actualStyle; ++ if (expectedMode == nsSizeMode_Maximized && ++ window->mCustomNonClient) { ++ newStyle &= ~WS_BORDER; ++ } else { ++ newStyle |= WS_BORDER; ++ } ++ if (newStyle != actualStyle) { ++ VERIFY_WINDOW_STYLE(newStyle); ++ MOZ_LOG(gWindowsLog, LogLevel::Info, ++ ("window style is %d, after delay restoring WS_BORDER", ++ expectedMode)); ++ ::SetWindowLongPtrW(window->mWnd, GWL_STYLE, newStyle); ++ ::SetWindowPos(window->mWnd, nullptr, 0, 0, 0, 0, ++ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ++ SWP_NOACTIVATE | SWP_NOOWNERZORDER); ++ } ++ })); ++ } + + mSizeMode = aMode; + diff --git a/src/zen/common/ZenUIManager.mjs b/src/zen/common/ZenUIManager.mjs index 645739228..115a75c97 100644 --- a/src/zen/common/ZenUIManager.mjs +++ b/src/zen/common/ZenUIManager.mjs @@ -493,20 +493,26 @@ var gZenUIManager = { if (gURLBar.focused) { setTimeout(() => { - window.dispatchEvent( - new CustomEvent('ZenURLBarClosed', { detail: { onSwitch, onElementPicked } }) - ); - gURLBar.view.close({ elementPicked: onElementPicked }); - gURLBar.updateTextOverflow(); + setTimeout(() => { + window.dispatchEvent( + new CustomEvent('ZenURLBarClosed', { detail: { onSwitch, onElementPicked } }) + ); + gURLBar.view.close({ elementPicked: onElementPicked }); + gURLBar.updateTextOverflow(); - // Ensure tab and browser are valid before updating state - const selectedTab = gBrowser.selectedTab; - if (selectedTab && selectedTab.linkedBrowser && !selectedTab.closing && onSwitch) { - const browserState = gURLBar.getBrowserState(selectedTab.linkedBrowser); - if (browserState) { - browserState.urlbarFocused = false; + if (onElementPicked && onSwitch) { + gURLBar.setURI(null, onSwitch); } - } + + // Ensure tab and browser are valid before updating state + const selectedTab = gBrowser.selectedTab; + if (selectedTab && selectedTab.linkedBrowser && !selectedTab.closing && onSwitch) { + const browserState = gURLBar.getBrowserState(selectedTab.linkedBrowser); + if (browserState) { + browserState.urlbarFocused = false; + } + } + }, 0); }, 0); } }, @@ -663,7 +669,10 @@ var gZenUIManager = { if (anchor?.closest('#zen-sidebar-top-buttons')) { block = 'topleft'; } - if (gZenVerticalTabsManager._hasSetSingleToolbar && gZenVerticalTabsManager._prefsRightSide) { + if ( + (gZenVerticalTabsManager._hasSetSingleToolbar && gZenVerticalTabsManager._prefsRightSide) || + (panel?.id === 'zen-unified-site-data-panel' && !gZenVerticalTabsManager._hasSetSingleToolbar) + ) { block = 'bottomright'; inline = 'topright'; } diff --git a/src/zen/common/styles/zen-omnibox.css b/src/zen/common/styles/zen-omnibox.css index 94838947e..4a916ef08 100644 --- a/src/zen/common/styles/zen-omnibox.css +++ b/src/zen/common/styles/zen-omnibox.css @@ -355,6 +355,8 @@ } :root:not([zen-single-toolbar='true']) { + --urlbar-icon-border-radius: 6px !important; + #notification-popup-box { margin: 0 4px 0 0 !important; justify-content: center; diff --git a/src/zen/folders/ZenFolders.mjs b/src/zen/folders/ZenFolders.mjs index 4245f4cd6..010a196a7 100644 --- a/src/zen/folders/ZenFolders.mjs +++ b/src/zen/folders/ZenFolders.mjs @@ -29,9 +29,11 @@ return `${month} month${month === 1 ? '' : 's'} ago`; } - const ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref('zen.folders.max-subfolders'); - class nsZenFolders extends nsZenDOMOperatedFeature { + #ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref('zen.folders.max-subfolders', 5); + #ZEN_EDGE_ZONE_THRESHOLD = + Services.prefs.getIntPref('zen.view.drag-and-drop.edge-zone-threshold', 25) / 100; + #popup = null; #popupTimer = null; #mouseTimer = null; @@ -89,7 +91,7 @@ const newSubfolderItem = document.getElementById('context_zenFolderNewSubfolder'); newSubfolderItem.setAttribute( 'disabled', - folder.level >= ZEN_MAX_SUBFOLDERS - 1 ? 'true' : 'false' + folder.level >= this.#ZEN_MAX_SUBFOLDERS - 1 ? 'true' : 'false' ); const changeFolderSpace = document @@ -470,7 +472,7 @@ canDropElement(element, targetElement) { const isZenFolder = element?.isZenFolder; const level = targetElement?.group?.level + 1; - if (isZenFolder && level >= ZEN_MAX_SUBFOLDERS) { + if (isZenFolder && level >= this.#ZEN_MAX_SUBFOLDERS) { return false; } return true; @@ -899,7 +901,11 @@ const labelContainer = group.querySelector('.tab-group-label-container'); // Setup mouseenter/mouseleave events for the folder labelContainer.addEventListener('mouseenter', (event) => { - if (!group.collapsed || !Services.prefs.getBoolPref('zen.folders.search.enabled')) { + if ( + !group.collapsed || + !Services.prefs.getBoolPref('zen.folders.search.enabled') || + gBrowser.tabContainer.hasAttribute('movingtab') + ) { return; } this.#mouseTimer = setTimeout(() => { @@ -1104,7 +1110,8 @@ (!folder.hasAttribute('split-view-group') || !folder.hasAttribute('selected')) && folder !== tab?.group && !( - folder.level >= ZEN_MAX_SUBFOLDERS && movingTabs?.some((t) => gBrowser.isTabGroupLabel(t)) + folder.level >= this.#ZEN_MAX_SUBFOLDERS && + movingTabs?.some((t) => gBrowser.isTabGroupLabel(t)) ) ) { folder.setAttribute('selected', 'true'); @@ -1151,10 +1158,6 @@ let dropElement = currentDropElement; let dropBefore = currentDropBefore; let colorCode = currentColorCode; - let dragUpThreshold = - Services.prefs.getIntPref('zen.view.drag-and-drop.drop-inside-upper-threshold') / 100; - let dragDownThreshold = - Services.prefs.getIntPref('zen.view.drag-and-drop.drop-inside-lower-threshold') / 100; const dropElementGroup = dropElement?.isZenFolder ? dropElement : dropElement?.group; const isSplitGroup = dropElement?.group?.hasAttribute('split-view-group'); @@ -1162,26 +1165,17 @@ dropElementGroup.querySelector('.zen-tab-group-start').nextElementSibling; if (gBrowser.isTabGroup(firstGroupElem)) firstGroupElem = firstGroupElem.labelElement; - const isRestrictedGroup = isSplitGroup || dropElementGroup.collapsed; - - const shouldDropInside = - !dropBefore && - overlapPercent >= dragDownThreshold && - overlapPercent <= dragUpThreshold && - !isSplitGroup; - const shouldDropNear = overlapPercent < dragUpThreshold || overlapPercent > dragDownThreshold; + const isInMiddleZone = + overlapPercent >= this.#ZEN_EDGE_ZONE_THRESHOLD && + overlapPercent <= 1 - this.#ZEN_EDGE_ZONE_THRESHOLD; + const shouldDropInside = isInMiddleZone && !isSplitGroup; if (shouldDropInside) { dropElement = firstGroupElem; dropBefore = true; this.highlightGroupOnDragOver(dropElementGroup, movingTabs); - } else if (shouldDropNear) { - if (dropBefore) { - colorCode = undefined; - } else if (!isRestrictedGroup) { - dropElement = firstGroupElem; - dropBefore = true; - } + } else { + colorCode = undefined; this.highlightGroupOnDragOver(null); } diff --git a/src/zen/glance/ZenGlanceManager.mjs b/src/zen/glance/ZenGlanceManager.mjs index 27d82b591..3302a3f4f 100644 --- a/src/zen/glance/ZenGlanceManager.mjs +++ b/src/zen/glance/ZenGlanceManager.mjs @@ -1415,8 +1415,9 @@ this.overlay.classList.remove('zen-glance-overlay'); this.#clearContainerStyles(this.browserWrapper); this.animatingFullOpen = false; + const glanceID = this.#currentGlanceID; this.closeGlance({ noAnimation: true, skipPermitUnload: true }); - this.#glances.delete(this.#currentGlanceID); + this.#glances.delete(glanceID); } /** diff --git a/src/zen/split-view/ZenViewSplitter.mjs b/src/zen/split-view/ZenViewSplitter.mjs index 5aeeaa67c..ab3912b3a 100644 --- a/src/zen/split-view/ZenViewSplitter.mjs +++ b/src/zen/split-view/ZenViewSplitter.mjs @@ -1067,86 +1067,88 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature { * @param {string|undefined} gridType - The type of grid layout. */ splitTabs(tabs, gridType, initialIndex = 0) { - // TODO: Add support for splitting essential tabs - tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab')); - if (tabs.length < 2 || tabs.length > this.MAX_TABS) { - return; - } + this.#withoutSplitViewTransition(() => { + // TODO: Add support for splitting essential tabs + tabs = tabs.filter((t) => !t.hidden && !t.hasAttribute('zen-empty-tab')); + if (tabs.length < 2 || tabs.length > this.MAX_TABS) { + return; + } - const existingSplitTab = tabs.find((tab) => tab.splitView); - if (existingSplitTab) { - this._moveTabsToContainer(tabs, tabs[initialIndex]); - const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab)); - const group = this._data[groupIndex]; - const gridTypeChange = gridType && group.gridType !== gridType; - const newTabsAdded = tabs.find((t) => !group.tabs.includes(t)); - if (gridTypeChange || !newTabsAdded) { - // reset layout - group.gridType = gridType; - group.layoutTree = this.calculateLayoutTree( - [...new Set(group.tabs.concat(tabs))], - gridType - ); - } else { - // Add any tabs that are not already in the group + const existingSplitTab = tabs.find((tab) => tab.splitView); + if (existingSplitTab) { + this._moveTabsToContainer(tabs, tabs[initialIndex]); + const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab)); + const group = this._data[groupIndex]; + const gridTypeChange = gridType && group.gridType !== gridType; + const newTabsAdded = tabs.find((t) => !group.tabs.includes(t)); + if (gridTypeChange || !newTabsAdded) { + // reset layout + group.gridType = gridType; + group.layoutTree = this.calculateLayoutTree( + [...new Set(group.tabs.concat(tabs))], + gridType + ); + } else { + // Add any tabs that are not already in the group + for (let i = 0; i < tabs.length; i++) { + const tab = tabs[i]; + if (!group.tabs.includes(tab)) { + gBrowser.moveTabToGroup(tab, this._getSplitViewGroup(tabs)); + group.tabs.push(tab); + this.addTabToSplit(tab, group.layoutTree); + } + } + } + if (this._sessionRestoring) { + return; + } + this.activateSplitView(group, true); + return; + } + + // We are here if none of the tabs have been previously split + // If there's ANY pinned tab on the list, we clone the pinned tab + // state to all the tabs + const allArePinned = tabs.every((tab) => tab.pinned); + const thereIsOnePinned = tabs.some((tab) => tab.pinned); + const thereIsOneEssential = tabs.some((tab) => tab.hasAttribute('zen-essential')); + + if (thereIsOneEssential || (thereIsOnePinned && !allArePinned)) { for (let i = 0; i < tabs.length; i++) { const tab = tabs[i]; - if (!group.tabs.includes(tab)) { - gBrowser.moveTabToGroup(tab, this._getSplitViewGroup(tabs)); - group.tabs.push(tab); - this.addTabToSplit(tab, group.layoutTree); + if (tab.pinned) { + tabs[i] = gBrowser.duplicateTab(tab, true); } } } + + gridType ??= 'grid'; + + const splitData = { + tabs, + gridType, + layoutTree: this.calculateLayoutTree(tabs, gridType), + }; + this._data.push(splitData); + if (!this._sessionRestoring) { + window.gBrowser.selectedTab = tabs[initialIndex] ?? tabs[0]; + } + + // Add tabs to the split view group + let splitGroup = this._getSplitViewGroup(tabs); + if (splitGroup) { + for (const tab of tabs) { + if (!tab.group || tab.group !== splitGroup) { + gBrowser.moveTabToGroup(tab, splitGroup); + } + } + } + if (this._sessionRestoring) { return; } - this.activateSplitView(group, true); - return; - } - - // We are here if none of the tabs have been previously split - // If there's ANY pinned tab on the list, we clone the pinned tab - // state to all the tabs - const allArePinned = tabs.every((tab) => tab.pinned); - const thereIsOnePinned = tabs.some((tab) => tab.pinned); - const thereIsOneEssential = tabs.some((tab) => tab.hasAttribute('zen-essential')); - - if (thereIsOneEssential || (thereIsOnePinned && !allArePinned)) { - for (let i = 0; i < tabs.length; i++) { - const tab = tabs[i]; - if (tab.pinned) { - tabs[i] = gBrowser.duplicateTab(tab, true); - } - } - } - - gridType ??= 'grid'; - - const splitData = { - tabs, - gridType, - layoutTree: this.calculateLayoutTree(tabs, gridType), - }; - this._data.push(splitData); - if (!this._sessionRestoring) { - window.gBrowser.selectedTab = tabs[initialIndex] ?? tabs[0]; - } - - // Add tabs to the split view group - let splitGroup = this._getSplitViewGroup(tabs); - if (splitGroup) { - for (const tab of tabs) { - if (!tab.group || tab.group !== splitGroup) { - gBrowser.moveTabToGroup(tab, splitGroup); - } - } - } - - if (this._sessionRestoring) { - return; - } - this.activateSplitView(splitData); + this.activateSplitView(splitData); + }); } addTabToSplit(tab, splitNode, prepend = true) { @@ -1929,6 +1931,17 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature { return true; } + #withoutSplitViewTransition(callback) { + this.tabBrowserPanel.classList.add('zen-split-view-no-transition'); + try { + callback(); + } finally { + requestAnimationFrame(() => { + this.tabBrowserPanel.classList.remove('zen-split-view-no-transition'); + }, 0); + } + } + createEmptySplit() { const selectedTab = gBrowser.selectedTab; const emptyTab = gZenWorkspaces._emptyTab; @@ -1975,6 +1988,13 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature { gZenUIManager.handleNewTab(false, false, 'tab', true); }, 0); } + + get splitViewBrowsers() { + if (this.currentView < 0) { + return []; + } + return this._data[this.currentView].tabs.map((tab) => tab.linkedBrowser); + } } window.gZenViewSplitter = new nsZenViewSplitter(); diff --git a/src/zen/split-view/zen-decks.css b/src/zen/split-view/zen-decks.css index bc88c016f..9c4ff3f3a 100644 --- a/src/zen/split-view/zen-decks.css +++ b/src/zen/split-view/zen-decks.css @@ -58,7 +58,7 @@ margin-top: 0 !important; } -#tabbrowser-tabpanels[zen-split-view='true']:not([zen-split-resizing]) > [zen-split='true'] { +#tabbrowser-tabpanels[zen-split-view='true']:not(.zen-split-view-no-transition):not([zen-split-resizing]) > [zen-split='true'] { transition: inset 0.09s ease-out !important; & browser { transition: opacity 0.2s ease-out !important; diff --git a/surfer.json b/surfer.json index e4e79e6e3..e8f0205d8 100644 --- a/surfer.json +++ b/surfer.json @@ -5,8 +5,8 @@ "binaryName": "zen", "version": { "product": "firefox", - "version": "145.0", - "candidate": "145.0" + "version": "145.0.1", + "candidate": "145.0.1" }, "buildOptions": { "generateBranding": true