diff --git a/locales/en-US/browser/browser/zen-folders.ftl b/locales/en-US/browser/browser/zen-folders.ftl index 774638949..3e6d3c467 100644 --- a/locales/en-US/browser/browser/zen-folders.ftl +++ b/locales/en-US/browser/browser/zen-folders.ftl @@ -23,4 +23,10 @@ zen-folders-panel-change-folder-space = zen-folders-panel-change-icon-folder = .label = Change Icon +zen-folders-unload-all-tooltip = + .tooltiptext = Unload all tabs in this folder + +zen-folders-unload-folder = + .label = Unload All Tabs + zen-folders-search-no-results = No tabs matching that search 🤔 diff --git a/src/browser/base/content/zen-panels/popups.inc b/src/browser/base/content/zen-panels/popups.inc index 5352eabd4..7f23e2704 100644 --- a/src/browser/base/content/zen-panels/popups.inc +++ b/src/browser/base/content/zen-panels/popups.inc @@ -36,8 +36,9 @@ + - + diff --git a/src/browser/themes/linux/browser-css.patch b/src/browser/themes/linux/browser-css.patch index fb8f1c3ef..258dc3936 100644 --- a/src/browser/themes/linux/browser-css.patch +++ b/src/browser/themes/linux/browser-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css -index dadb198cbf968dc622d2d0ee6c754f3541c052a2..5b7d17d8705c7cfddaee04c90d342bd705338a18 100644 +index dadb198cbf968dc622d2d0ee6c754f3541c052a2..ef8ed137443a089e5ac084bb8f86533ddd2086a1 100644 --- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -43,7 +43,8 @@ @@ -7,25 +7,24 @@ index dadb198cbf968dc622d2d0ee6c754f3541c052a2..5b7d17d8705c7cfddaee04c90d342bd7 appearance: auto; - #navigator-toolbox, -+ #zen-main-app-wrapper, -+ #zen-browser-background, ++ #zen-main-app-wrapper, ++ #zen-browser-background, dialog::backdrop { border-top-left-radius: env(-moz-gtk-csd-titlebar-radius); border-top-right-radius: env(-moz-gtk-csd-titlebar-radius); -@@ -51,13 +52,14 @@ +@@ -51,13 +52,10 @@ /* stylelint-disable-next-line media-query-no-invalid */ @media -moz-pref("widget.gtk.rounded-bottom-corners.enabled") { - #navigator-toolbox { -+ #zen-main-app-wrapper { - /* The body clip below covers this. */ - border-radius: 0; - } +- /* The body clip below covers this. */ +- border-radius: 0; +- } body, - dialog::backdrop { -+ dialog::backdrop, -+ #zen-browser-background { ++ dialog::backdrop, ++ #zen-browser-background { /* Use an uniform clip to allow WebRender to optimize it better */ border-radius: env(-moz-gtk-csd-titlebar-radius); } diff --git a/src/zen/common/ZenStartup.mjs b/src/zen/common/ZenStartup.mjs index 52578dcbb..89fac987f 100644 --- a/src/zen/common/ZenStartup.mjs +++ b/src/zen/common/ZenStartup.mjs @@ -177,13 +177,16 @@ const appWrapper = document.getElementById('zen-main-app-wrapper'); const element = document.createElement('div'); element.id = 'zen-update-animation'; + const elementBorder = document.createElement('div'); + elementBorder.id = 'zen-update-animation-border'; requestIdleCallback(() => { if (gReduceMotion) { return; } appWrapper.appendChild(element); - gZenUIManager.motion - .animate( + appWrapper.appendChild(elementBorder); + Promise.all([ + gZenUIManager.motion.animate( '#zen-update-animation', { top: ['100%', '-50%'], @@ -192,10 +195,21 @@ { duration: 0.35, } - ) - .then(() => { - element.remove(); - }); + ), + gZenUIManager.motion.animate( + '#zen-update-animation-border', + { + '--background-top': ['150%', '-50%'], + }, + { + duration: 0.35, + delay: 0.1, + } + ), + ]).then(() => { + element.remove(); + elementBorder.remove(); + }); }); } })(); diff --git a/src/zen/common/ZenUIManager.mjs b/src/zen/common/ZenUIManager.mjs index 002c3a95e..bc13275be 100644 --- a/src/zen/common/ZenUIManager.mjs +++ b/src/zen/common/ZenUIManager.mjs @@ -74,6 +74,24 @@ var gZenUIManager = { gZenVerticalTabsManager.init(); this._initCreateNewPopup(); + this._debloatContextMenus(); + }, + + _debloatContextMenus() { + const contextMenusToClean = [ + // Remove the 'new tab below' context menu. + // reason: It doesn't properly work with zen and it's philosophy of not having + // new tabs. It's also semi-not working as it doesn't create a new tab below + // the current one. + 'context_openANewTab', + ]; + for (const id of contextMenusToClean) { + const menu = document.getElementById(id); + if (!menu) { + continue; + } + menu.setAttribute('hidden', 'true'); + } }, _initCreateNewPopup() { diff --git a/src/zen/common/styles/zen-single-components.css b/src/zen/common/styles/zen-single-components.css index 43eff5325..9919b3fae 100644 --- a/src/zen/common/styles/zen-single-components.css +++ b/src/zen/common/styles/zen-single-components.css @@ -201,3 +201,24 @@ body > #confetti { transform: translateY(-50%); pointer-events: none; } + +#zen-update-animation-border { + position: absolute; + inset: 0; + border: solid 2px #0000; + border-radius: var(--zen-native-content-radius); + background: radial-gradient( + ellipse 100% 50% at center var(--background-top), + rgba(255, 255, 255, 0.8) 80%, + transparent + ) + border-box; + /* ensure gradient size is relative to border-box (not default padding-box) */ + --lyr: conic-gradient(white 0 0); /* any kind of gradient that's opaque everywhere */ + /* exclude padding-box (that is, mask out everything but the border area) */ + mask: + var(--lyr) padding-box exclude, + var(--lyr); + content: ''; + pointer-events: none; +} diff --git a/src/zen/folders/ZenFolder.mjs b/src/zen/folders/ZenFolder.mjs index fe792dd44..d6a57c2be 100644 --- a/src/zen/folders/ZenFolder.mjs +++ b/src/zen/folders/ZenFolder.mjs @@ -9,7 +9,7 @@ @@ -52,7 +52,7 @@ - + @@ -153,7 +153,7 @@ }); } - async expandGroupTabs() { + async unpackTabs() { for (let tab of this.allItems.reverse()) { tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab; if (tab.hasAttribute('zen-empty-tab')) { @@ -234,20 +234,20 @@ return this.labelElement.parentElement.querySelector('.tab-reset-button'); } - #unloadAllActiveTabs() { - for (const tab of this.activeTabs) { - const tabResetButton = tab.querySelector('.tab-reset-button'); - if (tabResetButton) { - tabResetButton.click(); - } + unloadAllTabs(event) { + this.#unloadAllActiveTabs(event, /* noClose */ true); + } + + #unloadAllActiveTabs(event, noClose = false) { + for (const tab of this.tabs) { + gZenPinnedTabManager._onCloseTabShortcut(event, tab, { noClose }); } this.activeTabs = []; } on_click(event) { if (event.target === this.resetButton) { - event.stopPropagation(); - this.#unloadAllActiveTabs(); + this.#unloadAllActiveTabs(event); return; } super.on_click(event); diff --git a/src/zen/folders/ZenFolders.mjs b/src/zen/folders/ZenFolders.mjs index 3d4e0ae98..4f09e1853 100644 --- a/src/zen/folders/ZenFolders.mjs +++ b/src/zen/folders/ZenFolders.mjs @@ -133,8 +133,11 @@ case 'context_zenFolderRename': this.#lastFolderContextMenu.rename(); break; - case 'context_zenFolderExpand': - this.#lastFolderContextMenu.expandGroupTabs(); + case 'context_zenFolderUnpack': + this.#lastFolderContextMenu.unpackTabs(); + break; + case 'context_zenFolderUnloadAll': + this.#lastFolderContextMenu.unloadAllTabs(event); break; case 'context_zenFolderNewSubfolder': this.#lastFolderContextMenu.createSubfolder(); @@ -448,11 +451,12 @@ }); animations.push(...this.updateFolderIcon(group)); + const startMargin = -(heightUntilSelected + 4 * (selectedItems.length === 0 ? 1 : 0)); animations.push( gZenUIManager.motion.animate( groupStart, { - marginTop: -(heightUntilSelected + 4 * (selectedItems.length === 0 ? 1 : 0)), + marginTop: startMargin, }, { duration: 0.12, ease: 'easeInOut' } ) @@ -1235,6 +1239,11 @@ } collapseVisibleTab(group, onlyIfActive = false, selectedTab = null) { + let tabsToCollapse = [selectedTab]; + if (group?.hasAttribute('split-view-group')) { + group = group.group; + tabsToCollapse = group.tabs; + } if (!group?.isZenFolder) return; if (onlyIfActive && group.activeGroups.length && selectedTab) { @@ -1255,7 +1264,7 @@ for (const item of group._prevActiveTabs) { if ( item.hasAttribute('folder-active') && - (selectedTab ? item === selectedTab : !item.selected || !onlyIfActive) + (selectedTab ? tabsToCollapse.includes(item) : !item.selected || !onlyIfActive) ) { item.removeAttribute('folder-active'); group.activeTabs = group.activeTabs.filter((t) => t !== item); diff --git a/src/zen/folders/zen-folders.css b/src/zen/folders/zen-folders.css index 66a647538..fe8bc16a8 100644 --- a/src/zen/folders/zen-folders.css +++ b/src/zen/folders/zen-folders.css @@ -277,7 +277,6 @@ zen-folder { fill-opacity: 0.9; -moz-context-properties: fill, fill-opacity; fill: var(--zen-folder-stroke); - transform: translate(-180%, 2.5px); } } @@ -341,7 +340,7 @@ zen-folder { } } - &[has-active] > .tab-group-label-container { + :root[zen-sidebar-expanded] &[has-active] > .tab-group-label-container { & .tab-reset-button { display: flex; opacity: 0; diff --git a/src/zen/tabs/ZenPinnedTabManager.mjs b/src/zen/tabs/ZenPinnedTabManager.mjs index f96d7da03..226b1c058 100644 --- a/src/zen/tabs/ZenPinnedTabManager.mjs +++ b/src/zen/tabs/ZenPinnedTabManager.mjs @@ -733,7 +733,7 @@ async _onCloseTabShortcut( event, selectedTab = gBrowser.selectedTab, - behavior = lazy.zenPinnedTabCloseShortcutBehavior + { behavior = lazy.zenPinnedTabCloseShortcutBehavior, noClose = false } = {} ) { if (!selectedTab?.pinned) { return; @@ -742,6 +742,10 @@ event.stopPropagation(); event.preventDefault(); + if (noClose && behavior === 'close') { + behavior = 'unload-switch'; + } + switch (behavior) { case 'close': this._removePinnedAttributes(selectedTab, true); @@ -780,7 +784,11 @@ /* only if active */ true, selectedTab ); - await gBrowser.explicitUnloadTabs([selectedTab]); + let tabsToUnload = [selectedTab]; + if (selectedTab.group?.hasAttribute('split-view-group')) { + tabsToUnload = selectedTab.group.tabs; + } + await gBrowser.explicitUnloadTabs(tabsToUnload); selectedTab.removeAttribute('discarded'); } if (selectedTab.selected) {