diff --git a/.github/workflows/update-submodules.yml b/.github/workflows/update-submodules.yml deleted file mode 100644 index 18fa6cc26..000000000 --- a/.github/workflows/update-submodules.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Update Components Submodules - -on: - push: - branches: - - dev - workflow_dispatch: - workflow_call: - -jobs: - update-submodules: - runs-on: ubuntu-latest - if: "!contains(github.event.head_commit.message, '[skip ci]')" - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - token: ${{ secrets.DEPLOY_KEY }} - - - name: Update submodules - run: | - git submodule update --remote --merge - - - name: Commit - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: '[skip ci] 📦 Update submodules' - commit_user_name: Zen Browser Robot - commit_user_email: zen-browser-auto@users.noreply.github.com diff --git a/configs/common/mozconfig b/configs/common/mozconfig index f840e768c..fce7a4692 100644 --- a/configs/common/mozconfig +++ b/configs/common/mozconfig @@ -9,7 +9,7 @@ ac_add_options --with-l10n-base="${topsrcdir}/browser/locales" export MOZ_USER_DIR="${name}" export MOZ_APP_BASENAME=Zen export MOZ_APP_PROFILE=${binName} -export MOZ_APP_DISPLAYNAME="${name}" +export MOZ_APP_DISPLAYNAME="Zen" export MOZ_BRANDING_DIRECTORY=${brandingDir} export MOZ_OFFICIAL_BRANDING_DIRECTORY=${brandingDir} diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index cdb976ff1..e0d21b352 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -80,6 +80,7 @@ pref('zen.welcome-screen.seen', false); pref('zen.tabs.vertical', true); pref('zen.tabs.vertical.right-side', false); +pref('zen.tabs.rename-tabs', true); pref('zen.theme.accent-color', "#ffb787"); pref('zen.theme.content-element-separation', 6); // In pixels pref('zen.theme.pill-button', false); diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 3613dca34..8180d1772 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -14,6 +14,10 @@ var gZenUIManager = { return ChromeUtils.importESModule('chrome://browser/content/zen-vendor/motion.min.mjs', { global: 'current' }); }); + ChromeUtils.defineLazyGetter(this, '_toastContainer', () => { + return document.getElementById('zen-toast-container'); + }); + new ResizeObserver(this.updateTabsToolbar.bind(this)).observe(document.getElementById('TabsToolbar')); new ResizeObserver( @@ -209,6 +213,38 @@ var gZenUIManager = { } } }, + + // Section: Notification messages + _createToastElement(messageId, options) { + const element = document.createXULElement('vbox'); + const label = document.createXULElement('label'); + document.l10n.setAttributes(label, messageId, options); + element.appendChild(label); + if (options.descriptionId) { + const description = document.createXULElement('label'); + description.classList.add('description'); + document.l10n.setAttributes(description, options.descriptionId, options); + element.appendChild(description); + } + element.classList.add('zen-toast'); + return element; + }, + + async showToast(messageId, options = {}) { + const toast = this._createToastElement(messageId, options); + this._toastContainer.removeAttribute('hidden'); + this._toastContainer.appendChild(toast); + await this.motion.animate(toast, { opacity: [0, 1], scale: [0.8, 1] }, { type: 'spring', duration: 0.3 }); + await new Promise((resolve) => setTimeout(resolve, 3000)); + await this.motion.animate(toast, { opacity: [1, 0], scale: [1, 0.9] }, { duration: 0.2, bounce: 0 }); + const toastHeight = toast.getBoundingClientRect().height; + // 5 for the separation between toasts + await this.motion.animate(toast, { marginBottom: [0, `-${toastHeight + 5}px`] }, { duration: 0.2 }); + toast.remove(); + if (!this._toastContainer.hasChildNodes()) { + this._toastContainer.setAttribute('hidden', 'true'); + } + }, }; var gZenVerticalTabsManager = { @@ -248,6 +284,9 @@ var gZenVerticalTabsManager = { if (!this.isWindowsStyledButtons) { document.documentElement.setAttribute('zen-window-buttons-reversed', true); } + + this._renameTabHalt = this.renameTabHalt.bind(this); + gBrowser.tabContainer.addEventListener('dblclick', this.renameTabStart.bind(this)); }, toggleExpand() { @@ -613,4 +652,85 @@ var gZenVerticalTabsManager = { } target.appendChild(child); }, + + renameTabKeydown(event) { + if (event.key === 'Enter') { + let label = this._tabEdited.querySelector('.tab-label-container-editing'); + let input = this._tabEdited.querySelector('#tab-label-input'); + let newName = input.value.trim(); + + // Check if name is blank, reset if so + // Always remove, so we can always rename and if it's empty, + // it will reset to the original name anyway + this._tabEdited.removeAttribute('zen-has-static-label'); + if (newName) { + gBrowser._setTabLabel(this._tabEdited, newName); + this._tabEdited.setAttribute('zen-has-static-label', 'true'); + } else { + gBrowser.setTabTitle(this._tabEdited); + } + + // Maybe add some confetti here?!? + gZenUIManager.motion.animate( + this._tabEdited, + { + scale: [1, 0.98, 1], + }, + { + duration: 0.25, + } + ); + + this._tabEdited.querySelector('.tab-editor-container').remove(); + label.classList.remove('tab-label-container-editing'); + + this._tabEdited = null; + } else if (event.key === 'Escape') { + event.target.blur(); + } + }, + + renameTabStart(event) { + if ( + this._tabEdited || + !Services.prefs.getBoolPref('zen.tabs.rename-tabs') || + Services.prefs.getBoolPref('browser.tabs.closeTabByDblclick') || + !gZenVerticalTabsManager._prefsSidebarExpanded + ) + return; + this._tabEdited = event.target.closest('.tabbrowser-tab'); + if (!this._tabEdited || !this._tabEdited.pinned || this._tabEdited.hasAttribute('zen-essential')) { + this._tabEdited = null; + return; + } + const label = this._tabEdited.querySelector('.tab-label-container'); + label.classList.add('tab-label-container-editing'); + + const container = window.MozXULElement.parseXULToFragment(` + + `); + label.after(container); + const containerHtml = this._tabEdited.querySelector('.tab-editor-container'); + const input = document.createElement('input'); + input.id = 'tab-label-input'; + input.value = this._tabEdited.label; + input.addEventListener('keydown', this.renameTabKeydown.bind(this)); + + containerHtml.appendChild(input); + input.focus(); + input.select(); + + input.addEventListener('blur', this._renameTabHalt); + }, + + renameTabHalt(event) { + if (document.activeElement === event.target || !this._tabEdited) { + return; + } + this._tabEdited.querySelector('.tab-editor-container').remove(); + const label = this._tabEdited.querySelector('.tab-label-container-editing'); + label.classList.remove('tab-label-container-editing'); + + this._tabEdited = null; + }, }; diff --git a/src/browser/base/content/browser-xhtml.patch b/src/browser/base/content/browser-xhtml.patch index f55a99295..248781b38 100644 --- a/src/browser/base/content/browser-xhtml.patch +++ b/src/browser/base/content/browser-xhtml.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml -index 891c067d6ad718061c410c04743bed25744504b5..560abfe817b94f535919ed29c21a912b09d63ac5 100644 +index 891c067d6ad718061c410c04743bed25744504b5..b7ded9691225068b23e4d6a5113242d0c0f5f842 100644 --- a/browser/base/content/browser.xhtml +++ b/browser/base/content/browser.xhtml @@ -99,6 +99,8 @@ @@ -19,7 +19,7 @@ index 891c067d6ad718061c410c04743bed25744504b5..560abfe817b94f535919ed29c21a912b # All sets except for popupsets (commands, keys, and stringbundles) -@@ -164,9 +167,12 @@ +@@ -164,9 +167,13 @@ @@ -27,6 +27,7 @@ index 891c067d6ad718061c410c04743bed25744504b5..560abfe817b94f535919ed29c21a912b - -#include browser-box.inc.xhtml + ++ + #include navigator-toolbox.inc.xhtml + + diff --git a/src/browser/base/content/zen-styles/zen-popup.css b/src/browser/base/content/zen-styles/zen-popup.css index 0fe1dc861..561df13f8 100644 --- a/src/browser/base/content/zen-styles/zen-popup.css +++ b/src/browser/base/content/zen-styles/zen-popup.css @@ -349,3 +349,30 @@ menuitem { #editBMPanel_workspaceList input[type='checkbox'] { margin-right: 8px; } + +/* Section: Toast notifications */ + +#zen-toast-container { + position: fixed; + top: calc(var(--zen-element-separation) * 2); + right: calc(var(--zen-element-separation) * 2); + z-index: 1000; + gap: 1rem; + + & .zen-toast { + padding: 0.9rem 0.8rem; + border-radius: 12px; + background-color: var(--button-primary-bgcolor); + color: var(--button-primary-color); + box-shadow: var(--zen-big-shadow); + display: flex; + gap: 5px; + flex-direction: column; + gap: 2px; + width: fit-content; + + & .description { + opacity: 0.6; + } + } +} diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 286493476..eeab85cdb 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -280,10 +280,6 @@ } } - &[selected] .tab-background { - backdrop-filter: blur(10px); - } - @media (-moz-bool-pref: 'zen.tabs.dim-pending') { &[pending='true'] .tab-icon-image { opacity: 0.5; @@ -326,13 +322,18 @@ /* On essentials, glance tabs are floating */ &[zen-essential='true'] .tabbrowser-tab { position: absolute; - top: 4px; - right: 4px; - --tab-collapsed-width: 35px; + top: 0px; + right: 0px; + --tab-collapsed-width: 34px; --tab-min-height: 16px; width: var(--tab-collapsed-width) !important; z-index: 1; pointer-events: none; + & .tab-background { + /* Solid colors because we don't want to show the background */ + background: light-dark(rgb(249, 249, 249), rgb(63, 63, 63)) !important; + border: 2px solid light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)); + } } } } @@ -954,7 +955,7 @@ padding: 0; } -#zen-essentials-container .tabbrowser-tab { +#zen-essentials-container > .tabbrowser-tab { --toolbarbutton-inner-padding: 0; max-width: unset; width: 100% !important; @@ -994,7 +995,7 @@ } @media (-moz-bool-pref: 'zen.theme.essentials-favicon-bg') { - &[visuallyselected] .tab-background { + &[visuallyselected] > .tab-stack > .tab-background { &::after { content: ""; inset: -50%; @@ -1138,6 +1139,20 @@ box-shadow: -3px 0 6px -2px var(--toolbarbutton-active-background, rgba(0, 255, 0, 0.2)); } +/* Renaming tabs */ +.tab-label-container-editing { + display: none !important; +} + +#tab-label-input { + white-space: nowrap; + overflow-x: scroll; + margin: 0; + background: transparent; + border: none; + padding: 0; +} + /* Section: tab workspaces stylings */ .zen-workspace-tabs-section { position: absolute; diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index 06ba77888..e325f12d5 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -161,15 +161,10 @@ @media (-moz-windows-mica) or (-moz-platform: macos) { background: transparent; - --zen-themed-toolbar-bg-transparency: 0; + --zen-themed-toolbar-bg-transparent: transparent; @media (-moz-bool-pref: 'zen.widget.windows.acrylic') { - --zen-themed-toolbar-bg-transparency: 15%; + --zen-themed-toolbar-bg-transparent: color-mix(in srgb, var(--zen-themed-toolbar-bg) 85%, transparent 15%); } - --zen-themed-toolbar-bg-transparent: color-mix( - in srgb, - var(--zen-themed-toolbar-bg) calc(100% - var(--zen-themed-toolbar-bg-transparency)), - transparent var(--zen-themed-toolbar-bg-transparency) - ); } --toolbar-field-background-color: var(--zen-colors-input-bg) !important; diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index 288032e8b..34a6e6466 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -73,6 +73,10 @@ filter: grayscale(0); opacity: 1; } + + &:hover { + background-color: var(--zen-toolbar-element-bg); + } } } } diff --git a/src/browser/base/zen-components/ZenCommonUtils.mjs b/src/browser/base/zen-components/ZenCommonUtils.mjs index 701363e36..83a75a1c8 100644 --- a/src/browser/base/zen-components/ZenCommonUtils.mjs +++ b/src/browser/base/zen-components/ZenCommonUtils.mjs @@ -69,7 +69,7 @@ var gZenCommonActions = { transferable.addDataFlavor('text/plain'); transferable.setTransferData('text/plain', str); Services.clipboard.setData(transferable, null, Ci.nsIClipboard.kGlobalClipboard); - ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-copy-current-url-confirmation'); + gZenUIManager.showToast('zen-copy-current-url-confirmation'); } }, copyCurrentURLAsMarkdownToClipboard() { @@ -84,7 +84,7 @@ var gZenCommonActions = { transferable.addDataFlavor('text/plain'); transferable.setTransferData('text/plain', str); Services.clipboard.setData(transferable, null, Ci.nsIClipboard.kGlobalClipboard); - ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-copy-current-url-confirmation'); + gZenUIManager.showToast('zen-copy-current-url-confirmation'); } }, diff --git a/src/browser/base/zen-components/ZenGradientGenerator.mjs b/src/browser/base/zen-components/ZenGradientGenerator.mjs index 963f87f76..59a19671a 100644 --- a/src/browser/base/zen-components/ZenGradientGenerator.mjs +++ b/src/browser/base/zen-components/ZenGradientGenerator.mjs @@ -725,7 +725,7 @@ if (!skipSave) { await ZenWorkspacesStorage.saveWorkspaceTheme(currentWorkspace.uuid, gradient); await ZenWorkspaces._propagateWorkspaceData(); - ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-panel-ui-gradient-generator-saved-message'); + gZenUIManager.showToast('zen-panel-ui-gradient-generator-saved-message'); currentWorkspace = await ZenWorkspaces.getActiveWorkspace(); } diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 3bb7f747f..97a373cb0 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -615,68 +615,70 @@ document.getElementById('context_zen-pinned-tab-separator').hidden = !isVisible; } - moveToAnotherTabContainerIfNecessary(event, draggedTab) { + moveToAnotherTabContainerIfNecessary(event, movingTabs) { const pinnedTabsTarget = event.target.closest('#vertical-pinned-tabs-container') || event.target.closest('.zen-current-workspace-indicator'); const essentialTabsTarget = event.target.closest('#zen-essentials-container'); const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox'); - let moved = false; let isVertical = this.expandedSidebarMode; - let isRegularTabs = false; - // Check for pinned tabs container - if (pinnedTabsTarget) { - if (!draggedTab.pinned) { - gBrowser.pinTab(draggedTab); - moved = true; - } else if (draggedTab.hasAttribute('zen-essential')) { - this.removeEssentials(draggedTab); - gBrowser.pinTab(draggedTab); - moved = true; - } - } - // Check for essentials container - else if (essentialTabsTarget) { - if (!draggedTab.hasAttribute('zen-essential')) { - this.addToEssentials(draggedTab); - moved = true; - isVertical = false; - } - } - // Check for normal tabs container - else if (tabsTarget || event.target.id === 'zen-tabs-wrapper') { - if (draggedTab.pinned && !draggedTab.hasAttribute('zen-essential')) { - gBrowser.unpinTab(draggedTab); - moved = true; - isRegularTabs = true; - } else if (draggedTab.hasAttribute('zen-essential')) { - this.removeEssentials(draggedTab); - moved = true; - isRegularTabs = true; - } - } - - // If the tab was moved, adjust its position relative to the target tab - if (moved) { - const targetTab = event.target.closest('.tabbrowser-tab'); - if (targetTab) { - const rect = targetTab.getBoundingClientRect(); - let newIndex = targetTab._tPos; - - if (isVertical) { - const middleY = targetTab.screenY + rect.height / 2; - if (!isRegularTabs && event.screenY > middleY) { - newIndex++; - } else if (isRegularTabs && event.screenY < middleY) { - newIndex--; - } - } else { - const middleX = targetTab.screenX + rect.width / 2; - if (event.screenX > middleX) { - newIndex++; - } + let moved = false; + for (const draggedTab of movingTabs) { + let isRegularTabs = false; + // Check for pinned tabs container + if (pinnedTabsTarget) { + if (!draggedTab.pinned) { + gBrowser.pinTab(draggedTab); + moved = true; + } else if (draggedTab.hasAttribute('zen-essential')) { + this.removeEssentials(draggedTab); + gBrowser.pinTab(draggedTab); + moved = true; + } + } + // Check for essentials container + else if (essentialTabsTarget) { + if (!draggedTab.hasAttribute('zen-essential')) { + this.addToEssentials(draggedTab); + moved = true; + isVertical = false; + } + } + // Check for normal tabs container + else if (tabsTarget || event.target.id === 'zen-tabs-wrapper') { + if (draggedTab.pinned && !draggedTab.hasAttribute('zen-essential')) { + gBrowser.unpinTab(draggedTab); + moved = true; + isRegularTabs = true; + } else if (draggedTab.hasAttribute('zen-essential')) { + this.removeEssentials(draggedTab); + moved = true; + isRegularTabs = true; + } + } + + // If the tab was moved, adjust its position relative to the target tab + if (moved) { + const targetTab = event.target.closest('.tabbrowser-tab'); + if (targetTab) { + const rect = targetTab.getBoundingClientRect(); + let newIndex = targetTab._tPos; + + if (isVertical) { + const middleY = targetTab.screenY + rect.height / 2; + if (!isRegularTabs && event.screenY > middleY) { + newIndex++; + } else if (isRegularTabs && event.screenY < middleY) { + newIndex--; + } + } else { + const middleX = targetTab.screenX + rect.width / 2; + if (event.screenX > middleX) { + newIndex++; + } + } + gBrowser.moveTabTo(draggedTab, newIndex); } - gBrowser.moveTabTo(draggedTab, newIndex); } } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index fb715e2a5..2224f6c5c 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -192,14 +192,13 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { afterRearangeAction() { document.getElementById('zenSplitViewModifier').hidePopup(); - ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-enabled-toast', { + gZenUIManager.showToast('zen-split-view-modifier-enabled-toast', { descriptionId: 'zen-split-view-modifier-enabled-toast-description', - showDescription: true, }); } afterRearangeRemove() { - ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-disabled-toast'); + gZenUIManager.showToast('zen-split-view-modifier-disabled-toast'); } toggleWrapperDisplay(value) { diff --git a/src/browser/components/sessionstore/TabState-sys-mjs.patch b/src/browser/components/sessionstore/TabState-sys-mjs.patch index a38f9b7c4..26972ac49 100644 --- a/src/browser/components/sessionstore/TabState-sys-mjs.patch +++ b/src/browser/components/sessionstore/TabState-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs -index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..83bf443ca158c07e05075777da02b7f228d83dff 100644 +index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..dc0fdf17952df397a684f8a1da2f71739d007350 100644 --- a/browser/components/sessionstore/TabState.sys.mjs +++ b/browser/components/sessionstore/TabState.sys.mjs -@@ -84,6 +84,13 @@ class _TabState { +@@ -84,6 +84,14 @@ class _TabState { tabData.groupId = tab.group.id; } @@ -12,6 +12,7 @@ index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..83bf443ca158c07e05075777da02b7f2 + tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId"); + tabData.zenPinnedEntry = tab.getAttribute("zen-pinned-entry"); + tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon"); ++ tabData.zenHasStaticLabel = tab.getAttribute("zen-has-static-label"); + tabData.searchMode = tab.ownerGlobal.gURLBar.getSearchMode(browser, true); diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 6790f1ba4..3a56da16a 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b62093051cc9a 100644 +index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafeda43b085 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js -@@ -406,11 +406,39 @@ +@@ -406,11 +406,52 @@ return this.tabContainer.visibleTabs; } @@ -13,6 +13,19 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 + break; + } + if (!tab.hidden) { ++ i += !tab.hasAttribute("zen-glance-tab"); ++ } ++ } ++ return i; ++ } ++ ++ get _numVisiblePinTabsWithoutGlance() { ++ let i = 0; ++ for (let tab of this.tabs) { ++ if (!tab.pinned) { ++ break; ++ } ++ if (!tab.hidden && !tab.hasAttribute("zen-glance-tab")) { + i++; + } + } @@ -26,7 +39,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 + break; + } + if (!tab.hidden) { -+ i++; ++ i += !tab.hasAttribute("zen-glance-tab"); + } + } + return i; @@ -40,11 +53,11 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 + if (!tab.pinned && !tab.hasAttribute("zen-glance-tab")) { break; } -+ i++; ++ i += !tab.hasAttribute("zen-glance-tab"); } return i; } -@@ -807,7 +835,7 @@ +@@ -807,7 +848,7 @@ this.showTab(aTab); if (this.tabContainer.verticalMode) { this._handleTabMove(aTab, () => @@ -53,7 +66,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 ); } else { this.moveTabTo(aTab, this.pinnedTabCount, { forceStandaloneTab: true }); -@@ -828,7 +856,7 @@ +@@ -828,7 +869,7 @@ // the moving of a tab from the vertical pinned tabs container // and back into arrowscrollbox. aTab.removeAttribute("pinned"); @@ -62,7 +75,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 }); } else { this.moveTabTo(aTab, this.pinnedTabCount - 1, { -@@ -1055,6 +1083,8 @@ +@@ -1055,6 +1096,8 @@ let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"]; @@ -71,7 +84,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if ( aIconURL && !aLoadingPrincipal && -@@ -1065,6 +1095,9 @@ +@@ -1065,6 +1108,9 @@ ); return; } @@ -81,7 +94,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1310,6 +1343,7 @@ +@@ -1310,6 +1356,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); newTab.updateLastAccessed(); @@ -89,7 +102,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 oldTab.updateLastAccessed(); // if this is the foreground window, update the last-seen timestamps. if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) { -@@ -1462,6 +1496,9 @@ +@@ -1462,6 +1509,9 @@ } let activeEl = document.activeElement; @@ -99,7 +112,16 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 // If focus is on the old tab, move it to the new tab. if (activeEl == oldTab) { newTab.focus(); -@@ -2387,7 +2424,7 @@ +@@ -1785,7 +1835,7 @@ + } + + _setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) { +- if (!aLabel || aLabel.includes("about:reader?")) { ++ if (!aLabel || aLabel.includes("about:reader?") || aTab.hasAttribute("zen-has-static-label")) { + return false; + } + +@@ -2387,7 +2437,7 @@ let panel = this.getPanel(browser); let uniqueId = this._generateUniquePanelID(); @@ -108,7 +130,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 aTab.linkedPanel = uniqueId; // Inject the into the DOM if necessary. -@@ -2446,8 +2483,8 @@ +@@ -2446,8 +2496,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) { @@ -119,7 +141,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 } else { aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1; } -@@ -2679,6 +2716,12 @@ +@@ -2679,6 +2729,12 @@ ); } @@ -132,7 +154,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (!UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.start("browser.tabs.opening", "initting", window); } -@@ -2742,6 +2785,12 @@ +@@ -2742,6 +2798,12 @@ noInitialLabel, skipBackgroundNotify, }); @@ -145,7 +167,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (insertTab) { // insert the tab into the tab container in the correct position this._insertTabAtIndex(t, { -@@ -2885,6 +2934,9 @@ +@@ -2885,6 +2947,9 @@ } } @@ -155,7 +177,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 // Additionally send pinned tab events if (pinned) { this._notifyPinnedStatus(t); -@@ -3403,6 +3455,21 @@ +@@ -3403,6 +3468,21 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -177,7 +199,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3416,6 +3483,7 @@ +@@ -3416,6 +3496,7 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -185,7 +207,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3451,7 +3519,21 @@ +@@ -3451,7 +3532,21 @@ skipLoad: true, preferredRemoteType, }); @@ -208,7 +230,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (select) { tabToSelect = tab; } -@@ -3464,8 +3546,8 @@ +@@ -3464,8 +3559,8 @@ // inserted in the DOM. If the tab is not yet in the DOM, // just insert it in the right place from the start. if (!tab.parentNode) { @@ -219,7 +241,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3729,7 +3811,7 @@ +@@ -3729,7 +3824,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. @@ -228,7 +250,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if ( !bulkOrderedOpen && ((openerTab && -@@ -3780,7 +3862,7 @@ +@@ -3780,7 +3875,7 @@ } /** @type {MozTabbrowserTab|undefined} */ @@ -237,7 +259,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 this.tabContainer._invalidateCachedTabs(); if (tabGroup) { -@@ -4095,6 +4177,9 @@ +@@ -4095,6 +4190,9 @@ return; } @@ -247,7 +269,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 this.removeTabs(selectedTabs); } -@@ -4427,6 +4512,7 @@ +@@ -4427,6 +4525,7 @@ skipSessionStore, } = {} ) { @@ -255,7 +277,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4443,6 +4529,12 @@ +@@ -4443,6 +4542,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -268,7 +290,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4457,7 +4549,9 @@ +@@ -4457,7 +4562,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -279,7 +301,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4471,7 +4565,6 @@ +@@ -4471,7 +4578,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -287,7 +309,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4610,14 +4703,14 @@ +@@ -4610,14 +4716,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -304,7 +326,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4812,6 +4905,8 @@ +@@ -4812,6 +4918,8 @@ this.tabs[i]._tPos = i; } @@ -313,7 +335,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -5465,10 +5560,10 @@ +@@ -5465,10 +5573,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -326,19 +348,28 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5706,9 +5801,9 @@ +@@ -5706,9 +5814,9 @@ // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { - aIndex = Math.min(aIndex, this.pinnedTabCount - 1); -+ aIndex = Math.min(aIndex, this._numVisiblePinTabs - 1); ++ aIndex = Math.min(aIndex, (aTab.hasAttribute('zen-essential') ? this._numZenEssentials : this._numVisiblePinTabsWithoutGlance) - 1); } else { - aIndex = Math.max(aIndex, this.pinnedTabCount); -+ aIndex = Math.max(aIndex, this._numVisiblePinTabs); ++ aIndex = Math.max(aIndex, this._numVisiblePinTabsWithoutGlance); } if (aTab._tPos == aIndex) { return; -@@ -5727,6 +5822,9 @@ +@@ -5717,7 +5825,7 @@ + this._lastRelatedTabMap = new WeakMap(); + + this._handleTabMove(aTab, () => { +- let neighbor = this.tabs[aIndex]; ++ let neighbor = this.tabs.filter(tab => !tab.hasAttribute("zen-glance-tab"))[aIndex]; + if (forceStandaloneTab && neighbor.group) { + neighbor = neighbor.group; + } +@@ -5727,6 +5835,9 @@ this.tabContainer.insertBefore(aTab, neighbor); } }); @@ -348,7 +379,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 } moveTabToGroup(aTab, aGroup) { -@@ -5802,7 +5900,7 @@ +@@ -5802,7 +5913,7 @@ createLazyBrowser, }; @@ -357,7 +388,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -7443,6 +7541,7 @@ +@@ -7443,6 +7554,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -365,7 +396,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; gBrowser.syncThrobberAnimations(this.mTab); -@@ -8411,7 +8510,7 @@ var TabContextMenu = { +@@ -8411,7 +8523,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -374,7 +405,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8444,7 +8543,7 @@ var TabContextMenu = { +@@ -8444,7 +8556,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -383,7 +414,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..5db2380df21f4b25a6c03bfa457b6209 contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8677,6 +8776,7 @@ var TabContextMenu = { +@@ -8677,6 +8789,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 878c2193a..03326222f 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index 8aeb244ffca9f48661805f5b7d860b5896055562..3d323615040dcb5e379519878fb7874d5b28de81 100644 +index 8aeb244ffca9f48661805f5b7d860b5896055562..393458caa425e0a980223cd3800ea0ef33542c84 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -52,7 +52,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..3d323615040dcb5e379519878fb7874d this._tabDropIndicator.hidden = true; event.stopPropagation(); + if (draggedTab && dropEffect == "move") { -+ let moved = gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, draggedTab); ++ let moved = gZenPinnedTabManager.moveToAnotherTabContainerIfNecessary(event, movingTabs); + + if (moved) { + this._finishMoveTogetherSelectedTabs(draggedTab);