mirror of
https://github.com/zen-browser/desktop.git
synced 2026-05-27 23:35:09 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db3eea65b7 | ||
|
|
b55358b9ab | ||
|
|
dba5a0402c | ||
|
|
92eb6b07c3 | ||
|
|
36aa7b0a20 | ||
|
|
0619d3d8de | ||
|
|
6b5f6c7b9d | ||
|
|
69e3a995ae | ||
|
|
e32ff53d2d | ||
|
|
ba593a19dc | ||
|
|
f40a7aaee1 | ||
|
|
62286a2758 | ||
|
|
067b8244ec | ||
|
|
be9928beda | ||
|
|
742a1e6882 | ||
|
|
a2796d7af0 | ||
|
|
2d6f2cbbde | ||
|
|
3fd89a93f5 | ||
|
|
595f236a7a | ||
|
|
8fec3702f4 | ||
|
|
ec2864902c | ||
|
|
7f00a16d6d | ||
|
|
65597fd6b5 | ||
|
|
fba5d0c4cc | ||
|
|
1089e72ef6 | ||
|
|
0829b3ac36 | ||
|
|
4c1e52c063 | ||
|
|
b39b9abc6f |
2
.github/workflows/issue-metrics.yml
vendored
2
.github/workflows/issue-metrics.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
echo "last_month_year=$previous_year" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Run issue-metrics tool
|
||||
uses: github/issue-metrics@v2
|
||||
uses: github-community-projects/issue-metrics@v2
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.DEPLOY_KEY }}
|
||||
HIDE_AUTHOR: true
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[-1] Unsplit Tabs
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[-1] Split out tab
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[-1] Unsplit Tabs
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[-1] Split out tab
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -6,7 +6,7 @@ tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (sono necessarie più schede selezionate)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
tab-zen-split-tabs =
|
||||
.label =
|
||||
{ $tabCount ->
|
||||
[1] Split Tab (multiple selected tabs needed)
|
||||
*[other] Split { $tabCount } Tabs
|
||||
[1] Join Tab (multiple selected tabs needed)
|
||||
*[other] Join { $tabCount } Tabs
|
||||
}
|
||||
.accesskey = S
|
||||
zen-split-link =
|
||||
|
||||
@@ -86,3 +86,7 @@
|
||||
- name: browser.tabs.splitView.enabled
|
||||
value: false
|
||||
locked: true
|
||||
|
||||
# See gh-12985 for details on the following preferences
|
||||
- name: browser.search.widget.new
|
||||
value: true
|
||||
|
||||
@@ -3,23 +3,6 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
<menupopup id="zenCreateNewPopup">
|
||||
<menu data-l10n-id="zen-panel-ui-live-folder-create" id="zen-panel-ui-live-folder-create">
|
||||
<menupopup>
|
||||
<menuitem
|
||||
data-l10n-id="zen-live-folder-github-pull-requests"
|
||||
command="cmd_zenNewLiveFolder"
|
||||
image="chrome://browser/skin/zen-icons/selectable/logo-github.svg" />
|
||||
<menuitem
|
||||
data-l10n-id="zen-live-folder-github-issues"
|
||||
command="cmd_zenNewLiveFolder"
|
||||
image="chrome://browser/skin/zen-icons/selectable/logo-github.svg" />
|
||||
<menuitem
|
||||
data-l10n-id="zen-live-folder-type-rss"
|
||||
command="cmd_zenNewLiveFolder"
|
||||
image="chrome://browser/skin/zen-icons/selectable/logo-rss.svg"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<menuitem data-l10n-id="zen-panel-ui-workspaces-create" command="cmd_zenOpenWorkspaceCreation" image="chrome://browser/skin/zen-icons/duplicate-tab.svg" />
|
||||
<menuitem data-l10n-id="zen-panel-ui-folder-create" command="cmd_zenOpenFolderCreation" image="chrome://browser/skin/zen-icons/folder.svg" />
|
||||
<menuseparator/>
|
||||
|
||||
@@ -1067,7 +1067,7 @@ var gZenCKSSettings = {
|
||||
zenMissingKeyboardShortcutL10n[conflictShortcut.getID()] ??
|
||||
conflictShortcut.getL10NID();
|
||||
|
||||
const [group] = await document.l10n.formatValues([
|
||||
const [group, conflictName] = await document.l10n.formatValues([
|
||||
{ id: `${ZEN_CKS_GROUP_PREFIX}-${conflictShortcut.getGroup()}` },
|
||||
{ id: shortcutL10nKey },
|
||||
]);
|
||||
@@ -1082,7 +1082,7 @@ var gZenCKSSettings = {
|
||||
|
||||
document.l10n.setAttributes(input.nextElementSibling, "zen-key-conflict", {
|
||||
group: group ?? "",
|
||||
shortcut: shortcut ?? "",
|
||||
shortcut: conflictName ?? shortcut ?? "",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
index ced2bfd88de2d16e2c028ca3f4d9d27516363575..aaf6e82782357c819ca875f05020723600e41e6b 100644
|
||||
index ced2bfd88de2d16e2c028ca3f4d9d27516363575..69b45c7dad9d294e4290de4ce878d184925e5610 100644
|
||||
--- a/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
+++ b/browser/components/tabbrowser/content/drag-and-drop.js
|
||||
@@ -35,6 +35,9 @@
|
||||
@@ -277,7 +277,11 @@ index ced2bfd88de2d16e2c028ca3f4d9d27516363575..aaf6e82782357c819ca875f050207236
|
||||
tab.removeAttribute("small-stack");
|
||||
tab.removeAttribute("big-stack");
|
||||
}
|
||||
@@ -2582,7 +2585,6 @@
|
||||
@@ -2578,11 +2581,9 @@
|
||||
)) {
|
||||
label.style.width = "";
|
||||
label.style.maxWidth = "";
|
||||
- label.style.height = "";
|
||||
label.style.left = "";
|
||||
label.style.top = "";
|
||||
label.style.pointerEvents = "";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js
|
||||
index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e0474669fc15c20 100644
|
||||
index e4266a159a0d5c42cc294602d00b8f66131f35d5..f3e362f062063ebe08bd26cc694f2d965ccffd84 100644
|
||||
--- a/browser/components/tabbrowser/content/tab.js
|
||||
+++ b/browser/components/tabbrowser/content/tab.js
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -52,7 +52,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,11 +228,23 @@
|
||||
@@ -225,11 +228,25 @@
|
||||
}
|
||||
|
||||
get visible() {
|
||||
@@ -74,14 +74,16 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
+ }
|
||||
+ currentParent = currentParent.group;
|
||||
+ }
|
||||
+ if (this.pinned && !this.hasAttribute("zen-essential") && gZenWorkspaces.activeWorkspaceElement?.hasCollapsedPinnedTabs) {
|
||||
+ if (this.pinned && !this.hasAttribute("zen-essential") &&
|
||||
+ gZenWorkspaces.activeWorkspaceElement?.hasCollapsedPinnedTabs &&
|
||||
+ !gZenWorkspaces.activeWorkspaceElement.collapsiblePins.activeTabs?.includes(this)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
}
|
||||
|
||||
get hidden() {
|
||||
@@ -308,7 +323,7 @@
|
||||
@@ -308,7 +325,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -90,7 +92,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
}
|
||||
|
||||
get lastAccessed() {
|
||||
@@ -393,7 +408,18 @@
|
||||
@@ -393,7 +410,18 @@
|
||||
}
|
||||
|
||||
get group() {
|
||||
@@ -110,7 +112,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
}
|
||||
|
||||
get splitview() {
|
||||
@@ -475,6 +501,10 @@
|
||||
@@ -475,6 +503,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
// If the previous target wasn't part of this tab then this is a mouseenter event.
|
||||
if (!this.contains(event.relatedTarget)) {
|
||||
this._mouseenter();
|
||||
@@ -504,6 +534,7 @@
|
||||
@@ -504,6 +536,7 @@
|
||||
if (!this.contains(event.relatedTarget)) {
|
||||
this._mouseleave();
|
||||
}
|
||||
@@ -129,7 +131,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
}
|
||||
|
||||
on_dragstart(event) {
|
||||
@@ -538,6 +569,8 @@
|
||||
@@ -538,6 +571,8 @@
|
||||
this.style.MozUserFocus = "ignore";
|
||||
} else if (
|
||||
event.target.classList.contains("tab-close-button") ||
|
||||
@@ -138,7 +140,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
event.target.classList.contains("tab-icon-overlay") ||
|
||||
event.target.classList.contains("tab-audio-button")
|
||||
) {
|
||||
@@ -592,16 +625,21 @@
|
||||
@@ -592,16 +627,21 @@
|
||||
this.style.MozUserFocus = "";
|
||||
}
|
||||
|
||||
@@ -161,7 +163,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
gBrowser.multiSelectedTabsCount > 0 &&
|
||||
!event.target.classList.contains("tab-close-button") &&
|
||||
!event.target.classList.contains("tab-icon-overlay") &&
|
||||
@@ -613,8 +651,9 @@
|
||||
@@ -613,8 +653,9 @@
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -173,7 +175,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
) {
|
||||
if (this.activeMediaBlocked) {
|
||||
if (this.multiselected) {
|
||||
@@ -632,7 +671,7 @@
|
||||
@@ -632,7 +673,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,7 +184,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
if (this.multiselected) {
|
||||
gBrowser.removeMultiSelectedTabs(
|
||||
lazy.TabMetrics.userTriggeredContext(
|
||||
@@ -652,6 +691,14 @@
|
||||
@@ -652,6 +693,14 @@
|
||||
// (see tabbrowser-tabs 'click' handler).
|
||||
gBrowser.tabContainer._blockDblClick = true;
|
||||
}
|
||||
@@ -197,7 +199,7 @@ index e4266a159a0d5c42cc294602d00b8f66131f35d5..88c321f05dabd948d06e155f6e047466
|
||||
}
|
||||
|
||||
on_dblclick(event) {
|
||||
@@ -675,6 +722,8 @@
|
||||
@@ -675,6 +724,8 @@
|
||||
animate: true,
|
||||
triggeringEvent: event,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
index d88bc0e5570c8fd428a84fdf5af0f6bab1e2a636..d9491b680bf8839038dadc0c6ee52f81a655e998 100644
|
||||
index d88bc0e5570c8fd428a84fdf5af0f6bab1e2a636..be4bedce98f404325e547dd8a4e73e895b6025b0 100644
|
||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
@@ -413,6 +413,7 @@
|
||||
@@ -186,6 +186,15 @@ index d88bc0e5570c8fd428a84fdf5af0f6bab1e2a636..d9491b680bf8839038dadc0c6ee52f81
|
||||
// If focus is on the old tab, move it to the new tab.
|
||||
if (activeEl == oldTab) {
|
||||
newTab.focus();
|
||||
@@ -1822,7 +1902,7 @@
|
||||
// Focus the location bar if it was previously focused for that tab.
|
||||
// In full screen mode, only bother making the location bar visible
|
||||
// if the tab is a blank one.
|
||||
- if (gURLBar.getBrowserState(newBrowser).urlbarFocused) {
|
||||
+ if (gURLBar.getBrowserState(newBrowser).urlbarFocused && !gZenVerticalTabsManager._hasSetSingleToolbar) {
|
||||
let selectURL = () => {
|
||||
if (this._asyncTabSwitching) {
|
||||
// Set _awaitingSetURI flag to suppress popup notification
|
||||
@@ -2110,7 +2190,12 @@
|
||||
return this._setTabLabel(aTab, aLabel);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js
|
||||
index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938d6923f3e 100644
|
||||
index 3ca119e8dc72fac652c98505211864483d98add2..b65307ee8df896488a4c51e3a25bf9ad9e1c8179 100644
|
||||
--- a/browser/components/tabbrowser/content/tabgroup.js
|
||||
+++ b/browser/components/tabbrowser/content/tabgroup.js
|
||||
@@ -14,11 +14,11 @@
|
||||
@@ -101,7 +101,13 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
|
||||
resetDefaultGroupName = () => {
|
||||
this.#defaultGroupName = "";
|
||||
@@ -178,7 +201,9 @@
|
||||
@@ -175,10 +198,15 @@
|
||||
if (!this.#tabChangeObserver) {
|
||||
this.#tabChangeObserver = new window.MutationObserver(mutations => {
|
||||
if (!this.tabs.length) {
|
||||
+ if (this.tagName === "zen-workspace-collapsible-pins") {
|
||||
+ return;
|
||||
+ }
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("TabGroupRemoved", { bubbles: true })
|
||||
);
|
||||
@@ -111,7 +117,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
Services.obs.notifyObservers(
|
||||
this,
|
||||
"browser-tabgroup-removed-from-dom"
|
||||
@@ -223,7 +248,10 @@
|
||||
@@ -223,7 +251,10 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -123,7 +129,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
}
|
||||
|
||||
get color() {
|
||||
@@ -317,6 +345,9 @@
|
||||
@@ -317,6 +348,9 @@
|
||||
}
|
||||
|
||||
set collapsed(val) {
|
||||
@@ -133,7 +139,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
if (!!val == this.collapsed) {
|
||||
return;
|
||||
}
|
||||
@@ -403,7 +434,6 @@
|
||||
@@ -403,7 +437,6 @@
|
||||
tabGroupName,
|
||||
})
|
||||
.then(result => {
|
||||
@@ -141,7 +147,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
});
|
||||
}
|
||||
|
||||
@@ -478,13 +508,65 @@
|
||||
@@ -478,13 +511,65 @@
|
||||
* @returns {MozTabbrowserTab[]}
|
||||
*/
|
||||
get tabs() {
|
||||
@@ -212,7 +218,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -592,7 +674,6 @@
|
||||
@@ -592,7 +677,6 @@
|
||||
);
|
||||
} else {
|
||||
if (tabOrSplitView.pinned) {
|
||||
@@ -220,7 +226,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
}
|
||||
let tabToMove =
|
||||
this.ownerGlobal === tabOrSplitView.ownerGlobal
|
||||
@@ -661,7 +742,7 @@
|
||||
@@ -661,7 +745,7 @@
|
||||
*/
|
||||
on_click(event) {
|
||||
let isToggleElement =
|
||||
@@ -229,7 +235,7 @@ index 3ca119e8dc72fac652c98505211864483d98add2..026b524be51170882e788a701095b938
|
||||
event.target === this.#overflowCountLabel;
|
||||
if (isToggleElement && event.button === 0) {
|
||||
event.preventDefault();
|
||||
@@ -740,5 +821,6 @@
|
||||
@@ -740,5 +824,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css
|
||||
index cbbf55f31ae5e456401172f79ddbbe41256025a4..8cab0f2809a43c0aa4249453732eb0e006c2c676 100644
|
||||
index cbbf55f31ae5e456401172f79ddbbe41256025a4..dc471dfe30dedf7c4917322a5b2257a9ec9c4f90 100644
|
||||
--- a/browser/themes/shared/urlbar-searchbar.css
|
||||
+++ b/browser/themes/shared/urlbar-searchbar.css
|
||||
@@ -10,7 +10,7 @@
|
||||
@@ -25,7 +25,7 @@ index cbbf55f31ae5e456401172f79ddbbe41256025a4..8cab0f2809a43c0aa4249453732eb0e0
|
||||
.urlbar[breakout][breakout-extend] {
|
||||
height: auto;
|
||||
+ align-items: center;
|
||||
+ :root:not([zen-single-toolbar='true']) {
|
||||
+ :root:not([zen-single-toolbar='true']) & {
|
||||
margin-left: calc(-1 * var(--urlbar-margin-inline));
|
||||
+ }
|
||||
width: calc(var(--urlbar-width) + 2 * var(--urlbar-margin-inline));
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
diff --git a/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs b/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs
|
||||
--- a/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs
|
||||
+++ b/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs
|
||||
@@ -490,10 +490,27 @@
|
||||
if (accepted) {
|
||||
return () => spinner.observe();
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
+
|
||||
+ /**
|
||||
+ * Reset the phase after a call to _trigger().
|
||||
+ * For testing purposes only.
|
||||
+ */
|
||||
+ get _reset() {
|
||||
+ let accepted = Services.prefs.getBoolPref(
|
||||
+ "toolkit.asyncshutdown.testing",
|
||||
+ false
|
||||
+ );
|
||||
+ if (accepted) {
|
||||
+ return () => {
|
||||
+ spinner = new Spinner(topic);
|
||||
+ };
|
||||
+ }
|
||||
+ return undefined;
|
||||
+ },
|
||||
});
|
||||
gPhases.set(topic, phase);
|
||||
return phase;
|
||||
}
|
||||
|
||||
diff --git a/toolkit/components/contentrelevancy/ContentRelevancyManager.sys.mjs b/toolkit/components/contentrelevancy/ContentRelevancyManager.sys.mjs
|
||||
--- a/toolkit/components/contentrelevancy/ContentRelevancyManager.sys.mjs
|
||||
+++ b/toolkit/components/contentrelevancy/ContentRelevancyManager.sys.mjs
|
||||
@@ -104,18 +104,14 @@
|
||||
this._nimbusUpdateCallback = this.#onNimbusUpdate.bind(this);
|
||||
// This will handle both Nimbus updates and pref changes.
|
||||
lazy.NimbusFeatures.contentRelevancy.onUpdate(this._nimbusUpdateCallback);
|
||||
this.#initialized = true;
|
||||
|
||||
- if (
|
||||
- Services.startup.isInOrBeyondShutdownPhase(
|
||||
- Ci.nsIAppStartup.SHUTDOWN_PHASE_APPSHUTDOWNCONFIRMED
|
||||
- )
|
||||
- ) {
|
||||
+ if (lazy.AsyncShutdown.profileChangeTeardown.isClosed) {
|
||||
// Corner case, where we're already in the shutdown phase while being constructed. In this
|
||||
// case, uninitialize immediately to deregister callback handlers
|
||||
- // (#https://bugzilla.mozilla.org/show_bug.cgi?id=1990569#c11)
|
||||
+ // (https://bugzilla.mozilla.org/show_bug.cgi?id=1990569#c11)
|
||||
this.uninit();
|
||||
} else {
|
||||
// If we're not in the above corner case, then register a shutdown blocker to uninitialize.
|
||||
// Interrupt sooner prior to the `profile-before-change` phase to allow
|
||||
// all the in-progress IOs to exit.
|
||||
diff --git a/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js b/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js
|
||||
--- a/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js
|
||||
+++ b/toolkit/components/contentrelevancy/tests/xpcshell/test_ContentRelevancyManager.js
|
||||
@@ -149,10 +149,39 @@
|
||||
await TestUtils.waitForCondition(
|
||||
() => ContentRelevancyManager.interrupt.calledOnce,
|
||||
"The interrupt shutdown blocker should be called"
|
||||
);
|
||||
|
||||
+ AsyncShutdown.profileChangeTeardown._reset();
|
||||
+ Services.prefs.clearUserPref("toolkit.asyncshutdown.testing");
|
||||
+ Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED);
|
||||
+ gSandbox.restore();
|
||||
+});
|
||||
+
|
||||
+add_task(async function test_dont_register_blocker_if_in_shutdown() {
|
||||
+ // Test a corner case: the ContentRelevancyManager is initialized during shutdown.
|
||||
+ //
|
||||
+ // In this case it shouldn't register a shutdown blocker, because it's too late to do that.
|
||||
+ // Instead, it should just immediately uninitialize itself.
|
||||
+ //
|
||||
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=1990569
|
||||
+ ContentRelevancyManager.uninit();
|
||||
+ Services.prefs.setBoolPref(PREF_CONTENT_RELEVANCY_ENABLED, true);
|
||||
+ await TestUtils.waitForTick();
|
||||
+
|
||||
+ gSandbox.spy(ContentRelevancyManager, "interrupt");
|
||||
+
|
||||
+ // Simulate shutdown.
|
||||
+ Services.prefs.setBoolPref("toolkit.asyncshutdown.testing", true);
|
||||
+ AsyncShutdown.profileChangeTeardown._trigger();
|
||||
+ ContentRelevancyManager.init();
|
||||
+ Assert.ok(
|
||||
+ !ContentRelevancyManager.initialized,
|
||||
+ "ContentRelevancyManager should have uninitialized itself"
|
||||
+ );
|
||||
+
|
||||
+ AsyncShutdown.profileChangeTeardown._reset();
|
||||
Services.prefs.clearUserPref("toolkit.asyncshutdown.testing");
|
||||
Services.prefs.clearUserPref(PREF_CONTENT_RELEVANCY_ENABLED);
|
||||
gSandbox.restore();
|
||||
});
|
||||
|
||||
diff --git a/toolkit/modules/AppServicesTracing.sys.mjs b/toolkit/modules/AppServicesTracing.sys.mjs
|
||||
--- a/toolkit/modules/AppServicesTracing.sys.mjs
|
||||
+++ b/toolkit/modules/AppServicesTracing.sys.mjs
|
||||
@@ -9,10 +9,11 @@
|
||||
*/
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
+ AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
|
||||
// eslint-disable-next-line mozilla/use-console-createInstance
|
||||
Log: "resource://gre/modules/Log.sys.mjs",
|
||||
});
|
||||
|
||||
import {
|
||||
@@ -118,20 +119,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** A singleton uniffi callback interface. */
|
||||
class TracingEventHandler extends EventSink {
|
||||
- static OBSERVER_NAME = "xpcom-will-shutdown";
|
||||
-
|
||||
constructor() {
|
||||
super();
|
||||
// Map targets to CallbackLists
|
||||
this.targetCallbackLists = new Map();
|
||||
// CallbackList for callbacks registered with registerMinLevelEventSink
|
||||
this.minLevelCallbackList = new CallbackList();
|
||||
|
||||
- Services.obs.addObserver(this, TracingEventHandler.OBSERVER_NAME);
|
||||
+ // Choose `profileBeforeChange` to call `#close()` and deregister our callbacks.
|
||||
+ //
|
||||
+ // Most other components will shutdown during the `profileChangeTeardown` phase, since that's
|
||||
+ // the last opportunity to write to the profile directory. By choosing the next one, we ensure
|
||||
+ // we can forward any logging that happens when those components shutdown.
|
||||
+ if (lazy.AsyncShutdown.profileBeforeChange.isClosed) {
|
||||
+ // Corner case, where we're already in the shutdown phase while being constructed. In this
|
||||
+ // case, uninitialize immediately.
|
||||
+ this.#close();
|
||||
+ } else {
|
||||
+ // If we're not in the above corner case, then register a shutdown blocker to uninitialize.
|
||||
+ lazy.AsyncShutdown.profileBeforeChange.addBlocker(
|
||||
+ "TracingEventHandler: deregister callbacks",
|
||||
+ () => this.#close()
|
||||
+ );
|
||||
+ }
|
||||
}
|
||||
|
||||
register(target, level, callback) {
|
||||
if (this.targetCallbackLists === null) {
|
||||
lazy.console.trace(
|
||||
@@ -223,19 +237,17 @@
|
||||
targetList.processEvent(event);
|
||||
}
|
||||
this.minLevelCallbackList.processEvent(event);
|
||||
}
|
||||
|
||||
- observe(_aSubject, aTopic, _aData) {
|
||||
- if (aTopic == TracingEventHandler.OBSERVER_NAME) {
|
||||
- for (let target of this.targetCallbackLists.keys()) {
|
||||
- unregisterEventSink(target);
|
||||
- }
|
||||
- unregisterMinLevelEventSink();
|
||||
- this.targetCallbackLists = null;
|
||||
- this.minLevelCallbackList = null;
|
||||
+ #close() {
|
||||
+ for (let target of this.targetCallbackLists.keys()) {
|
||||
+ unregisterEventSink(target);
|
||||
}
|
||||
+ unregisterMinLevelEventSink();
|
||||
+ this.targetCallbackLists = null;
|
||||
+ this.minLevelCallbackList = null;
|
||||
}
|
||||
}
|
||||
|
||||
// the singleton.
|
||||
let tracingEventHandler = new TracingEventHandler();
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
diff --git a/gfx/webrender_bindings/DCLayerTree.cpp b/gfx/webrender_bindings/DCLayerTree.cpp
|
||||
--- a/gfx/webrender_bindings/DCLayerTree.cpp
|
||||
+++ b/gfx/webrender_bindings/DCLayerTree.cpp
|
||||
@@ -2097,10 +2097,14 @@
|
||||
hr = mCompositionSurface->BeginDraw(&updateRect, __uuidof(ID3D11Texture2D),
|
||||
(void**)getter_AddRefs(backBuffer),
|
||||
&offset);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
+ LayoutDeviceIntRect rect = widget::WinUtils::ToIntRect(updateRect);
|
||||
+
|
||||
+ gfxCriticalNote << "DCLayerCompositionSurface::Bind failed: "
|
||||
+ << gfx::hexa(hr) << " " << rect;
|
||||
RenderThread::Get()->HandleWebRenderError(WebRenderError::BEGIN_DRAW);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto gl = mDCLayerTree->GetGLContext();
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
diff --git a/gfx/webrender_bindings/DCLayerTree.cpp b/gfx/webrender_bindings/DCLayerTree.cpp
|
||||
--- a/gfx/webrender_bindings/DCLayerTree.cpp
|
||||
+++ b/gfx/webrender_bindings/DCLayerTree.cpp
|
||||
@@ -2182,18 +2182,18 @@
|
||||
|
||||
updatePos = {0, 0};
|
||||
}
|
||||
|
||||
mFirstDraw = false;
|
||||
+ LayoutDeviceIntRect rect = widget::WinUtils::ToIntRect(updateRect);
|
||||
+ MOZ_ASSERT(!rect.IsEmpty());
|
||||
|
||||
hr = mCompositionSurface->BeginDraw(&updateRect, __uuidof(ID3D11Texture2D),
|
||||
(void**)getter_AddRefs(backBuffer),
|
||||
&offset);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
- LayoutDeviceIntRect rect = widget::WinUtils::ToIntRect(updateRect);
|
||||
-
|
||||
gfxCriticalNote << "DCLayerCompositionSurface::Bind failed: "
|
||||
<< gfx::hexa(hr) << " " << rect;
|
||||
RenderThread::Get()->HandleWebRenderError(WebRenderError::BEGIN_DRAW);
|
||||
return;
|
||||
}
|
||||
diff --git a/gfx/wr/webrender/src/renderer/composite.rs b/gfx/wr/webrender/src/renderer/composite.rs
|
||||
--- a/gfx/wr/webrender/src/renderer/composite.rs
|
||||
+++ b/gfx/wr/webrender/src/renderer/composite.rs
|
||||
@@ -1120,11 +1120,13 @@
|
||||
// Only use supplied clear color for first content layer we encounter
|
||||
let clear_color = content_clear_color.take().unwrap_or(ColorF::TRANSPARENT);
|
||||
|
||||
if let Some(ref mut _compositor) = self.compositor_config.layer_compositor() {
|
||||
if let Some(PartialPresentMode::Single { dirty_rect }) = partial_present_mode {
|
||||
- if dirty_rect.is_empty() {
|
||||
+ let device_rect = DeviceRect::from_size(device_size.to_f32());
|
||||
+ let clipped_dirty_rect = dirty_rect.intersection_unchecked(&device_rect);
|
||||
+ if clipped_dirty_rect.is_empty() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
diff --git a/gfx/wr/webrender/src/renderer/composite.rs b/gfx/wr/webrender/src/renderer/composite.rs
|
||||
--- a/gfx/wr/webrender/src/renderer/composite.rs
|
||||
+++ b/gfx/wr/webrender/src/renderer/composite.rs
|
||||
@@ -974,12 +974,15 @@
|
||||
.iter()
|
||||
.chain(self.layer_compositor_frame_state_in_prev_frame.as_ref().unwrap().rects_without_id.iter()) {
|
||||
combined_dirty_rect = combined_dirty_rect.union(&rect);
|
||||
}
|
||||
|
||||
+ let device_rect = DeviceRect::from_size(device_size.to_f32());
|
||||
+ let clipped_dirty_rect = combined_dirty_rect.intersection_unchecked(&device_rect);
|
||||
+
|
||||
partial_present_mode = Some(PartialPresentMode::Single {
|
||||
- dirty_rect: combined_dirty_rect,
|
||||
+ dirty_rect: clipped_dirty_rect,
|
||||
});
|
||||
} else {
|
||||
partial_present_mode = None;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
[
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D279007",
|
||||
"name": "Fix MacOS Crash on Shutdown Firefox 149"
|
||||
},
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D284084",
|
||||
@@ -40,5 +35,20 @@
|
||||
// the parameter's help description with the correct one.
|
||||
"application": "Application"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D291099",
|
||||
"name": "gh-12979 1 Add gfxCriticalNote to DCLayerCompositionSurface"
|
||||
},
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D291123",
|
||||
"name": "gh-12979 2 Compositor rendering performance fix"
|
||||
},
|
||||
{
|
||||
"type": "phabricator",
|
||||
"id": "D291714",
|
||||
"name": "gh-12979 3 Clip dirty_rect to device_size"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/toolkit/content/widgets/arrowscrollbox.js b/toolkit/content/widgets/arrowscrollbox.js
|
||||
index b80d1049bb6ae305f2ac9c4c35fe975fd508031c..be2cbdb20cb2064459b6f7bef56fd0470c3b7f40 100644
|
||||
index b80d1049bb6ae305f2ac9c4c35fe975fd508031c..574149bffa49329e927c8db9db0c080eb6b87f5f 100644
|
||||
--- a/toolkit/content/widgets/arrowscrollbox.js
|
||||
+++ b/toolkit/content/widgets/arrowscrollbox.js
|
||||
@@ -98,6 +98,7 @@
|
||||
@@ -10,7 +10,19 @@ index b80d1049bb6ae305f2ac9c4c35fe975fd508031c..be2cbdb20cb2064459b6f7bef56fd047
|
||||
let contentSize =
|
||||
slot.getBoundingClientRect()[this.#verticalMode ? "height" : "width"];
|
||||
// NOTE(emilio): This should be contentSize > scrollClientSize, but due
|
||||
@@ -642,7 +643,7 @@
|
||||
@@ -125,6 +126,11 @@
|
||||
overflowObserver.observe(this.scrollbox);
|
||||
}
|
||||
|
||||
+ connectedMoveCallback() {
|
||||
+ // See gh-13015, define connectedMoveCallback to prevent connectedCallback
|
||||
+ // from being called when using moveBefore.
|
||||
+ }
|
||||
+
|
||||
connectedCallback() {
|
||||
this.removeAttribute("overflowing");
|
||||
|
||||
@@ -642,7 +648,7 @@
|
||||
|
||||
on_wheel(event) {
|
||||
// Don't consume the event if we can't scroll.
|
||||
|
||||
@@ -46,14 +46,13 @@ class ZenStartup {
|
||||
}
|
||||
newContainer.appendChild(node);
|
||||
}
|
||||
|
||||
// Fix notification deck
|
||||
const deckTemplate = document.getElementById(
|
||||
"tab-notification-deck-template"
|
||||
);
|
||||
if (deckTemplate) {
|
||||
document.getElementById("zen-appcontent-wrapper").prepend(deckTemplate);
|
||||
}
|
||||
const deckTemplate =
|
||||
document.getElementById("tab-notification-deck-template") ||
|
||||
document.getElementById("tab-notification-deck");
|
||||
|
||||
// overlap and interaction issues with vertical tabs
|
||||
document.getElementById("browser").prepend(deckTemplate);
|
||||
|
||||
gZenWorkspaces.init();
|
||||
setTimeout(() => {
|
||||
@@ -159,8 +158,13 @@ class ZenStartup {
|
||||
}
|
||||
|
||||
#checkForWelcomePage() {
|
||||
if (!Services.prefs.getBoolPref("zen.welcome-screen.seen", false)) {
|
||||
Services.prefs.setBoolPref("zen.welcome-screen.seen", true);
|
||||
const kWelcomeScreenSeenPref = "zen.welcome-screen.seen";
|
||||
if (Services.env.get("MOZ_HEADLESS")) {
|
||||
Services.prefs.setBoolPref(kWelcomeScreenSeenPref, true);
|
||||
return;
|
||||
}
|
||||
if (!Services.prefs.getBoolPref(kWelcomeScreenSeenPref, false)) {
|
||||
Services.prefs.setBoolPref(kWelcomeScreenSeenPref, true);
|
||||
Services.prefs.setStringPref(
|
||||
"zen.updates.last-build-id",
|
||||
Services.appinfo.appBuildID
|
||||
|
||||
@@ -999,7 +999,7 @@ window.gZenVerticalTabsManager = {
|
||||
command="cmd_zenToggleTabsOnRight"
|
||||
/>
|
||||
`);
|
||||
document.getElementById("viewToolbarsMenuSeparator").before(fragment);
|
||||
document.getElementById("toolbar-context-customize").before(fragment);
|
||||
},
|
||||
|
||||
get _topButtonsSeparatorElement() {
|
||||
@@ -1014,6 +1014,7 @@ window.gZenVerticalTabsManager = {
|
||||
|
||||
animateItemOpen(aItem) {
|
||||
if (
|
||||
gReduceMotion ||
|
||||
!gZenUIManager.motion ||
|
||||
!aItem ||
|
||||
!gZenUIManager._hasLoadedDOM ||
|
||||
|
||||
@@ -13,35 +13,36 @@ export default function checkForZenUpdates() {
|
||||
const lastVersion = Services.prefs.getStringPref(ZEN_UPDATE_PREF, "");
|
||||
Services.prefs.setStringPref(ZEN_UPDATE_PREF, version);
|
||||
if (
|
||||
version !== lastVersion &&
|
||||
!gZenUIManager.testingEnabled &&
|
||||
Services.prefs.getBoolPref(ZEN_UPDATE_SHOW, true)
|
||||
version === lastVersion ||
|
||||
gZenUIManager.testingEnabled ||
|
||||
!Services.prefs.getBoolPref(ZEN_UPDATE_SHOW, true)
|
||||
) {
|
||||
const updateUrl = Services.prefs.getStringPref(
|
||||
"app.releaseNotesURL.prompt",
|
||||
""
|
||||
);
|
||||
createSidebarNotification({
|
||||
headingL10nId: "zen-sidebar-notification-updated-heading",
|
||||
links: [
|
||||
{
|
||||
url: Services.urlFormatter.formatURL(
|
||||
updateUrl.replace("%VERSION%", version)
|
||||
),
|
||||
l10nId: "zen-sidebar-notification-updated",
|
||||
special: true,
|
||||
icon: "chrome://browser/skin/zen-icons/heart-circle-fill.svg",
|
||||
},
|
||||
{
|
||||
action: () => {
|
||||
Services.obs.notifyObservers(window, "restart-in-safe-mode");
|
||||
},
|
||||
l10nId: "zen-sidebar-notification-restart-safe-mode",
|
||||
icon: "chrome://browser/skin/zen-icons/security-broken.svg",
|
||||
},
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
const updateUrl = Services.prefs.getStringPref(
|
||||
"app.releaseNotesURL.prompt",
|
||||
""
|
||||
);
|
||||
createSidebarNotification({
|
||||
headingL10nId: "zen-sidebar-notification-updated-heading",
|
||||
links: [
|
||||
{
|
||||
url: Services.urlFormatter.formatURL(
|
||||
updateUrl.replace("%VERSION%", version)
|
||||
),
|
||||
l10nId: "zen-sidebar-notification-updated",
|
||||
special: true,
|
||||
icon: "chrome://browser/skin/zen-icons/heart-circle-fill.svg",
|
||||
},
|
||||
{
|
||||
action: () => {
|
||||
Services.obs.notifyObservers(window, "restart-in-safe-mode");
|
||||
},
|
||||
l10nId: "zen-sidebar-notification-restart-safe-mode",
|
||||
icon: "chrome://browser/skin/zen-icons/security-broken.svg",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export async function createWindowUpdateAnimation() {
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
% file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
color-scheme: dark;
|
||||
--toolbar-color-scheme: dark;
|
||||
--zen-urlbar-outline-offset: -2px;
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
% file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
color-scheme: light;
|
||||
--toolbar-color-scheme: light;
|
||||
--zen-urlbar-outline-offset: 0px;
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
background-color: var(--zen-urlbar-background-transparent, var(--zen-urlbar-background-base)) !important;
|
||||
box-shadow: 0 30px 140px -15px light-dark(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.6)) !important;
|
||||
backdrop-filter: none !important;
|
||||
outline: 0.5px solid light-dark(rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.2)) !important;
|
||||
outline: 0.5px solid light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.2)) !important;
|
||||
outline-offset: var(--zen-urlbar-outline-offset) !important;
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@@ -404,32 +404,6 @@
|
||||
min-width: 26px;
|
||||
}
|
||||
|
||||
/* Notification Stack */
|
||||
|
||||
.notificationbox-stack {
|
||||
background: transparent;
|
||||
|
||||
&[notificationside="top"] {
|
||||
position: fixed;
|
||||
bottom: calc(var(--zen-element-separation) * 1.5);
|
||||
right: calc(var(--zen-element-separation) * 1.5);
|
||||
width: fit-content;
|
||||
max-width: 30rem !important;
|
||||
z-index: 9999;
|
||||
|
||||
& notification-message {
|
||||
background: color-mix(in srgb, var(--zen-colors-tertiary) 70%, transparent 30%);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid var(--arrowpanel-border-color);
|
||||
border-radius: var(--zen-border-radius);
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#nav-bar,
|
||||
#zen-sidebar-top-buttons {
|
||||
min-height: var(--zen-toolbar-height) !important;
|
||||
@@ -512,6 +486,11 @@
|
||||
margin-block: -1px !important;
|
||||
}
|
||||
}
|
||||
|
||||
& #identity-icon-box {
|
||||
--urlbar-box-hover-bgcolor: transparent;
|
||||
margin-inline: 2px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@@ -708,7 +687,8 @@
|
||||
}
|
||||
|
||||
#identity-box {
|
||||
margin-inline-end: 0;
|
||||
margin-inline-end: 3px !important;
|
||||
margin-inline-start: 2px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -650,3 +650,36 @@
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Notification Stack */
|
||||
|
||||
.notificationbox-stack {
|
||||
background: transparent;
|
||||
|
||||
&[notificationside="top"] {
|
||||
position: fixed;
|
||||
bottom: calc(var(--zen-element-separation) * 1.5);
|
||||
right: calc(var(--zen-element-separation) * 1.5);
|
||||
|
||||
:root[zen-right-side="true"] & {
|
||||
right: auto;
|
||||
left: calc(var(--zen-element-separation) * 1.5);
|
||||
}
|
||||
|
||||
width: fit-content;
|
||||
max-width: 30rem !important;
|
||||
z-index: 9999;
|
||||
|
||||
& notification-message {
|
||||
background: color-mix(in srgb, var(--zen-colors-tertiary) 70%, transparent 30%);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid var(--arrowpanel-border-color);
|
||||
border-radius: var(--zen-border-radius);
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ window.gZenCompactModeManager = {
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("viewToolbarsMenuSeparator").before(fragment);
|
||||
document.getElementById("toolbar-context-customize").before(fragment);
|
||||
this.updateContextMenu();
|
||||
},
|
||||
|
||||
@@ -590,7 +590,7 @@ window.gZenCompactModeManager = {
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
toggle.setAttribute("checked", this.preference);
|
||||
toggle.toggleAttribute("checked", this.preference);
|
||||
|
||||
const hideTabBar = this.canHideSidebar;
|
||||
const hideToolbar = this.canHideToolbar;
|
||||
@@ -600,9 +600,9 @@ window.gZenCompactModeManager = {
|
||||
const sidebarItem = document.getElementById(idName + "sidebar");
|
||||
const toolbarItem = document.getElementById(idName + "toolbar");
|
||||
const bothItem = document.getElementById(idName + "both");
|
||||
sidebarItem.setAttribute("checked", !hideBoth && hideTabBar);
|
||||
toolbarItem.setAttribute("checked", !hideBoth && hideToolbar);
|
||||
bothItem.setAttribute("checked", hideBoth);
|
||||
sidebarItem.toggleAttribute("checked", !hideBoth && hideTabBar);
|
||||
toolbarItem.toggleAttribute("checked", !hideBoth && hideToolbar);
|
||||
bothItem.toggleAttribute("checked", hideBoth);
|
||||
},
|
||||
|
||||
_removeOpenStateOnUnifiedExtensions() {
|
||||
|
||||
@@ -70,7 +70,24 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
);
|
||||
document.getElementById("context_moveTabToGroup").before(contextMenuItems);
|
||||
const contextMenuItemsToolbar = window.MozXULElement.parseXULToFragment(
|
||||
`<menuitem id="zen-context-menu-new-folder-toolbar" data-l10n-id="zen-toolbar-context-new-folder"/>`
|
||||
`<menuitem id="zen-context-menu-new-folder-toolbar" data-l10n-id="zen-toolbar-context-new-folder"/>
|
||||
<menuseparator />
|
||||
<menu data-l10n-id="zen-panel-ui-live-folder-create" id="zen-panel-ui-live-folder-create">
|
||||
<menupopup>
|
||||
<menuitem
|
||||
data-l10n-id="zen-live-folder-github-pull-requests"
|
||||
command="cmd_zenNewLiveFolder"
|
||||
image="chrome://browser/skin/zen-icons/selectable/logo-github.svg" />
|
||||
<menuitem
|
||||
data-l10n-id="zen-live-folder-github-issues"
|
||||
command="cmd_zenNewLiveFolder"
|
||||
image="chrome://browser/skin/zen-icons/selectable/logo-github.svg" />
|
||||
<menuitem
|
||||
data-l10n-id="zen-live-folder-type-rss"
|
||||
command="cmd_zenNewLiveFolder"
|
||||
image="chrome://browser/skin/zen-icons/selectable/logo-rss.svg"/>
|
||||
</menupopup>
|
||||
</menu>`
|
||||
);
|
||||
document
|
||||
.getElementById("toolbar-context-openANewTab")
|
||||
|
||||
@@ -507,17 +507,6 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.#glances.get(this.#currentGlanceID).elementImageData =
|
||||
data.elementData;
|
||||
|
||||
gZenUIManager.motion.animate(
|
||||
imageDataElement,
|
||||
{
|
||||
opacity: [1, 0],
|
||||
},
|
||||
{
|
||||
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
||||
easing: "easeInOut",
|
||||
}
|
||||
);
|
||||
|
||||
return imageDataElement;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
z-index: 0;
|
||||
@@ -179,6 +180,10 @@
|
||||
translate: -50% -50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& image {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
|
||||
@@ -10,8 +10,11 @@ export class nsGithubLiveFolderProvider extends nsZenLiveFolderProvider {
|
||||
constructor({ id, state, manager }) {
|
||||
super({ id, state, manager });
|
||||
|
||||
this.state.url = "https://github.com/issues/assigned";
|
||||
this.state.type = state.type;
|
||||
this.state.url =
|
||||
this.state.type === "pull-requests"
|
||||
? "https://github.com/pulls"
|
||||
: "https://github.com/issues/assigned";
|
||||
|
||||
this.state.options = state.options ?? {};
|
||||
this.state.repos = new Set(state.repos ?? []);
|
||||
@@ -29,22 +32,106 @@ export class nsGithubLiveFolderProvider extends nsZenLiveFolderProvider {
|
||||
return "zen-live-folder-github-no-filter";
|
||||
}
|
||||
|
||||
const searchParams = this.#buildSearchOptions();
|
||||
const url = `${this.state.url}?${searchParams}`;
|
||||
const queries = this.#buildSearchOptions();
|
||||
const requests = await Promise.all(
|
||||
queries.map(query => {
|
||||
const url = new URL(this.state.url);
|
||||
url.searchParams.set("q", query);
|
||||
|
||||
const { text, status } = await this.fetch(url);
|
||||
if (this.state.type === "pull-requests") {
|
||||
return this.parsePullRequests(url.href);
|
||||
}
|
||||
|
||||
// Assume no auth
|
||||
if (status === 404) {
|
||||
return "zen-live-folder-github-no-auth";
|
||||
return this.parseIssues(url.href);
|
||||
})
|
||||
);
|
||||
|
||||
const combinedItems = new Map();
|
||||
const combinedActiveRepos = new Set();
|
||||
|
||||
for (const { status, items, activeRepos } of requests) {
|
||||
// Assume no auth
|
||||
if (status === 404) {
|
||||
return "zen-live-folder-github-no-auth";
|
||||
}
|
||||
|
||||
if (items) {
|
||||
items.forEach(item => combinedItems.set(item.id, item));
|
||||
}
|
||||
|
||||
if (activeRepos) {
|
||||
activeRepos.forEach(repo => combinedActiveRepos.add(repo));
|
||||
}
|
||||
}
|
||||
|
||||
this.state.repos = combinedActiveRepos;
|
||||
return Array.from(combinedItems.values());
|
||||
} catch (error) {
|
||||
console.error("Error fetching or parsing GitHub issues:", error);
|
||||
return "zen-live-folder-failed-fetch";
|
||||
}
|
||||
}
|
||||
|
||||
async parsePullRequests(url) {
|
||||
const { text, status } = await this.fetch(url);
|
||||
|
||||
try {
|
||||
const document = new DOMParser().parseFromString(text, "text/html");
|
||||
const issues = document.querySelectorAll("div[id^=issue_]");
|
||||
const items = [];
|
||||
const activeRepos = [];
|
||||
|
||||
if (issues.length) {
|
||||
const authors = document.querySelectorAll(".opened-by a");
|
||||
const titles = document.querySelectorAll("a[id^=issue_]");
|
||||
|
||||
for (let i = 0; i < issues.length; i++) {
|
||||
const author = authors[i].textContent;
|
||||
const title = titles[i].textContent;
|
||||
|
||||
const repo = titles[i].previousElementSibling.textContent.trim();
|
||||
if (repo) {
|
||||
activeRepos.push(repo);
|
||||
}
|
||||
|
||||
const idMatch = authors[i].parentElement.textContent
|
||||
.match(/#[0-9]+/)
|
||||
.shift();
|
||||
|
||||
items.push({
|
||||
title,
|
||||
subtitle: author,
|
||||
icon: "chrome://browser/content/zen-images/favicons/github.svg",
|
||||
url: new URL(titles[i].href, this.state.url),
|
||||
id: `${repo}${idMatch}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status,
|
||||
|
||||
items,
|
||||
activeRepos,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("Failed to parse Github pull requests", err);
|
||||
return {
|
||||
status,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async parseIssues(url) {
|
||||
const { text, status } = await this.fetch(url);
|
||||
|
||||
try {
|
||||
const document = new DOMParser().parseFromString(text, "text/html");
|
||||
const issues = document.querySelectorAll(
|
||||
"div[class^=IssueItem-module__defaultRepoContainer]"
|
||||
);
|
||||
const items = [];
|
||||
const activeRepos = new Set();
|
||||
const activeRepos = [];
|
||||
|
||||
if (issues.length) {
|
||||
const authors = document.querySelectorAll(
|
||||
@@ -65,7 +152,7 @@ export class nsGithubLiveFolderProvider extends nsZenLiveFolderProvider {
|
||||
|
||||
const repo = rawRepo.textContent?.trim();
|
||||
if (repo) {
|
||||
activeRepos.add(repo);
|
||||
activeRepos.push(repo);
|
||||
}
|
||||
|
||||
const numberMatch = rawNumber?.textContent?.match(/[0-9]+/);
|
||||
@@ -81,76 +168,67 @@ export class nsGithubLiveFolderProvider extends nsZenLiveFolderProvider {
|
||||
}
|
||||
}
|
||||
|
||||
this.state.repos = activeRepos;
|
||||
return {
|
||||
status,
|
||||
|
||||
return items;
|
||||
} catch (error) {
|
||||
console.error("Error fetching or parsing GitHub issues:", error);
|
||||
return "zen-live-folder-failed-fetch";
|
||||
items,
|
||||
activeRepos,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("Failed to parse Github Issues", err);
|
||||
return {
|
||||
status,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#buildSearchOptions() {
|
||||
let searchParams = new URLSearchParams();
|
||||
const baseQuery = [
|
||||
this.state.type === "pull-requests" ? "is:pr" : "is:issue",
|
||||
"state:open",
|
||||
"sort:updated-desc",
|
||||
];
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: "state:open",
|
||||
enabled: true,
|
||||
value: "author:@me",
|
||||
enabled: this.state.options.authorMe ?? false,
|
||||
},
|
||||
{
|
||||
value: "sort:updated-desc",
|
||||
enabled: true,
|
||||
value: "assignee:@me",
|
||||
enabled: this.state.options.assignedMe ?? true,
|
||||
},
|
||||
{
|
||||
value: "review-requested:@me",
|
||||
enabled: this.state.options.reviewRequested ?? false,
|
||||
},
|
||||
[
|
||||
{
|
||||
value: "is:pr",
|
||||
enabled: this.state.type === "pull-requests",
|
||||
},
|
||||
{
|
||||
value: "is:issue",
|
||||
enabled: this.state.type === "issues",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
value: "author:@me",
|
||||
enabled: this.state.options.authorMe ?? false,
|
||||
},
|
||||
{
|
||||
value: "assignee:@me",
|
||||
enabled: this.state.options.assignedMe ?? true,
|
||||
},
|
||||
{
|
||||
value: "review-requested:@me",
|
||||
enabled: this.state.options.reviewRequested ?? false,
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
const excluded = this.state.options.repoExcludes;
|
||||
for (const repo of excluded) {
|
||||
if (repo && repo.trim()) {
|
||||
options.push({ value: `-repo:${repo.trim()}`, enabled: true });
|
||||
baseQuery.push(`-repo:${repo.trim()}`);
|
||||
}
|
||||
}
|
||||
|
||||
let outputString = "";
|
||||
const queries = [];
|
||||
for (const option of options) {
|
||||
if (Array.isArray(option)) {
|
||||
const enabledOptions = option.filter(x => x.enabled).map(x => x.value);
|
||||
if (enabledOptions.length) {
|
||||
outputString += ` (${enabledOptions.join(" OR ")}) `;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (option.enabled) {
|
||||
outputString += ` ${option.value} `;
|
||||
queries.push(option.value);
|
||||
}
|
||||
}
|
||||
|
||||
searchParams.set("q", outputString.trim().replace(/ +(?= )/g, ""));
|
||||
return searchParams.toString();
|
||||
const searchParams = [];
|
||||
if (this.state.type === "pull-requests") {
|
||||
for (const query of queries) {
|
||||
searchParams.push(`${baseQuery.join(" ")} ${query}`);
|
||||
}
|
||||
|
||||
return searchParams;
|
||||
}
|
||||
|
||||
// type: issues
|
||||
return [`${baseQuery.join(" ")} ${queries.join(" OR ")}`];
|
||||
}
|
||||
|
||||
get options() {
|
||||
@@ -209,7 +287,7 @@ export class nsGithubLiveFolderProvider extends nsZenLiveFolderProvider {
|
||||
super.onOptionTrigger(option);
|
||||
|
||||
const key = option.getAttribute("option-key");
|
||||
const checked = option.getAttribute("checked") === "true";
|
||||
const checked = option.hasAttribute("checked");
|
||||
if (!this.options.some(x => x.key === key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,10 +151,11 @@ export class nsZenSessionManager {
|
||||
);
|
||||
const db = await PlacesUtils.promiseDBConnection();
|
||||
let data = {};
|
||||
let rows = await db.execute(
|
||||
"SELECT * FROM zen_workspaces ORDER BY created_at ASC"
|
||||
);
|
||||
let rows = [];
|
||||
try {
|
||||
rows = await db.execute(
|
||||
"SELECT * FROM zen_workspaces ORDER BY created_at ASC"
|
||||
);
|
||||
data.spaces = rows.map(row => ({
|
||||
uuid: row.getResultByName("uuid"),
|
||||
name: row.getResultByName("name"),
|
||||
|
||||
@@ -790,7 +790,10 @@ class nsZenWindowSync {
|
||||
// We *shouldn't* care about this scenario since the remoteness should be
|
||||
// the same anyways.
|
||||
if (!aOurTab.linkedBrowser || !aOtherTab.linkedBrowser) {
|
||||
return true;
|
||||
this.log(
|
||||
`Cannot swap browsers between tabs ${aOurTab.id} and ${aOtherTab.id} because one of them doesn't have a linked browser`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Can't swap between chrome and content processes.
|
||||
if (
|
||||
|
||||
@@ -1753,6 +1753,10 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
|
||||
"--toolbox-textcolor",
|
||||
`rgba(${textColor[0]}, ${textColor[1]}, ${textColor[2]}, ${textColor[3]})`
|
||||
);
|
||||
docElement.style.setProperty(
|
||||
"--toolbar-color-scheme",
|
||||
isDarkMode ? "dark" : "light"
|
||||
);
|
||||
}
|
||||
|
||||
if (!skipUpdate) {
|
||||
|
||||
@@ -10,9 +10,6 @@ window.ZenWorkspaceBookmarksStorage = {
|
||||
ChromeUtils.defineESModuleGetters(this.lazy, {
|
||||
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
|
||||
});
|
||||
if (!window.gZenWorkspaces) {
|
||||
return;
|
||||
}
|
||||
this.promiseInitialized = new Promise(resolve => {
|
||||
this._resolveInitialized = resolve;
|
||||
});
|
||||
|
||||
@@ -199,25 +199,27 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
this.style.visibility = "visible";
|
||||
gZenCompactModeManager.getAndApplySidebarWidth();
|
||||
this.resolveInitialized();
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.elementsToAnimate,
|
||||
{
|
||||
y: [20, 0],
|
||||
opacity: [0, 1],
|
||||
filter: ["blur(2px)", "blur(0)"],
|
||||
},
|
||||
{
|
||||
duration: 0.6,
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: gZenUIManager.motion.stagger(0.05, { startDelay: 0.2 }),
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.inputName.focus();
|
||||
gZenWorkspaces.workspaceElement(this.workspaceId).hidden = false;
|
||||
});
|
||||
let animation = gZenUIManager.motion.animate(
|
||||
this.elementsToAnimate,
|
||||
{
|
||||
y: [20, 0],
|
||||
opacity: [0, 1],
|
||||
filter: ["blur(2px)", "blur(0)"],
|
||||
},
|
||||
{
|
||||
duration: 0.6,
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: gZenUIManager.motion.stagger(0.05, { startDelay: 0.2 }),
|
||||
}
|
||||
);
|
||||
if (gReduceMotion) {
|
||||
animation.complete();
|
||||
}
|
||||
animation.then(() => {
|
||||
this.inputName.focus();
|
||||
gZenWorkspaces.workspaceElement(this.workspaceId).hidden = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -303,20 +305,22 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
}
|
||||
|
||||
async #cleanup() {
|
||||
await gZenUIManager.motion.animate(
|
||||
this.elementsToAnimate.reverse(),
|
||||
{
|
||||
y: [0, 20],
|
||||
opacity: [1, 0],
|
||||
filter: ["blur(0)", "blur(2px)"],
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: gZenUIManager.motion.stagger(0.05),
|
||||
}
|
||||
);
|
||||
if (!gReduceMotion) {
|
||||
await gZenUIManager.motion.animate(
|
||||
this.elementsToAnimate.reverse(),
|
||||
{
|
||||
y: [0, 20],
|
||||
opacity: [1, 0],
|
||||
filter: ["blur(0)", "blur(2px)"],
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: gZenUIManager.motion.stagger(0.05),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
document.getElementById("zen-sidebar-splitter").style.pointerEvents = "";
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ class nsZenWorkspaces {
|
||||
_workspaceCache = [];
|
||||
|
||||
#lastScrollTime = 0;
|
||||
#currentSpaceSwitchContext = {
|
||||
promise: null,
|
||||
animations: [],
|
||||
};
|
||||
|
||||
bookmarkMenus = [
|
||||
"PlacesToolbar",
|
||||
@@ -777,7 +781,7 @@ class nsZenWorkspaces {
|
||||
if (
|
||||
!this.privateWindowOrDisabled &&
|
||||
spacesFromStore.length === 0 &&
|
||||
lazy.ZenSessionStore._migrationData
|
||||
lazy.ZenSessionStore._migrationData?.spaces
|
||||
) {
|
||||
spacesFromStore.push(...lazy.ZenSessionStore._migrationData.spaces);
|
||||
}
|
||||
@@ -1631,9 +1635,18 @@ class nsZenWorkspaces {
|
||||
}
|
||||
|
||||
async changeWorkspace(workspace, ...args) {
|
||||
if (!this.workspaceEnabled || this.#inChangingWorkspace) {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
this.#currentSpaceSwitchContext.animations.forEach(animation => {
|
||||
animation.complete();
|
||||
});
|
||||
await this.#currentSpaceSwitchContext.promise;
|
||||
let { resolve, promise } = Promise.withResolvers();
|
||||
this.#currentSpaceSwitchContext = {
|
||||
promise,
|
||||
animations: [],
|
||||
};
|
||||
this.#inChangingWorkspace = true;
|
||||
try {
|
||||
this.log("Changing workspace to", workspace?.uuid);
|
||||
@@ -1642,10 +1655,11 @@ class nsZenWorkspaces {
|
||||
console.error("gZenWorkspaces: Error changing workspace", e);
|
||||
}
|
||||
this.#inChangingWorkspace = false;
|
||||
resolve();
|
||||
}
|
||||
|
||||
_cancelSwipeAnimation() {
|
||||
this._animateTabs(this.getActiveWorkspaceFromCache(), true);
|
||||
this.#animateTabs(this.getActiveWorkspaceFromCache(), true);
|
||||
}
|
||||
|
||||
async #performWorkspaceChange(
|
||||
@@ -1923,7 +1937,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
|
||||
/* eslint-disable complexity */
|
||||
async _animateTabs(
|
||||
async #animateTabs(
|
||||
newWorkspace,
|
||||
shouldAnimate,
|
||||
tabToSelect = null,
|
||||
@@ -2253,12 +2267,14 @@ class nsZenWorkspaces {
|
||||
let promiseTimeout = new Promise(resolve =>
|
||||
setTimeout(resolve, kGlobalAnimationDuration * 1000 + 50)
|
||||
);
|
||||
this.#currentSpaceSwitchContext.animations = animations;
|
||||
// See issue https://github.com/zen-browser/desktop/issues/9334, we need to add
|
||||
// some sort of timeout to the animation promise, just in case it gets stuck.
|
||||
// We are doing a race between the timeout and the animations finishing.
|
||||
await Promise.race([Promise.all(animations), promiseTimeout]).catch(
|
||||
console.error
|
||||
);
|
||||
this.#currentSpaceSwitchContext.animations = [];
|
||||
document.documentElement.removeAttribute("animating-background");
|
||||
if (shouldAnimate) {
|
||||
for (const cloned of clonedEssentials) {
|
||||
@@ -2420,7 +2436,7 @@ class nsZenWorkspaces {
|
||||
|
||||
gZenUIManager.tabsWrapper.scrollbarWidth = "none";
|
||||
this.workspaceIcons.activeIndex = workspace.uuid;
|
||||
await this._animateTabs(
|
||||
await this.#animateTabs(
|
||||
workspace,
|
||||
!onInit && !this._animatingChange,
|
||||
tabToSelect,
|
||||
|
||||
@@ -1164,12 +1164,16 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
insetUpdateContextMenuItems() {
|
||||
const contentAreaContextMenu = document.getElementById("tabContextMenu");
|
||||
contentAreaContextMenu.addEventListener("popupshowing", () => {
|
||||
let isExistingSplitView = gBrowser.selectedTabs.some(tab =>
|
||||
let contextTab = TabContextMenu.contextTab;
|
||||
let selectedTabs = contextTab.multiselected
|
||||
? gBrowser.selectedTabs
|
||||
: [contextTab];
|
||||
let isExistingSplitView = selectedTabs.every(tab =>
|
||||
tab.group?.hasAttribute("split-view-group")
|
||||
);
|
||||
const splitTabCommand = document.getElementById("context_zenSplitTabs");
|
||||
document.l10n.setAttributes(splitTabCommand, "tab-zen-split-tabs", {
|
||||
tabCount: isExistingSplitView ? -1 : gBrowser.selectedTabs.length,
|
||||
tabCount: isExistingSplitView ? -1 : selectedTabs.length,
|
||||
});
|
||||
if (isExistingSplitView) {
|
||||
splitTabCommand.removeAttribute("hidden");
|
||||
@@ -1237,9 +1241,14 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
* Splits the selected tabs.
|
||||
*/
|
||||
contextSplitTabs() {
|
||||
const tabs = window.gBrowser.selectedTabs;
|
||||
// If any is already in a split view, we unsplit them first
|
||||
if (tabs.some(tab => tab.splitView)) {
|
||||
let tabs;
|
||||
if (TabContextMenu.contextTab.multiselected) {
|
||||
tabs = gBrowser.selectedTabs;
|
||||
} else {
|
||||
tabs = [TabContextMenu.contextTab];
|
||||
}
|
||||
// If all are already in a split view, we unsplit them first.
|
||||
if (tabs.every(tab => tab.splitView)) {
|
||||
for (const tab of tabs) {
|
||||
if (tab.splitView) {
|
||||
this.removeTabFromGroup(tab);
|
||||
@@ -1263,7 +1272,7 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature {
|
||||
return false;
|
||||
}
|
||||
for (const tab of window.gBrowser.selectedTabs) {
|
||||
if (tab.splitView || tab.hasAttribute("zen-empty-tab")) {
|
||||
if (tab.hasAttribute("zen-empty-tab")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,6 +427,11 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
state.image = tab.zenStaticIcon || initialState.image;
|
||||
state.index = 0;
|
||||
|
||||
// See gh-13024, we need to remove the scroll position from the state,
|
||||
// otherwise when we reset the pinned tab, it will scroll to the previous position
|
||||
// which can be confusing for the user, especially if they have a long page.
|
||||
delete state.scroll;
|
||||
|
||||
SessionStore.setTabState(tab, state);
|
||||
this.resetPinChangedUrl(tab);
|
||||
}
|
||||
@@ -673,14 +678,15 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
return tab;
|
||||
}
|
||||
let workspaceId;
|
||||
if (
|
||||
!tab.hasAttribute("zen-essential") &&
|
||||
tab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace
|
||||
) {
|
||||
workspaceId = gZenWorkspaces.activeWorkspace;
|
||||
}
|
||||
if (tab.ownerGlobal !== window) {
|
||||
fromDifferentWindow = true;
|
||||
if (
|
||||
!tab.hasAttribute("zen-essential") &&
|
||||
tab.getAttribute("zen-workspace-id") !=
|
||||
gZenWorkspaces.activeWorkspace
|
||||
) {
|
||||
workspaceId = gZenWorkspaces.activeWorkspace;
|
||||
if (workspaceId) {
|
||||
tab.ownerGlobal.gBrowser.selectedTab =
|
||||
tab.ownerGlobal.gBrowser._findTabToBlurTo(tab, movingTabs);
|
||||
tab.ownerGlobal.gZenWorkspaces.moveTabToWorkspace(tab, workspaceId);
|
||||
@@ -695,9 +701,9 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
|
||||
if (tab) {
|
||||
++newIndex;
|
||||
}
|
||||
if (workspaceId) {
|
||||
tab.setAttribute("zen-workspace-id", workspaceId);
|
||||
}
|
||||
}
|
||||
if (workspaceId) {
|
||||
tab.setAttribute("zen-workspace-id", workspaceId);
|
||||
}
|
||||
return tab;
|
||||
});
|
||||
|
||||
@@ -310,11 +310,13 @@
|
||||
}
|
||||
|
||||
& .tabbrowser-tab {
|
||||
&,
|
||||
& .tab-content > image {
|
||||
transition:
|
||||
scale 0.2s ease,
|
||||
var(--zen-tabbox-element-indent-transition);
|
||||
@media not (prefers-reduced-motion: reduce) {
|
||||
&,
|
||||
& .tab-content > image {
|
||||
transition:
|
||||
scale 0.2s ease,
|
||||
var(--zen-tabbox-element-indent-transition);
|
||||
}
|
||||
}
|
||||
|
||||
:root[zen-sidebar-expanded="true"] &:not([zen-glance-tab]) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"brandShortName": "Zen",
|
||||
"brandFullName": "Zen Browser",
|
||||
"release": {
|
||||
"displayVersion": "1.19.4b",
|
||||
"displayVersion": "1.19.6b",
|
||||
"github": {
|
||||
"repo": "zen-browser/desktop"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user