diff --git a/prefs/zen/view.yaml b/prefs/zen/view.yaml index c5970430e..8235e67fe 100644 --- a/prefs/zen/view.yaml +++ b/prefs/zen/view.yaml @@ -57,3 +57,6 @@ - name: zen.view.shift-down-site-on-hover value: false + +- name: zen.view.show-clear-tabs-button + value: true diff --git a/prefs/zen/zen-urlbar.yaml b/prefs/zen/zen-urlbar.yaml index 97be59be9..4bd362402 100644 --- a/prefs/zen/zen-urlbar.yaml +++ b/prefs/zen/zen-urlbar.yaml @@ -26,6 +26,9 @@ - name: zen.urlbar.enable-overrides value: false +- name: zen.urlbar.single-toolbar-show-copy-url + value: true + # Mark: Zen suggestions controls - name: zen.urlbar.suggestions.quick-actions diff --git a/src/browser/base/content/browser-addons-js.patch b/src/browser/base/content/browser-addons-js.patch index 0264323c8..edd6cb122 100644 --- a/src/browser/base/content/browser-addons-js.patch +++ b/src/browser/base/content/browser-addons-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js -index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..29864ab59819271b7319b273c08bdc2736d40c93 100644 +index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..ed3062bab0b80db3b456cdad03e7efcc31266b08 100644 --- a/browser/base/content/browser-addons.js +++ b/browser/base/content/browser-addons.js @@ -1071,7 +1071,7 @@ var gXPInstallObserver = { @@ -7,7 +7,7 @@ index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..29864ab59819271b7319b273c08bdc27 hideClose: true, popupOptions: { - position: "bottomright topright", -+ position: gZenUIManager.panelUIPosition, ++ position: gZenUIManager.panelUIPosition(), }, }; @@ -16,7 +16,7 @@ index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..29864ab59819271b7319b273c08bdc27 timeout: Date.now() + 30000, popupOptions: { - position: "bottomright topright", -+ position: gZenUIManager.panelUIPosition, ++ position: gZenUIManager.panelUIPosition(), }, }; @@ -65,7 +65,7 @@ index 754ce380ed233eb8764af07af3c8dc95d3f39d5c..29864ab59819271b7319b273c08bdc27 this.ensureButtonShownBeforeAttachingPanel(panel); PanelMultiView.openPopup(panel, this._button, { - position: "bottomright topright", -+ position: gZenUIManager.panelUIPosition, ++ position: gZenUIManager.panelUIPosition(panel, this._button), triggerEvent: aEvent, }); } diff --git a/src/browser/base/content/browser-places-js.patch b/src/browser/base/content/browser-places-js.patch index e302f2838..5425bd91e 100644 --- a/src/browser/base/content/browser-places-js.patch +++ b/src/browser/base/content/browser-places-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js -index 79b4f6f8fb2f7dd8784920038784e6bb0c967e2d..1f3f4991b3ba7c00516e9708e89e8f95db25a36a 100644 +index 79b4f6f8fb2f7dd8784920038784e6bb0c967e2d..4db983dad9bea10c17b5ac166ba58b93fa2a4d56 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -252,6 +252,8 @@ var StarUI = { @@ -33,3 +33,11 @@ index 79b4f6f8fb2f7dd8784920038784e6bb0c967e2d..1f3f4991b3ba7c00516e9708e89e8f95 removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() { this._removeBookmarksOnPopupHidden = true; this.panel.hidePopup(); +@@ -1800,6 +1817,7 @@ var BookmarkingUI = { + document.getElementById("context-bookmarkpage"), + PanelMultiView.getViewNode(document, "panelMenuBookmarkThisPage"), + document.getElementById("pageAction-panel-bookmark"), ++ document.getElementById("zen-site-data-icon-button"), + ]) { + if (!element) { + // The page action panel element may not have been created yet. diff --git a/src/browser/base/content/navigator-toolbox-js.patch b/src/browser/base/content/navigator-toolbox-js.patch index 167525ff8..829800da2 100644 --- a/src/browser/base/content/navigator-toolbox-js.patch +++ b/src/browser/base/content/navigator-toolbox-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/base/content/navigator-toolbox.js b/browser/base/content/navigator-toolbox.js -index 413bad2a62058a1c434d6a44e927e44eb397289d..472eab5d3bca2bc665920707a71105167cbe75ec 100644 +index 413bad2a62058a1c434d6a44e927e44eb397289d..d28116ffacb0ddb6fdb421db5d6498e455356b4a 100644 --- a/browser/base/content/navigator-toolbox.js +++ b/browser/base/content/navigator-toolbox.js @@ -8,7 +8,7 @@ @@ -11,24 +11,6 @@ index 413bad2a62058a1c434d6a44e927e44eb397289d..472eab5d3bca2bc665920707a7110516 const widgetOverflow = document.getElementById("widget-overflow"); function onPopupShowing(event) { -@@ -110,7 +110,7 @@ document.addEventListener( - #pageActionButton, - #downloads-button, - #fxa-toolbar-menu-button, -- #unified-extensions-button, -+ #zen-site-data-icon-button, - #library-button - `); - if (!element) { -@@ -138,7 +138,7 @@ document.addEventListener( - gSync.toggleAccountPanel(element, event); - break; - -- case "unified-extensions-button": -+ case "zen-site-data-icon-button": - gUnifiedExtensions.togglePanel(event); - break; - @@ -187,6 +187,7 @@ document.addEventListener( #reload-button , #urlbar-go-button, diff --git a/src/browser/base/content/zen-panels/site-data.inc b/src/browser/base/content/zen-panels/site-data.inc index bf310982b..b3b99dc06 100644 --- a/src/browser/base/content/zen-panels/site-data.inc +++ b/src/browser/base/content/zen-panels/site-data.inc @@ -5,8 +5,7 @@ + noautofocus="true"> # We'll keep the view with this name/id in order to prevent # any sort of future issues we may have if firefox decides diff --git a/src/browser/components/customizableui/content/panelUI-js.patch b/src/browser/components/customizableui/content/panelUI-js.patch index c20733de9..23ea8bef7 100644 --- a/src/browser/components/customizableui/content/panelUI-js.patch +++ b/src/browser/components/customizableui/content/panelUI-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js -index 7156397d597579f745ea20ae2b9327433a31c8ec..13b844a63e79e227c96faf153ee5908759306407 100644 +index 7156397d597579f745ea20ae2b9327433a31c8ec..23c15c60acd77150ea89bd6f2fa1685a0cfc37fd 100644 --- a/browser/components/customizableui/content/panelUI.js +++ b/browser/components/customizableui/content/panelUI.js @@ -518,8 +518,7 @@ const PanelUI = { @@ -30,7 +30,7 @@ index 7156397d597579f745ea20ae2b9327433a31c8ec..13b844a63e79e227c96faf153ee59087 }); - this.notificationPanel.openPopup(anchor, "bottomright topright"); -+ this.notificationPanel.openPopup(anchor, gZenUIManager.panelUIPosition); ++ this.notificationPanel.openPopup(anchor, gZenUIManager.panelUIPosition(this.notificationPanel, anchor)); }, _clearNotificationPanel() { diff --git a/src/browser/modules/ExtensionsUI-sys-mjs.patch b/src/browser/modules/ExtensionsUI-sys-mjs.patch index 9cb95334a..0466fcc51 100644 --- a/src/browser/modules/ExtensionsUI-sys-mjs.patch +++ b/src/browser/modules/ExtensionsUI-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/modules/ExtensionsUI.sys.mjs b/browser/modules/ExtensionsUI.sys.mjs -index 17cad7b3fbdd6dff862483892f37f72c00792c88..72d87d70182abfbf664b1dc86f4b4a3ecb2b1d01 100644 +index 17cad7b3fbdd6dff862483892f37f72c00792c88..90ea4d95738eb50d1a4a67ee7df087e7c2a68b3d 100644 --- a/browser/modules/ExtensionsUI.sys.mjs +++ b/browser/modules/ExtensionsUI.sys.mjs @@ -478,7 +478,7 @@ export var ExtensionsUI = { @@ -7,7 +7,7 @@ index 17cad7b3fbdd6dff862483892f37f72c00792c88..72d87d70182abfbf664b1dc86f4b4a3e removeOnDismissal: true, popupOptions: { - position: "bottomright topright", -+ position: window.gZenUIManager.panelUIPosition, ++ position: window.gZenUIManager.panelUIPosition(), }, // Pass additional options used internally by the // addon-webext-permissions-notification custom element diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index 082e5b7c8..71416c647 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -399,6 +399,10 @@ &:not([can-close='true']) .toolbarbutton-icon { display: none; } + + @media -moz-pref('zen.view.show-clear-tabs-button', false) { + display: none; + } } .zen-workspace-actions-reorder-icon, @@ -513,7 +517,7 @@ -moz-context-properties: fill, fill-opacity; pointer-events: none; } - &[open] image { + &:is([open], [starred]) image { list-style-image: url('permissions-fill.svg'); } } diff --git a/src/zen/common/ZenUIManager.mjs b/src/zen/common/ZenUIManager.mjs index a95f7e60d..a65b9540f 100644 --- a/src/zen/common/ZenUIManager.mjs +++ b/src/zen/common/ZenUIManager.mjs @@ -610,10 +610,59 @@ var gZenUIManager = { this._toastTimeouts[messageId] = setTimeout(timeoutFunction, options.timeout || 2000); }, - get panelUIPosition() { - return gZenVerticalTabsManager._hasSetSingleToolbar && !gZenVerticalTabsManager._prefsRightSide - ? 'bottomleft topleft' - : 'bottomright topright'; + panelUIPosition(panel, anchor) { + void panel; + // The alignment position of the panel is determined during the "popuppositioned" event + // when the panel opens. The alignment positions help us determine in which orientation + // the panel is anchored to the screen space. + // + // * "after_start": The panel is anchored at the top-left corner in LTR locales, top-right in RTL locales. + // * "after_end": The panel is anchored at the top-right corner in LTR locales, top-left in RTL locales. + // * "before_start": The panel is anchored at the bottom-left corner in LTR locales, bottom-right in RTL locales. + // * "before_end": The panel is anchored at the bottom-right corner in LTR locales, bottom-left in RTL locales. + // + // ┌─Anchor(LTR) ┌─Anchor(RTL) + // │ Anchor(RTL)─┐ │ Anchor(LTR)─┐ + // │ │ │ │ + // x───────────────────x x───────────────────x + // │ │ │ │ + // │ Panel │ │ Panel │ + // │ "after_start" │ │ "after_end" │ + // │ │ │ │ + // └───────────────────┘ └───────────────────┘ + // + // ┌───────────────────┐ ┌───────────────────┐ + // │ │ │ │ + // │ Panel │ │ Panel │ + // │ "before_start" │ │ "before_end" │ + // │ │ │ │ + // x───────────────────x x───────────────────x + // │ │ │ │ + // │ Anchor(RTL)─┘ │ Anchor(LTR)─┘ + // └─Anchor(LTR) └─Anchor(RTL) + // + // The default choice for the panel is "after_start", to match the content context menu's alignment. However, it is + // possible to end up with any of the four combinations. Before the panel is opened, the XUL popup manager needs to + // make a determination about the size of the panel and whether or not it will fit within the visible screen area with + // the intended alignment. The manager may change the panel's alignment before opening to ensure the panel is fully visible. + // + // For example, if the panel is opened such that the bottom edge would be rendered off screen, then the XUL popup manager + // will change the alignment from "after_start" to "before_start", anchoring the panel's bottom corner to the target screen + // location instead of its top corner. This transformation ensures that the whole of the panel is visible on the screen. + // + // When the panel is anchored by one of its bottom corners (the "before_..." options), then it causes unintentionally odd + // behavior where dragging the text-area resizer downward with the mouse actually grows the panel's top edge upward, since + // the bottom of the panel is anchored in place. We want to disable the resizer if the panel was positioned to be anchored + // from one of its bottom corners. + let block = 'before'; + let inline = 'end'; + if (anchor?.closest('#zen-sidebar-top-buttons')) { + block = 'after'; + } + if (gZenVerticalTabsManager._hasSetSingleToolbar && !gZenVerticalTabsManager._prefsRightSide) { + inline = 'start'; + } + return `${block}_${inline}`; }, urlStringsDomainMatch(url1, url2) { diff --git a/src/zen/common/styles/zen-omnibox.css b/src/zen/common/styles/zen-omnibox.css index 7d07cc6dc..a150a3aab 100644 --- a/src/zen/common/styles/zen-omnibox.css +++ b/src/zen/common/styles/zen-omnibox.css @@ -189,6 +189,12 @@ } } +@media -moz-pref('zen.urlbar.single-toolbar-show-copy-url', false) { + :root[zen-single-toolbar='true'] #zen-copy-url-button { + display: none !important; + } +} + .urlbar-page-action, #tracking-protection-icon-container { padding: 0 !important; diff --git a/src/zen/compact-mode/sidebar.inc.css b/src/zen/compact-mode/sidebar.inc.css index 62a906ce9..40fecdf51 100644 --- a/src/zen/compact-mode/sidebar.inc.css +++ b/src/zen/compact-mode/sidebar.inc.css @@ -42,6 +42,7 @@ :root[zen-no-padding='true'] & { --zen-compact-float: 10px; + --zen-compact-top-toolbar-hidden-fix: var(--zen-compact-float); --zen-compact-mode-no-padding-radius-fix: 2px; } @@ -68,7 +69,7 @@ bottom: calc(var(--zen-compact-float) / 2); height: calc(100% - var(--zen-toolbar-height-with-bookmarks)); @media -moz-pref('zen.view.compact.hide-toolbar') { - height: 100%; + height: calc(100% - var(--zen-compact-top-toolbar-hidden-fix, 0px)); } } & #zen-sidebar-top-buttons { diff --git a/src/zen/urlbar/ZenSiteDataPanel.sys.mjs b/src/zen/urlbar/ZenSiteDataPanel.sys.mjs index ad3382a11..48b94bace 100644 --- a/src/zen/urlbar/ZenSiteDataPanel.sys.mjs +++ b/src/zen/urlbar/ZenSiteDataPanel.sys.mjs @@ -52,6 +52,7 @@ export class nsZenSiteDataPanel { this.panel.addEventListener('popupshowing', this); this.document.getElementById('zen-site-data-manage-addons').addEventListener('click', this); this.document.getElementById('zen-site-data-settings-more').addEventListener('click', this); + this.anchor.addEventListener('click', this); const kCommandIDs = [ 'zen-site-data-header-share', 'zen-site-data-header-bookmark', @@ -139,6 +140,12 @@ export class nsZenSiteDataPanel { } } + get #currentPageIsBookmarked() { + // A hacky way to check if the current page is bookmarked, but + // it works for our purposes. + return this.window.BookmarkingUI.star?.hasAttribute('starred'); + } + #setSiteHeader() { { const button = this.document.getElementById('zen-site-data-header-reader-mode'); @@ -156,7 +163,7 @@ export class nsZenSiteDataPanel { } { const button = this.document.getElementById('zen-site-data-header-bookmark'); - const isPageBookmarked = this.window.BookmarkingUI.star?.hasAttribute('starred'); + const isPageBookmarked = this.#currentPageIsBookmarked; if (isPageBookmarked) { button.classList.add('active'); @@ -548,6 +555,10 @@ export class nsZenSiteDataPanel { BrowserCommands.pageInfo(null, 'permTab'); break; } + case 'zen-site-data-icon-button': { + this.window.gUnifiedExtensions.togglePanel(event); + break; + } default: { const item = event.target.closest('.permission-popup-permission-item'); if (!item) { diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index a54c1ebfe..8bce5d7e7 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -2502,7 +2502,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { } // Only animate if it's from an event let animateContainer = target && target.target instanceof EventTarget; - if (target?.type === 'TabClose' || target?.type === 'TabOpened') { + if (target?.type === 'TabClose' || target?.type === 'TabOpen') { animateContainer = target.target.pinned; } await this.onPinnedTabsResize( @@ -2514,14 +2514,29 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { ); } - updateShouldHideSeparator(arrowScrollbox, pinnedContainer) { + updateShouldHideSeparator(arrowScrollbox, pinnedContainer, fromTabSelection = false) { + const visibleTabsFound = () => { + let count = 0; + for (const child of arrowScrollbox.children) { + if ( + !child.hasAttribute('hidden') && + !child.closing && + !child.hasAttribute('zen-empty-tab') + ) { + count++; + if (count > 1) { + // Early return + return true; + } + } + } + return false; + }; + // <= 2 because we have the empty tab and the new tab button - const shouldHideSeparator = - pinnedContainer.children.length === 1 || - Array.from(arrowScrollbox.children).filter( - (child) => - !child.hasAttribute('hidden') && !child.closing && !child.hasAttribute('zen-empty-tab') - ).length <= 1; + const shouldHideSeparator = fromTabSelection + ? pinnedContainer.hasAttribute('hide-separator') + : pinnedContainer.children.length === 1 || !visibleTabsFound(); if (shouldHideSeparator) { pinnedContainer.setAttribute('hide-separator', 'true'); } else { @@ -2656,7 +2671,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { } const workspaceID = tab.getAttribute('zen-workspace-id'); const isEssential = tab.getAttribute('zen-essential') === 'true'; - + this.updateShouldHideSeparator(this.activeWorkspaceStrip, this.pinnedTabsContainer, true); if (tab.hasAttribute('zen-empty-tab')) { return; } diff --git a/surfer.json b/surfer.json index 282528c9d..e88c81e65 100644 --- a/surfer.json +++ b/surfer.json @@ -19,7 +19,7 @@ "brandShortName": "Zen", "brandFullName": "Zen Browser", "release": { - "displayVersion": "1.17.4b", + "displayVersion": "1.17.5b", "github": { "repo": "zen-browser/desktop" },