Refactor CSS and JavaScript files for consistency; clean up whitespace and formatting

This commit is contained in:
mr. M 2025-01-04 02:21:45 +01:00
parent 22515592f0
commit 7dfa6d55ba
No known key found for this signature in database
GPG key ID: CBD57A2AEDBDA1FB
56 changed files with 1607 additions and 1515 deletions

View file

@ -10,7 +10,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:

View file

@ -28,4 +28,3 @@ jobs:
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'

View file

@ -26,6 +26,6 @@ jobs:
- name: Commit - name: Commit
uses: stefanzweifel/git-auto-commit-action@v5 uses: stefanzweifel/git-auto-commit-action@v5
with: with:
commit_message: "[skip ci] 📦 Update submodules" commit_message: '[skip ci] 📦 Update submodules'
commit_user_name: Zen Browser Robot commit_user_name: Zen Browser Robot
commit_user_email: zen-browser-auto@users.noreply.github.com commit_user_email: zen-browser-auto@users.noreply.github.com

View file

@ -3,6 +3,7 @@ engine/
**/*.html **/*.html
**/*.xhtml **/*.xhtml
**/*.inc.xhtml **/*.inc.xhtml
**/*.bundle.min.js
**/*.svg **/*.svg
@ -11,5 +12,9 @@ pnpm-lock.yaml
**/engine/ **/engine/
docs/issue-metrics/*.md
# Some CSS files are preprocessed and prettier doesn't handle them well # Some CSS files are preprocessed and prettier doesn't handle them well
# We also dont want to format the CSS files that are generated by the build
src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css
src/browser/base/zen-components/ZenEmojies.mjs

View file

@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our Examples of behavior that contributes to a positive environment for our
community include: community include:
* Demonstrating empathy and kindness toward other people - Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences - Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback - Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, - Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience and learning from the experience
* Focusing on what is best not just for us as individuals, but for the - Focusing on what is best not just for us as individuals, but for the
overall community overall community
Examples of unacceptable behavior include: Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or - The use of sexualized language or imagery, and sexual attention or
advances of any kind advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks - Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment - Public or private harassment
* Publishing others' private information, such as a physical or email - Publishing others' private information, such as a physical or email
address, without their explicit permission address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a - Other conduct which could reasonably be considered inappropriate in a
professional setting professional setting
## Enforcement Responsibilities ## Enforcement Responsibilities

View file

@ -6,7 +6,6 @@
[![Crowdin](https://badges.crowdin.net/zen-browser/localized.svg)](https://crowdin.com/project/zen-browser) [![Crowdin](https://badges.crowdin.net/zen-browser/localized.svg)](https://crowdin.com/project/zen-browser)
[![Zen Release builds](https://github.com/zen-browser/desktop/actions/workflows/build.yml/badge.svg?branch=stable)](https://github.com/zen-browser/desktop/actions/workflows/build.yml) [![Zen Release builds](https://github.com/zen-browser/desktop/actions/workflows/build.yml/badge.svg?branch=stable)](https://github.com/zen-browser/desktop/actions/workflows/build.yml)
✨ Experience tranquillity while browsing the web without people tracking you! Zen is a privacy-focused browser that blocks trackers, ads, and other unwanted content while offering the best browsing experience! ✨ Experience tranquillity while browsing the web without people tracking you! Zen is a privacy-focused browser that blocks trackers, ads, and other unwanted content while offering the best browsing experience!
<div flex="true"> <div flex="true">
@ -99,7 +98,7 @@ yay -S zen-browser-bin
##### Other Linux distributions (AppImage with automated system integration) ##### Other Linux distributions (AppImage with automated system integration)
- `native` tarball install: - `native` tarball install:
```bash <(curl -s https://updates.zen-browser.app/install.sh)``` `bash <(curl -s https://updates.zen-browser.app/install.sh)`
- `zsync` is required for the Update feature of the script below - `zsync` is required for the Update feature of the script below
@ -107,7 +106,7 @@ yay -S zen-browser-bin
bash <(curl https://updates.zen-browser.app/appimage.sh) bash <(curl https://updates.zen-browser.app/appimage.sh)
``` ```
* Again, if you don't see your OS listed above, that's because we already have it in our [downloads page](https://zen-browser.app/download)! 🔄 - Again, if you don't see your OS listed above, that's because we already have it in our [downloads page](https://zen-browser.app/download)! 🔄
To upgrade the browser to a newer version, use the embedded update functionality in `About Zen`. To upgrade the browser to a newer version, use the embedded update functionality in `About Zen`.

View file

@ -1,4 +1,3 @@
# Branch Structure # Branch Structure
The repository is structured as follows: The repository is structured as follows:

View file

@ -28,13 +28,14 @@
// Fix notification deck // Fix notification deck
const deckTemplate = document.getElementById('tab-notification-deck-template'); const deckTemplate = document.getElementById('tab-notification-deck-template');
if (deckTemplate) { if (deckTemplate) {
document document.getElementById('zen-appcontent-navbar-container').appendChild(deckTemplate);
.getElementById('zen-appcontent-navbar-container')
.appendChild(deckTemplate);
} }
// Disable smooth scroll // Disable smooth scroll
gBrowser.tabContainer.arrowScrollbox.smoothScroll = Services.prefs.getBoolPref('zen.startup.smooth-scroll-in-tabs', false); gBrowser.tabContainer.arrowScrollbox.smoothScroll = Services.prefs.getBoolPref(
'zen.startup.smooth-scroll-in-tabs',
false
);
ZenWorkspaces.init(); ZenWorkspaces.init();
gZenUIManager.init(); gZenUIManager.init();

View file

@ -6,20 +6,18 @@ var gZenUIManager = {
document.addEventListener('popupshowing', this.onPopupShowing.bind(this)); document.addEventListener('popupshowing', this.onPopupShowing.bind(this));
document.addEventListener('popuphidden', this.onPopupHidden.bind(this)); document.addEventListener('popuphidden', this.onPopupHidden.bind(this));
XPCOMUtils.defineLazyPreferenceGetter(this, 'sidebarHeightThrottle', 'zen.view.sidebar-height-throttle', 500); XPCOMUtils.defineLazyPreferenceGetter(this, 'sidebarHeightThrottle', 'zen.view.sidebar-height-throttle', 500);
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(this, 'contentElementSeparation', 'zen.theme.content-element-separation', 0);
this,
'contentElementSeparation',
'zen.theme.content-element-separation',
0
);
new ResizeObserver(gZenCommonActions.throttle(this.updateTabsToolbar.bind(this), this.sidebarHeightThrottle)).observe( new ResizeObserver(gZenCommonActions.throttle(this.updateTabsToolbar.bind(this), this.sidebarHeightThrottle)).observe(
document.getElementById('tabbrowser-tabs') document.getElementById('tabbrowser-tabs')
); );
new ResizeObserver(gZenCommonActions.throttle(gZenCompactModeManager.getAndApplySidebarWidth.bind(gZenCompactModeManager), this.sidebarHeightThrottle)).observe( new ResizeObserver(
document.getElementById('navigator-toolbox') gZenCommonActions.throttle(
); gZenCompactModeManager.getAndApplySidebarWidth.bind(gZenCompactModeManager),
this.sidebarHeightThrottle
)
).observe(document.getElementById('navigator-toolbox'));
}, },
updateTabsToolbar() { updateTabsToolbar() {
@ -30,7 +28,7 @@ var gZenUIManager = {
const toolbarRect = toolbarItems.getBoundingClientRect(); const toolbarRect = toolbarItems.getBoundingClientRect();
let height = toolbarRect.height; let height = toolbarRect.height;
// -5 for the controls padding // -5 for the controls padding
let totalHeight = toolbarRect.height - (this.contentElementSeparation * 2) - 5; let totalHeight = toolbarRect.height - this.contentElementSeparation * 2 - 5;
// remove the height from other elements that aren't hidden // remove the height from other elements that aren't hidden
const otherElements = document.querySelectorAll('#tabbrowser-tabs > *:not([hidden="true"])'); const otherElements = document.querySelectorAll('#tabbrowser-tabs > *:not([hidden="true"])');
for (let tab of otherElements) { for (let tab of otherElements) {
@ -83,7 +81,10 @@ var gZenUIManager = {
for (const el of this._popupTrackingElements) { for (const el of this._popupTrackingElements) {
// target may be inside a shadow root, not directly under the element // target may be inside a shadow root, not directly under the element
// we also ignore menus inside panels // we also ignore menus inside panels
if (!el.contains(showEvent.explicitOriginalTarget) || (showEvent.explicitOriginalTarget instanceof Element && showEvent.explicitOriginalTarget?.closest('panel'))) { if (
!el.contains(showEvent.explicitOriginalTarget) ||
(showEvent.explicitOriginalTarget instanceof Element && showEvent.explicitOriginalTarget?.closest('panel'))
) {
continue; continue;
} }
document.removeEventListener('mousemove', this.__removeHasPopupAttribute); document.removeEventListener('mousemove', this.__removeHasPopupAttribute);
@ -115,8 +116,11 @@ var gZenVerticalTabsManager = {
this._multiWindowFeature = new ZenMultiWindowFeature(); this._multiWindowFeature = new ZenMultiWindowFeature();
ChromeUtils.defineLazyGetter(this, 'isWindowsStyledButtons', () => { ChromeUtils.defineLazyGetter(this, 'isWindowsStyledButtons', () => {
return !(window.AppConstants.platform === 'macosx' || window.matchMedia('(-moz-gtk-csd-reversed-placement)').matches return !(
|| Services.prefs.getBoolPref('zen.view.experimental-force-window-controls-left')); window.AppConstants.platform === 'macosx' ||
window.matchMedia('(-moz-gtk-csd-reversed-placement)').matches ||
Services.prefs.getBoolPref('zen.view.experimental-force-window-controls-left')
);
}); });
ChromeUtils.defineLazyGetter(this, 'hidesTabsToolbar', () => { ChromeUtils.defineLazyGetter(this, 'hidesTabsToolbar', () => {
@ -144,7 +148,7 @@ var gZenVerticalTabsManager = {
XPCOMUtils.defineLazyPreferenceGetter(this, 'canOpenTabOnMiddleClick', 'zen.tabs.newtab-on-middle-click', true); XPCOMUtils.defineLazyPreferenceGetter(this, 'canOpenTabOnMiddleClick', 'zen.tabs.newtab-on-middle-click', true);
if (!this.isWindowsStyledButtons) { if (!this.isWindowsStyledButtons) {
document.documentElement.setAttribute("zen-window-buttons-reversed", true); document.documentElement.setAttribute('zen-window-buttons-reversed', true);
} }
if (tabs) { if (tabs) {
@ -199,9 +203,9 @@ var gZenVerticalTabsManager = {
get actualWindowButtons() { get actualWindowButtons() {
// we have multiple ".titlebar-buttonbox-container" in the DOM, because of the titlebar // we have multiple ".titlebar-buttonbox-container" in the DOM, because of the titlebar
if (!this.__actualWindowButtons) { if (!this.__actualWindowButtons) {
this.__actualWindowButtons = (!this.isWindowsStyledButtons) ? this.__actualWindowButtons = !this.isWindowsStyledButtons
document.querySelector('.titlebar-buttonbox-container') : // TODO: test if it works 100% of the time ? document.querySelector('.titlebar-buttonbox-container') // TODO: test if it works 100% of the time
document.querySelector('#nav-bar .titlebar-buttonbox-container'); : document.querySelector('#nav-bar .titlebar-buttonbox-container');
} }
return this.__actualWindowButtons; return this.__actualWindowButtons;
}, },
@ -225,44 +229,20 @@ var gZenVerticalTabsManager = {
initializePreferences(updateEvent) { initializePreferences(updateEvent) {
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
this, this,
"_prefsCompactMode", '_prefsCompactMode',
"zen.view.compact", 'zen.view.compact',
false false
// no need to update the event, it's handled by the compact mode manager // no need to update the event, it's handled by the compact mode manager
); );
XPCOMUtils.defineLazyPreferenceGetter(this, '_prefsVerticalTabs', 'zen.tabs.vertical', true, updateEvent);
XPCOMUtils.defineLazyPreferenceGetter(this, '_prefsRightSide', 'zen.tabs.vertical.right-side', false, updateEvent);
XPCOMUtils.defineLazyPreferenceGetter(this, '_prefsUseSingleToolbar', 'zen.view.use-single-toolbar', false, updateEvent);
XPCOMUtils.defineLazyPreferenceGetter(this, '_prefsSidebarExpanded', 'zen.view.sidebar-expanded', false, updateEvent);
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
this, this,
"_prefsVerticalTabs", '_prefsSidebarExpandedMaxWidth',
"zen.tabs.vertical", 'zen.view.sidebar-expanded.max-width',
true,
updateEvent
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_prefsRightSide",
"zen.tabs.vertical.right-side",
false,
updateEvent
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_prefsUseSingleToolbar",
"zen.view.use-single-toolbar",
false,
updateEvent
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_prefsSidebarExpanded",
"zen.view.sidebar-expanded",
false,
updateEvent
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"_prefsSidebarExpandedMaxWidth",
"zen.view.sidebar-expanded.max-width",
300, 300,
updateEvent updateEvent
); );
@ -276,17 +256,17 @@ var gZenVerticalTabsManager = {
try { try {
this._updateMaxWidth(); this._updateMaxWidth();
window.docShell.treeOwner window.docShell.treeOwner.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIAppWindow).rollupAllPopups();
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow)
.rollupAllPopups();
const topButtons = document.getElementById('zen-sidebar-top-buttons'); const topButtons = document.getElementById('zen-sidebar-top-buttons');
const isCompactMode = this._prefsCompactMode && !forCustomizableMode; const isCompactMode = this._prefsCompactMode && !forCustomizableMode;
const isVerticalTabs = this._prefsVerticalTabs || forCustomizableMode; const isVerticalTabs = this._prefsVerticalTabs || forCustomizableMode;
const isSidebarExpanded = this._prefsSidebarExpanded || !isVerticalTabs; const isSidebarExpanded = this._prefsSidebarExpanded || !isVerticalTabs;
const isRightSide = this._prefsRightSide && isVerticalTabs; const isRightSide = this._prefsRightSide && isVerticalTabs;
const isSingleToolbar = ((this._prefsUseSingleToolbar && (isVerticalTabs && isSidebarExpanded) )|| !isVerticalTabs) && !forCustomizableMode && !this.hidesTabsToolbar; const isSingleToolbar =
((this._prefsUseSingleToolbar && isVerticalTabs && isSidebarExpanded) || !isVerticalTabs) &&
!forCustomizableMode &&
!this.hidesTabsToolbar;
const titlebar = document.getElementById('titlebar'); const titlebar = document.getElementById('titlebar');
gBrowser.tabContainer.setAttribute('orient', isVerticalTabs ? 'vertical' : 'horizontal'); gBrowser.tabContainer.setAttribute('orient', isVerticalTabs ? 'vertical' : 'horizontal');
@ -311,10 +291,12 @@ var gZenVerticalTabsManager = {
const appContentNavbarContaienr = document.getElementById('zen-appcontent-navbar-container'); const appContentNavbarContaienr = document.getElementById('zen-appcontent-navbar-container');
let shouldHide = false; let shouldHide = false;
if (((!isRightSide && this.isWindowsStyledButtons) || (isRightSide && !this.isWindowsStyledButtons) if (
|| ( ((!isRightSide && this.isWindowsStyledButtons) ||
isCompactMode && isSingleToolbar && this.isWindowsStyledButtons (isRightSide && !this.isWindowsStyledButtons) ||
)) && isSingleToolbar) { (isCompactMode && isSingleToolbar && this.isWindowsStyledButtons)) &&
isSingleToolbar
) {
appContentNavbarContaienr.setAttribute('should-hide', 'true'); appContentNavbarContaienr.setAttribute('should-hide', 'true');
shouldHide = true; shouldHide = true;
} else { } else {
@ -322,10 +304,7 @@ var gZenVerticalTabsManager = {
} }
// Check if the sidebar is in hover mode // Check if the sidebar is in hover mode
if ( if (!this.navigatorToolbox.hasAttribute('zen-right-side') && !isCompactMode) {
!this.navigatorToolbox.hasAttribute('zen-right-side') &&
!isCompactMode
) {
this.navigatorToolbox.prepend(topButtons); this.navigatorToolbox.prepend(topButtons);
} }
@ -335,7 +314,9 @@ var gZenVerticalTabsManager = {
if (isSingleToolbar) { if (isSingleToolbar) {
this._navbarParent = navBar.parentElement; this._navbarParent = navBar.parentElement;
let elements = document.querySelectorAll('#nav-bar-customization-target > :is([cui-areatype="toolbar"], .chromeclass-toolbar-additional):not(#urlbar-container)'); let elements = document.querySelectorAll(
'#nav-bar-customization-target > :is([cui-areatype="toolbar"], .chromeclass-toolbar-additional):not(#urlbar-container)'
);
elements = Array.from(elements).reverse(); elements = Array.from(elements).reverse();
// Add separator if it doesn't exist // Add separator if it doesn't exist
if (!buttonsTarget.contains(this._topButtonsSeparatorElement)) { if (!buttonsTarget.contains(this._topButtonsSeparatorElement)) {
@ -356,18 +337,20 @@ var gZenVerticalTabsManager = {
titlebar.before(topButtons); titlebar.before(topButtons);
titlebar.before(navBar); titlebar.before(navBar);
} }
document.documentElement.setAttribute("zen-single-toolbar", true); document.documentElement.setAttribute('zen-single-toolbar', true);
this._hasSetSingleToolbar = true; this._hasSetSingleToolbar = true;
} else if (this._hasSetSingleToolbar) { } else if (this._hasSetSingleToolbar) {
this._hasSetSingleToolbar = false; this._hasSetSingleToolbar = false;
// Do the opposite // Do the opposite
this._navbarParent.prepend(navBar); this._navbarParent.prepend(navBar);
const elements = document.querySelectorAll('#zen-sidebar-top-buttons-customization-target > :is([cui-areatype="toolbar"], .chromeclass-toolbar-additional)'); const elements = document.querySelectorAll(
'#zen-sidebar-top-buttons-customization-target > :is([cui-areatype="toolbar"], .chromeclass-toolbar-additional)'
);
for (const button of elements) { for (const button of elements) {
document.getElementById('nav-bar-customization-target').append(button); document.getElementById('nav-bar-customization-target').append(button);
} }
this._topButtonsSeparatorElement.remove(); this._topButtonsSeparatorElement.remove();
document.documentElement.removeAttribute("zen-single-toolbar"); document.documentElement.removeAttribute('zen-single-toolbar');
navBar.appendChild(document.getElementById('PanelUI-button')); navBar.appendChild(document.getElementById('PanelUI-button'));
this._toolbarOriginalParent.prepend(navBar); this._toolbarOriginalParent.prepend(navBar);
if (!dontRebuildAreas) { if (!dontRebuildAreas) {
@ -398,7 +381,7 @@ var gZenVerticalTabsManager = {
if (isRightSide && !isSidebarExpanded) { if (isRightSide && !isSidebarExpanded) {
navBar.appendChild(windowButtons); navBar.appendChild(windowButtons);
} else { } else {
document.getElementById("zen-sidebar-top-buttons-customization-target").appendChild(windowButtons); document.getElementById('zen-sidebar-top-buttons-customization-target').appendChild(windowButtons);
} }
} else if (!isSingleToolbar && !isCompactMode) { } else if (!isSingleToolbar && !isCompactMode) {
if (this.isWindowsStyledButtons) { if (this.isWindowsStyledButtons) {
@ -407,7 +390,8 @@ var gZenVerticalTabsManager = {
} else { } else {
navBar.append(windowButtons); navBar.append(windowButtons);
} }
} else { // not windows styled buttons } else {
// not windows styled buttons
if (isRightSide || !isSidebarExpanded) { if (isRightSide || !isSidebarExpanded) {
navBar.prepend(windowButtons); navBar.prepend(windowButtons);
} else { } else {

View file

@ -24,6 +24,6 @@
font-feature-settings: 'swsh' 1; font-feature-settings: 'swsh' 1;
& .zen-branding-title-italic { & .zen-branding-title-italic {
font-family: "Zen-Junicode-Italic", serif; font-family: 'Zen-Junicode-Italic', serif;
} }
} }

View file

@ -10,7 +10,9 @@
position: relative; position: relative;
/* For glance */ /* For glance */
transition: transform 0.1s ease-in-out, opacity 0.1s ease-in-out; transition:
transform 0.1s ease-in-out,
opacity 0.1s ease-in-out;
box-shadow: 0 0 1px 1px light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.5)); box-shadow: 0 0 1px 1px light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.5));
overflow: hidden; overflow: hidden;
@ -20,7 +22,7 @@
margin-left: var(--zen-element-separation); margin-left: var(--zen-element-separation);
} }
:root[zen-no-padding='true'] &:not([zen-split="true"]) { :root[zen-no-padding='true'] &:not([zen-split='true']) {
border-radius: 0 !important; border-radius: 0 !important;
} }
} }

View file

@ -51,7 +51,7 @@
&[animating='true']::after { &[animating='true']::after {
background: var(--zen-main-browser-background-old); background: var(--zen-main-browser-background-old);
backdrop-filter: blur(5px); backdrop-filter: blur(5px);
animation: zen-main-app-wrapper-animation .6s ease forwards; animation: zen-main-app-wrapper-animation 0.6s ease forwards;
transition: 0s; transition: 0s;
} }
} }
@ -99,7 +99,6 @@
border: none; border: none;
} }
@supports (-moz-osx-font-smoothing: auto) { @supports (-moz-osx-font-smoothing: auto) {
#zen-main-app-wrapper, #zen-main-app-wrapper,
#zen-appcontent-wrapper, #zen-appcontent-wrapper,

View file

@ -48,7 +48,10 @@
&:not([animate='true']) { &:not([animate='true']) {
position: absolute; position: absolute;
z-index: 10; z-index: 10;
transition: left 0.25s ease, right 0.25s ease, opacity 1.5s ease; transition:
left 0.25s ease,
right 0.25s ease,
opacity 1.5s ease;
top: 0; top: 0;
bottom: var(--zen-element-separation); bottom: var(--zen-element-separation);
opacity: 0; opacity: 0;
@ -124,9 +127,13 @@
#navigator-toolbox[has-popup-menu], #navigator-toolbox[has-popup-menu],
#navigator-toolbox[movingtab], #navigator-toolbox[movingtab],
#navigator-toolbox:has(.tabbrowser-tab:active), #navigator-toolbox:has(.tabbrowser-tab:active),
#navigator-toolbox:has(*:is([panelopen='true'], [open='true'], #nav-bar:focus-within):not(tab):not(.zen-compact-mode-ignore)) { #navigator-toolbox:has(
*:is([panelopen='true'], [open='true'], #nav-bar:focus-within):not(tab):not(.zen-compact-mode-ignore)
) {
&:not([animate='true']) { &:not([animate='true']) {
transition: left 0.25s ease, right 0.25s ease; transition:
left 0.25s ease,
right 0.25s ease;
opacity: 1; opacity: 1;
left: -1px; left: -1px;

View file

@ -17,7 +17,7 @@
} }
#zen-splitview-dropzone { #zen-splitview-dropzone {
border-radius: var(--zen-webview-border-radius, var(--zen-border-radius)); border-radius: var(--zen-webview-border-radius, var(--zen-border-radius));
transition: inset ease-out .08s; transition: inset ease-out 0.08s;
display: none; display: none;
background-color: color-mix(in srgb, var(--zen-colors-secondary) 30%, transparent 70%); background-color: color-mix(in srgb, var(--zen-colors-secondary) 30%, transparent 70%);
} }
@ -25,7 +25,8 @@
display: initial; display: initial;
} }
#tabbrowser-tabpanels[zen-split-view='true'] > [zen-split='true'], #zen-splitview-dropzone { #tabbrowser-tabpanels[zen-split-view='true'] > [zen-split='true'],
#zen-splitview-dropzone {
flex: 1; flex: 1;
margin: calc(var(--zen-split-column-gap) / 2) calc(var(--zen-split-row-gap) / 2 + 1px) !important; margin: calc(var(--zen-split-column-gap) / 2) calc(var(--zen-split-row-gap) / 2 + 1px) !important;
margin-bottom: 0 !important; margin-bottom: 0 !important;
@ -60,7 +61,8 @@
} }
} }
#tabbrowser-tabpanels:has(> [zen-split='true']), #zen-splitview-overlay { #tabbrowser-tabpanels:has(> [zen-split='true']),
#zen-splitview-overlay {
margin-right: calc(var(--zen-element-separation) - var(--zen-split-row-gap) / 2); margin-right: calc(var(--zen-element-separation) - var(--zen-split-row-gap) / 2);
margin-bottom: calc(var(--zen-element-separation) - var(--zen-split-column-gap) / 2); margin-bottom: calc(var(--zen-element-separation) - var(--zen-split-column-gap) / 2);
@ -112,7 +114,6 @@
pointer-events: all; pointer-events: all;
} }
.zen-split-view-splitter[orient='vertical'] { .zen-split-view-splitter[orient='vertical'] {
width: var(--zen-split-row-gap); width: var(--zen-split-row-gap);
margin-left: calc(var(--zen-split-row-gap) / -2); margin-left: calc(var(--zen-split-row-gap) / -2);
@ -181,7 +182,7 @@
border-radius: 3px; border-radius: 3px;
width: 100%; width: 100%;
height: 100%; height: 100%;
transition: .1s; transition: 0.1s;
} }
&:hover box { &:hover box {

View file

@ -32,7 +32,7 @@
& .browserContainer { & .browserContainer {
opacity: 1; opacity: 1;
animation: zen-glance-content-animation-out .3s ease-in-out forwards !important; animation: zen-glance-content-animation-out 0.3s ease-in-out forwards !important;
& browser { & browser {
opacity: 1 !important; opacity: 1 !important;
@ -40,7 +40,7 @@
& #zen-glance-sidebar-container { & #zen-glance-sidebar-container {
opacity: 0; opacity: 0;
transition: opacity .1s ease-in-out; transition: opacity 0.1s ease-in-out;
} }
} }
} }
@ -118,7 +118,7 @@
} }
&[animate='true'] { &[animate='true'] {
animation: zen-glance-content-animation .4s ease-in-out forwards; animation: zen-glance-content-animation 0.4s ease-in-out forwards;
&:not([animate-end='true']) { &:not([animate-end='true']) {
pointer-events: none; pointer-events: none;

View file

@ -51,7 +51,7 @@
bottom: 2px; bottom: 2px;
right: 0; right: 0;
border: 2px solid var(--zen-colors-border); border: 2px solid var(--zen-colors-border);
transition: transform .2s; transition: transform 0.2s;
} }
&[dragging='true']::after { &[dragging='true']::after {
@ -152,7 +152,7 @@
padding: 2px 4px !important; padding: 2px 4px !important;
margin: 0 !important; margin: 0 !important;
margin-left: auto !important; margin-left: auto !important;
transition: opacity .1s; transition: opacity 0.1s;
opacity: 0; opacity: 0;
} }
@ -246,8 +246,8 @@
box-shadow: 0 0 0 2px var(--zen-themed-toolbar-bg); box-shadow: 0 0 0 2px var(--zen-themed-toolbar-bg);
cursor: pointer; cursor: pointer;
border: 2px solid #fff; border: 2px solid #fff;
animation: zen-theme-picker-dot-animation .5s; animation: zen-theme-picker-dot-animation 0.5s;
transition: transform .2s; transition: transform 0.2s;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
&[dragging='true'] { &[dragging='true'] {

View file

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
panel[type='arrow'][animate][animate='open']::part(content) { panel[type='arrow'][animate][animate='open']::part(content) {
animation: zen-jello-animation .35s ease; animation: zen-jello-animation 0.35s ease;
} }
panel[type='arrow'][animate]:not([animate='open'])::part(content) { panel[type='arrow'][animate]:not([animate='open'])::part(content) {

View file

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
.printSettingsBrowser { .printSettingsBrowser {
min-width: 350px; min-width: 350px;
} }

View file

@ -341,6 +341,6 @@ menuitem {
cursor: pointer; cursor: pointer;
} }
#editBMPanel_workspaceList input[type="checkbox"] { #editBMPanel_workspaceList input[type='checkbox'] {
margin-right: 8px; margin-right: 8px;
} }

View file

@ -1,4 +1,3 @@
#zen-rice-share-dialog-overlay:not([hidden]) { #zen-rice-share-dialog-overlay:not([hidden]) {
position: absolute; position: absolute;
top: 0; top: 0;
@ -17,15 +16,15 @@
color: var(--panel-color); color: var(--panel-color);
background: var(--arrowpanel-background); background: var(--arrowpanel-background);
border-radius: var(--zen-panel-radius); border-radius: var(--zen-panel-radius);
box-shadow: 0 0 1px 1px hsla(0,0%,0%,.2);; box-shadow: 0 0 1px 1px hsla(0, 0%, 0%, 0.2);
border: var(--zen-appcontent-border); border: var(--zen-appcontent-border);
overflow: hidden; overflow: hidden;
animation: zen-jello-animation-large 0.4s ease; animation: zen-jello-animation-large 0.4s ease;
max-width: 400px; max-width: 400px;
&[animate="true"] { &[animate='true'] {
animation: zen-rice-submit-animation 1s cubic-bezier(.77,0,.18,1); animation: zen-rice-submit-animation 1s cubic-bezier(0.77, 0, 0.18, 1);
} }
& .zen-rice-share-content { & .zen-rice-share-content {
@ -47,7 +46,7 @@
padding: 0 10px; padding: 0 10px;
} }
& #zen-rice-share-first-form input[type="text"] { & #zen-rice-share-first-form input[type='text'] {
width: 100%; width: 100%;
padding: 1px 2px; padding: 1px 2px;
border: 0; border: 0;
@ -78,8 +77,10 @@
max-height: 30px; max-height: 30px;
overflow: hidden; overflow: hidden;
transition: max-height 0.3s ease, height 0.3s ease; transition:
&[zen-collapsed="false"] { max-height 0.3s ease,
height 0.3s ease;
&[zen-collapsed='false'] {
max-height: 350px; max-height: 350px;
} }
@ -106,7 +107,7 @@
height: 15px; height: 15px;
} }
&[zen-collapsed="false"] > .options-header image { &[zen-collapsed='false'] > .options-header image {
transform: rotate(90deg); transform: rotate(90deg);
} }
@ -162,7 +163,7 @@
overflow: hidden; overflow: hidden;
&::before { &::before {
content: ""; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;

View file

@ -101,7 +101,7 @@
} }
.zen-sidebar-web-panel-splitter, .zen-sidebar-web-panel-splitter,
.zen-split-view-splitter[orient="vertical"] { .zen-split-view-splitter[orient='vertical'] {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@ -131,7 +131,7 @@
} }
} }
.zen-split-view-splitter[orient="vertical"]::before { .zen-split-view-splitter[orient='vertical']::before {
transform: translate(-75%, -50%); transform: translate(-75%, -50%);
} }
@ -256,7 +256,7 @@
} }
#zen-sidebar-web-panel-title { #zen-sidebar-web-panel-title {
font-size: .9em; font-size: 0.9em;
font-weight: 600; font-weight: 600;
margin: 0 10px; margin: 0 10px;
padding: 0; padding: 0;
@ -316,4 +316,3 @@
#zen-sidebar-web-panel[hidden] { #zen-sidebar-web-panel[hidden] {
animation: better-sidebar-hide 0.15s ease-in-out forwards !important; animation: better-sidebar-hide 0.15s ease-in-out forwards !important;
} }

View file

@ -66,7 +66,6 @@
display: none !important; display: none !important;
} }
body > #confetti { body > #confetti {
z-index: 1; z-index: 1;
} }

View file

@ -18,7 +18,6 @@
padding: var(--zen-toolbox-padding) !important; padding: var(--zen-toolbox-padding) !important;
} }
#tabbrowser-tabs { #tabbrowser-tabs {
display: -webkit-box !important; display: -webkit-box !important;
-webkit-box-orient: horizontal; -webkit-box-orient: horizontal;
@ -79,8 +78,7 @@
width: 0% !important; width: 0% !important;
} }
.tabbrowser-tab[zen-glance-tab="true"] { .tabbrowser-tab[zen-glance-tab='true'] {
.tab-label-container { .tab-label-container {
display: none !important; display: none !important;
width: 0px !important; width: 0px !important;
@ -105,7 +103,7 @@
flex-direction: row !important; flex-direction: row !important;
} }
#tabbrowser-tabs[orient="vertical"] { #tabbrowser-tabs[orient='vertical'] {
flex-direction: row !important; flex-direction: row !important;
} }
@ -205,7 +203,7 @@
#vertical-pinned-tabs-container::after { #vertical-pinned-tabs-container::after {
z-index: -1; z-index: -1;
content: ""; content: '';
position: absolute; position: absolute;
right: 0; right: 0;
width: 1px; width: 1px;
@ -311,16 +309,16 @@
height: 3px !important; height: 3px !important;
} }
.tabbrowser-tab[zen-glance-tab="true"] { .tabbrowser-tab[zen-glance-tab='true'] {
flex-basis: fit-content !important; flex-basis: fit-content !important;
max-width: 36px !important; max-width: 36px !important;
} }
#zen-essentials-container .tabbrowser-tab[zen-glance-tab="true"] { #zen-essentials-container .tabbrowser-tab[zen-glance-tab='true'] {
left: 2px; left: 2px;
} }
#vertical-pinned-tabs-container .tabbrowser-tab[zen-glance-tab="true"] { #vertical-pinned-tabs-container .tabbrowser-tab[zen-glance-tab='true'] {
position: absolute !important; position: absolute !important;
} }

View file

@ -2,7 +2,9 @@ height: var(--zen-toolbar-height);
@media (-moz-bool-pref: 'zen.view.hide-window-controls') { @media (-moz-bool-pref: 'zen.view.hide-window-controls') {
& { & {
transition: height 0.15s ease, opacity 0.1s ease-out; transition:
height 0.15s ease,
opacity 0.1s ease-out;
transition-delay: 0.2s; transition-delay: 0.2s;
& > * { & > * {

View file

@ -21,7 +21,7 @@
/* Branding */ /* Branding */
--zen-branding-dark: #202020; --zen-branding-dark: #202020;
--zen-branding-coral: #F76F53; --zen-branding-coral: #f76f53;
--zen-branding-paper: #ebebeb; --zen-branding-paper: #ebebeb;
--zen-branding-bg: light-dark(var(--zen-branding-paper), var(--zen-branding-dark)); --zen-branding-bg: light-dark(var(--zen-branding-paper), var(--zen-branding-dark));
@ -43,9 +43,21 @@
--zen-secondary-btn-color: var(--zen-colors-primary-foreground); --zen-secondary-btn-color: var(--zen-colors-primary-foreground);
--in-content-primary-button-background: color-mix(in srgb, var(--zen-primary-color) 10%, var(--zen-branding-bg) 90%) !important; --in-content-primary-button-background: color-mix(
--in-content-primary-button-background-hover: color-mix(in srgb, var(--zen-primary-color) 15%, var(--zen-branding-bg) 85%) !important; in srgb,
--in-content-primary-button-background-active: color-mix(in srgb, var(--zen-primary-color) 20%, var(--zen-branding-bg) 80%) !important; var(--zen-primary-color) 10%,
var(--zen-branding-bg) 90%
) !important;
--in-content-primary-button-background-hover: color-mix(
in srgb,
var(--zen-primary-color) 15%,
var(--zen-branding-bg) 85%
) !important;
--in-content-primary-button-background-active: color-mix(
in srgb,
var(--zen-primary-color) 20%,
var(--zen-branding-bg) 80%
) !important;
--button-text-color-primary: var(--zen-branding-bg-reverse) !important; --button-text-color-primary: var(--zen-branding-bg-reverse) !important;
--in-content-primary-button-text-color: var(--zen-colors-primary-foreground) !important; --in-content-primary-button-text-color: var(--zen-colors-primary-foreground) !important;
--in-content-primary-button-border-color: transparent !important; --in-content-primary-button-border-color: transparent !important;
@ -91,10 +103,7 @@
--zen-button-border-radius: 5px; --zen-button-border-radius: 5px;
--zen-button-padding: 0.6rem 1.2rem; --zen-button-padding: 0.6rem 1.2rem;
--zen-toolbar-element-bg: light-dark( --zen-toolbar-element-bg: light-dark(rgba(255, 255, 255, 0.4), rgba(170, 170, 170, 0.2));
rgba(255, 255, 255, 0.4),
rgba(170, 170, 170, 0.2)
);
/* Toolbar */ /* Toolbar */
--zen-toolbar-height: 38px; --zen-toolbar-height: 38px;
@ -137,7 +146,10 @@
--fp-contextmenu-bgcolor: light-dark(Menu, rgb(43 42 51 / 0.95)); --fp-contextmenu-bgcolor: light-dark(Menu, rgb(43 42 51 / 0.95));
--toolbar-bgcolor: transparent; --toolbar-bgcolor: transparent;
--toolbarbutton-active-background: light-dark(rgba(255, 255, 255, .9), color-mix(in srgb, var(--zen-primary-color) 50%, rgba(255, 255, 255, .1))); --toolbarbutton-active-background: light-dark(
rgba(255, 255, 255, 0.9),
color-mix(in srgb, var(--zen-primary-color) 50%, rgba(255, 255, 255, 0.1))
);
--input-bgcolor: var(--zen-colors-tertiary) !important; --input-bgcolor: var(--zen-colors-tertiary) !important;
--input-border-color: var(--zen-input-border-color) !important; --input-border-color: var(--zen-input-border-color) !important;
@ -147,13 +159,16 @@
@media (-moz-windows-mica) or (-moz-platform: macos) { @media (-moz-windows-mica) or (-moz-platform: macos) {
background: transparent; background: transparent;
--zen-themed-toolbar-bg-transparency: 0; --zen-themed-toolbar-bg-transparency: 0;
--zen-themed-toolbar-bg-transparent: light-dark(rgba(255, 255, 255, var(--zen-themed-toolbar-bg-transparency)), rgba(0, 0, 0, var(--zen-themed-toolbar-bg-transparency))); --zen-themed-toolbar-bg-transparent: light-dark(
rgba(255, 255, 255, var(--zen-themed-toolbar-bg-transparency)),
rgba(0, 0, 0, var(--zen-themed-toolbar-bg-transparency))
);
} }
--toolbar-field-background-color: var(--zen-colors-input-bg) !important; --toolbar-field-background-color: var(--zen-colors-input-bg) !important;
--arrowpanel-background: var(--zen-dialog-background) !important; --arrowpanel-background: var(--zen-dialog-background) !important;
--tab-selected-shadow: 0 0 1px 1px rgba(0,0,0,.1) !important; --tab-selected-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1) !important;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {

View file

@ -48,7 +48,7 @@
outline-color: none !important; outline-color: none !important;
} }
#identity-box.chromeUI:not([pageproxystate="invalid"]) { #identity-box.chromeUI:not([pageproxystate='invalid']) {
& #identity-icon-box { & #identity-icon-box {
background: light-dark(rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.1)) !important; background: light-dark(rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.1)) !important;
} }
@ -125,7 +125,6 @@
} }
:root[zen-single-toolbar='true'] { :root[zen-single-toolbar='true'] {
.urlbar-page-action:not(#star-button-box):not([open]), .urlbar-page-action:not(#star-button-box):not([open]),
#tracking-protection-icon-container { #tracking-protection-icon-container {
margin-inline-end: calc(-16px - 2 * var(--urlbar-icon-padding)) !important; margin-inline-end: calc(-16px - 2 * var(--urlbar-icon-padding)) !important;
@ -437,7 +436,10 @@ button.popup-notification-dropmarker {
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
**/ **/
.urlbarView-title, .urlbarView-title-separator, .urlbarView-action, .urlbarView-url { .urlbarView-title,
.urlbarView-title-separator,
.urlbarView-action,
.urlbarView-url {
margin-top: auto !important; margin-top: auto !important;
margin-bottom: auto !important; margin-bottom: auto !important;
} }
@ -447,7 +449,8 @@ button.popup-notification-dropmarker {
font-weight: 500 !important; font-weight: 500 !important;
} }
.urlbarView-url, .urlbarView-title-separator::before { .urlbarView-url,
.urlbarView-title-separator::before {
font-size: 14px !important; font-size: 14px !important;
font-weight: 500 !important; font-weight: 500 !important;
color: #aaa !important; color: #aaa !important;
@ -460,7 +463,7 @@ button.popup-notification-dropmarker {
border-radius: 6px !important; border-radius: 6px !important;
} }
.urlbarView-row[has-action]:is([type="switchtab"], [type="remotetab"], [type="clipboard"]) .urlbarView-action { .urlbarView-row[has-action]:is([type='switchtab'], [type='remotetab'], [type='clipboard']) .urlbarView-action {
margin-left: auto !important; margin-left: auto !important;
margin-right: 0 !important; margin-right: 0 !important;
} }
@ -477,7 +480,8 @@ button.popup-notification-dropmarker {
background-color: color-mix(in srgb, var(--zen-branding-bg-reverse) 20%, transparent 80%) !important; background-color: color-mix(in srgb, var(--zen-branding-bg-reverse) 20%, transparent 80%) !important;
} }
.urlbarView-url, .urlbarView-title-separator::before { .urlbarView-url,
.urlbarView-title-separator::before {
color: color-mix(in srgb, var(--zen-colors-primary) 30%, lightgray) !important; color: color-mix(in srgb, var(--zen-colors-primary) 30%, lightgray) !important;
} }
} }

View file

@ -266,7 +266,6 @@
} }
} }
/* Workspace icon picker styles */ /* Workspace icon picker styles */
#PanelUI-zen-workspaces-icon-picker-wrapper { #PanelUI-zen-workspaces-icon-picker-wrapper {
display: flex; display: flex;
@ -391,7 +390,6 @@
background-color: var(--toolbarbutton-icon-fill-attention); background-color: var(--toolbarbutton-icon-fill-attention);
} }
#PanelUI-zen-workspaces-reorder-mode[active='true'] { #PanelUI-zen-workspaces-reorder-mode[active='true'] {
color: var(--toolbarbutton-icon-fill-attention) !important; color: var(--toolbarbutton-icon-fill-attention) !important;
} }

View file

@ -76,9 +76,9 @@ var ZenThemeModifier = {
const separation = Services.prefs.getIntPref('zen.theme.content-element-separation'); const separation = Services.prefs.getIntPref('zen.theme.content-element-separation');
document.documentElement.style.setProperty('--zen-element-separation', separation + 'px'); document.documentElement.style.setProperty('--zen-element-separation', separation + 'px');
if (separation == 0) { if (separation == 0) {
document.documentElement.setAttribute("zen-no-padding", true); document.documentElement.setAttribute('zen-no-padding', true);
} else { } else {
document.documentElement.removeAttribute("zen-no-padding"); document.documentElement.removeAttribute('zen-no-padding');
} }
}, },

View file

@ -1,4 +1,3 @@
// Utility to register JSWindowActors // Utility to register JSWindowActors
var gZenActorsManager = { var gZenActorsManager = {
_actors: new Set(), _actors: new Set(),
@ -16,4 +15,4 @@ var gZenActorsManager = {
console.warn(`Failed to register JSWindowActor: ${e}`); console.warn(`Failed to register JSWindowActor: ${e}`);
} }
}, },
} };

View file

@ -62,22 +62,14 @@ var gZenCommonActions = {
copyCurrentURLToClipboard() { copyCurrentURLToClipboard() {
const currentUrl = gBrowser.currentURI.spec; const currentUrl = gBrowser.currentURI.spec;
if (currentUrl) { if (currentUrl) {
let str = Cc["@mozilla.org/supports-string;1"].createInstance( let str = Cc['@mozilla.org/supports-string;1'].createInstance(Ci.nsISupportsString);
Ci.nsISupportsString
);
str.data = currentUrl; str.data = currentUrl;
let transferable = Cc[ let transferable = Cc['@mozilla.org/widget/transferable;1'].createInstance(Ci.nsITransferable);
"@mozilla.org/widget/transferable;1"
].createInstance(Ci.nsITransferable);
transferable.init(getLoadContext()); transferable.init(getLoadContext());
transferable.addDataFlavor("text/plain"); transferable.addDataFlavor('text/plain');
transferable.setTransferData("text/plain", str); transferable.setTransferData('text/plain', str);
Services.clipboard.setData( Services.clipboard.setData(transferable, null, Ci.nsIClipboard.kGlobalClipboard);
transferable, ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-copy-current-url-confirmation');
null,
Ci.nsIClipboard.kGlobalClipboard
);
ConfirmationHint.show(document.getElementById("PanelUI-menu-button"), "zen-copy-current-url-confirmation");
} }
}, },
@ -87,5 +79,5 @@ var gZenCommonActions = {
clearTimeout(timer); clearTimeout(timer);
timer = setTimeout(() => f.apply(this, args), delay); timer = setTimeout(() => f.apply(this, args), delay);
}; };
} },
}; };

View file

@ -69,7 +69,11 @@ var gZenCompactModeManager = {
updateCompactModeContext(isSingleToolbar) { updateCompactModeContext(isSingleToolbar) {
this.getAndApplySidebarWidth(); // Ignore return value this.getAndApplySidebarWidth(); // Ignore return value
const IDs = ['zen-context-menu-compact-mode-hide-sidebar', 'zen-context-menu-compact-mode-hide-toolbar', 'zen-context-menu-compact-mode-hide-both']; const IDs = [
'zen-context-menu-compact-mode-hide-sidebar',
'zen-context-menu-compact-mode-hide-toolbar',
'zen-context-menu-compact-mode-hide-both',
];
for (let id of IDs) { for (let id of IDs) {
document.getElementById(id).disabled = isSingleToolbar; document.getElementById(id).disabled = isSingleToolbar;
} }
@ -104,7 +108,7 @@ var gZenCompactModeManager = {
getAndApplySidebarWidth() { getAndApplySidebarWidth() {
let sidebarWidth = this.sidebar.getBoundingClientRect().width; let sidebarWidth = this.sidebar.getBoundingClientRect().width;
if (sidebarWidth > 1) { if (sidebarWidth > 1) {
this.sidebar.style.setProperty("--zen-sidebar-width", `${sidebarWidth}px`); this.sidebar.style.setProperty('--zen-sidebar-width', `${sidebarWidth}px`);
} }
return sidebarWidth; return sidebarWidth;
}, },
@ -118,40 +122,40 @@ var gZenCompactModeManager = {
this._isAnimating = true; this._isAnimating = true;
// Do this so we can get the correct width ONCE compact mode styled have been applied // Do this so we can get the correct width ONCE compact mode styled have been applied
if (this._canAnimateSidebar) { if (this._canAnimateSidebar) {
this.sidebar.setAttribute("animate", "true"); this.sidebar.setAttribute('animate', 'true');
} }
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
let sidebarWidth = this.getAndApplySidebarWidth(); let sidebarWidth = this.getAndApplySidebarWidth();
if (!this._canAnimateSidebar) { if (!this._canAnimateSidebar) {
this.sidebar.removeAttribute("animate"); this.sidebar.removeAttribute('animate');
this._isAnimating = false; this._isAnimating = false;
return; return;
} }
if (canHideSidebar && isCompactMode) { if (canHideSidebar && isCompactMode) {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.sidebar.style.position = "unset"; this.sidebar.style.position = 'unset';
this.sidebar.style.transition = "margin .4s ease"; this.sidebar.style.transition = 'margin .4s ease';
this.sidebar.style.left = "0"; this.sidebar.style.left = '0';
if (!this.sidebarIsOnRight) { if (!this.sidebarIsOnRight) {
this.sidebar.style.marginLeft = `${-1 * sidebarWidth}px`; this.sidebar.style.marginLeft = `${-1 * sidebarWidth}px`;
} else { } else {
this.sidebar.style.marginRight = `${-1 * sidebarWidth}px`; this.sidebar.style.marginRight = `${-1 * sidebarWidth}px`;
} }
this.sidebar.style.pointerEvents = "none"; this.sidebar.style.pointerEvents = 'none';
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
setTimeout(() => { setTimeout(() => {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.sidebar.style.removeProperty("pointer-events"); this.sidebar.style.removeProperty('pointer-events');
this.sidebar.style.removeProperty("position"); this.sidebar.style.removeProperty('position');
this.sidebar.style.removeProperty("margin-left"); this.sidebar.style.removeProperty('margin-left');
this.sidebar.style.removeProperty("margin-right"); this.sidebar.style.removeProperty('margin-right');
this.sidebar.style.removeProperty("transform"); this.sidebar.style.removeProperty('transform');
this.sidebar.style.removeProperty("left"); this.sidebar.style.removeProperty('left');
document.getElementById('browser').style.removeProperty("overflow"); document.getElementById('browser').style.removeProperty('overflow');
this.sidebar.removeAttribute("animate"); this.sidebar.removeAttribute('animate');
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.sidebar.style.removeProperty("transition"); this.sidebar.style.removeProperty('transition');
this._isAnimating = false; this._isAnimating = false;
}); });
}); });
@ -159,9 +163,9 @@ var gZenCompactModeManager = {
}); });
}); });
} else if (canHideSidebar && !isCompactMode) { } else if (canHideSidebar && !isCompactMode) {
document.getElementById('browser').style.overflow = "hidden"; document.getElementById('browser').style.overflow = 'hidden';
this.sidebar.style.position = "relative"; this.sidebar.style.position = 'relative';
this.sidebar.style.left = "0"; this.sidebar.style.left = '0';
if (!this.sidebarIsOnRight) { if (!this.sidebarIsOnRight) {
this.sidebar.style.marginLeft = `${-1 * sidebarWidth}px`; this.sidebar.style.marginLeft = `${-1 * sidebarWidth}px`;
@ -171,35 +175,35 @@ var gZenCompactModeManager = {
} }
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.sidebar.style.transition = "margin .3s ease, transform .275s ease, opacity .3s ease"; this.sidebar.style.transition = 'margin .3s ease, transform .275s ease, opacity .3s ease';
// we are in compact mode and we are exiting it // we are in compact mode and we are exiting it
if (!this.sidebarIsOnRight) { if (!this.sidebarIsOnRight) {
this.sidebar.style.marginLeft = "0"; this.sidebar.style.marginLeft = '0';
} else { } else {
this.sidebar.style.marginRight = "0"; this.sidebar.style.marginRight = '0';
this.sidebar.style.transform = "translateX(0)"; this.sidebar.style.transform = 'translateX(0)';
} }
this.sidebar.style.pointerEvents = "none"; this.sidebar.style.pointerEvents = 'none';
setTimeout(() => { setTimeout(() => {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this._isAnimating = false; this._isAnimating = false;
this.sidebar.style.removeProperty("position"); this.sidebar.style.removeProperty('position');
this.sidebar.style.removeProperty("pointer-events"); this.sidebar.style.removeProperty('pointer-events');
this.sidebar.style.removeProperty("opacity"); this.sidebar.style.removeProperty('opacity');
this.sidebar.style.removeProperty("margin-left"); this.sidebar.style.removeProperty('margin-left');
this.sidebar.style.removeProperty("margin-right"); this.sidebar.style.removeProperty('margin-right');
this.sidebar.style.removeProperty("transform"); this.sidebar.style.removeProperty('transform');
this.sidebar.style.removeProperty("transition"); this.sidebar.style.removeProperty('transition');
this.sidebar.style.removeProperty("left"); this.sidebar.style.removeProperty('left');
document.getElementById('browser').style.removeProperty("overflow"); document.getElementById('browser').style.removeProperty('overflow');
this.sidebar.removeAttribute("animate"); this.sidebar.removeAttribute('animate');
}); });
}, 400); }, 400);
}); });
} else { } else {
this.sidebar.removeAttribute("animate"); // remove the attribute if we are not animating this.sidebar.removeAttribute('animate'); // remove the attribute if we are not animating
} }
}); });
}, },

View file

@ -1,6 +1,4 @@
{ {
class ZenGlanceManager extends ZenDOMOperatedFeature { class ZenGlanceManager extends ZenDOMOperatedFeature {
#currentBrowser = null; #currentBrowser = null;
#currentTab = null; #currentTab = null;
@ -8,23 +6,19 @@
#animating = false; #animating = false;
init() { init() {
document.documentElement.setAttribute("zen-glance-uuid", gZenUIManager.generateUuidv4()); document.documentElement.setAttribute('zen-glance-uuid', gZenUIManager.generateUuidv4());
window.addEventListener("keydown", this.onKeyDown.bind(this)); window.addEventListener('keydown', this.onKeyDown.bind(this));
window.addEventListener("TabClose", this.onTabClose.bind(this)); window.addEventListener('TabClose', this.onTabClose.bind(this));
ChromeUtils.defineLazyGetter( ChromeUtils.defineLazyGetter(this, 'sidebarButtons', () => document.getElementById('zen-glance-sidebar-container'));
this,
'sidebarButtons',
() => document.getElementById('zen-glance-sidebar-container')
);
document.getElementById('tabbrowser-tabpanels').addEventListener("click", this.onOverlayClick.bind(this)); document.getElementById('tabbrowser-tabpanels').addEventListener('click', this.onOverlayClick.bind(this));
Services.obs.addObserver(this, "quit-application-requested"); Services.obs.addObserver(this, 'quit-application-requested');
} }
onKeyDown(event) { onKeyDown(event) {
if (event.key === "Escape" && this.#currentBrowser) { if (event.key === 'Escape' && this.#currentBrowser) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
this.closeGlance(); this.closeGlance();
@ -39,7 +33,7 @@
observe(subject, topic) { observe(subject, topic) {
switch (topic) { switch (topic) {
case "quit-application-requested": case 'quit-application-requested':
this.onUnload(); this.onUnload();
break; break;
} }
@ -54,7 +48,7 @@
createBrowserElement(url, currentTab) { createBrowserElement(url, currentTab) {
const newTabOptions = { const newTabOptions = {
userContextId: currentTab.getAttribute("usercontextid") || "", userContextId: currentTab.getAttribute('usercontextid') || '',
skipBackgroundNotify: true, skipBackgroundNotify: true,
insertTab: true, insertTab: true,
skipLoad: false, skipLoad: false,
@ -64,8 +58,8 @@
const newTab = gBrowser.addTrustedTab(Services.io.newURI(url).spec, newTabOptions); const newTab = gBrowser.addTrustedTab(Services.io.newURI(url).spec, newTabOptions);
gBrowser.selectedTab = newTab; gBrowser.selectedTab = newTab;
currentTab.querySelector(".tab-content").appendChild(newTab); currentTab.querySelector('.tab-content').appendChild(newTab);
newTab.setAttribute("zen-glance-tab", true); newTab.setAttribute('zen-glance-tab', true);
this.#currentBrowser = newTab.linkedBrowser; this.#currentBrowser = newTab.linkedBrowser;
this.#currentTab = newTab; this.#currentTab = newTab;
return this.#currentBrowser; return this.#currentBrowser;
@ -81,12 +75,12 @@
const initialWidth = data.width; const initialWidth = data.width;
const initialHeight = data.height; const initialHeight = data.height;
this.browserWrapper?.removeAttribute("animate"); this.browserWrapper?.removeAttribute('animate');
this.browserWrapper?.removeAttribute("animate-end"); this.browserWrapper?.removeAttribute('animate-end');
this.browserWrapper?.removeAttribute("animate-full"); this.browserWrapper?.removeAttribute('animate-full');
this.browserWrapper?.removeAttribute("animate-full-end"); this.browserWrapper?.removeAttribute('animate-full-end');
this.browserWrapper?.removeAttribute("has-finished-animation"); this.browserWrapper?.removeAttribute('has-finished-animation');
this.overlay?.removeAttribute("post-fade-out"); this.overlay?.removeAttribute('post-fade-out');
const url = data.url; const url = data.url;
const currentTab = gBrowser.selectedTab; const currentTab = gBrowser.selectedTab;
@ -94,29 +88,29 @@
this.animatingOpen = true; this.animatingOpen = true;
const browserElement = this.createBrowserElement(url, currentTab); const browserElement = this.createBrowserElement(url, currentTab);
this.overlay = browserElement.closest(".browserSidebarContainer"); this.overlay = browserElement.closest('.browserSidebarContainer');
this.browserWrapper = browserElement.closest(".browserContainer"); this.browserWrapper = browserElement.closest('.browserContainer');
this.contentWrapper = browserElement.closest(".browserStack"); this.contentWrapper = browserElement.closest('.browserStack');
this.browserWrapper.prepend(this.sidebarButtons); this.browserWrapper.prepend(this.sidebarButtons);
this.overlay.classList.add("zen-glance-overlay"); this.overlay.classList.add('zen-glance-overlay');
this.browserWrapper.removeAttribute("animate-end"); this.browserWrapper.removeAttribute('animate-end');
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.quickOpenGlance(); this.quickOpenGlance();
this.browserWrapper.style.setProperty("--initial-x", `${initialX}px`); this.browserWrapper.style.setProperty('--initial-x', `${initialX}px`);
this.browserWrapper.style.setProperty("--initial-y", `${initialY}px`); this.browserWrapper.style.setProperty('--initial-y', `${initialY}px`);
this.browserWrapper.style.setProperty("--initial-width", initialWidth + "px"); this.browserWrapper.style.setProperty('--initial-width', initialWidth + 'px');
this.browserWrapper.style.setProperty("--initial-height", initialHeight + "px"); this.browserWrapper.style.setProperty('--initial-height', initialHeight + 'px');
this.overlay.removeAttribute("fade-out"); this.overlay.removeAttribute('fade-out');
this.browserWrapper.setAttribute("animate", true); this.browserWrapper.setAttribute('animate', true);
this.#animating = true; this.#animating = true;
setTimeout(() => { setTimeout(() => {
this.browserWrapper.setAttribute("animate-end", true); this.browserWrapper.setAttribute('animate-end', true);
this.browserWrapper.setAttribute("has-finished-animation", true); this.browserWrapper.setAttribute('has-finished-animation', true);
this.#animating = false; this.#animating = false;
this.animatingOpen = false; this.animatingOpen = false;
}, 500); }, 500);
@ -128,7 +122,7 @@
return; return;
} }
this.browserWrapper.removeAttribute("has-finished-animation"); this.browserWrapper.removeAttribute('has-finished-animation');
if (noAnimation) { if (noAnimation) {
this.quickCloseGlance({ closeCurrentTab: false }); this.quickCloseGlance({ closeCurrentTab: false });
this.#currentBrowser = null; this.#currentBrowser = null;
@ -156,13 +150,13 @@
// do NOT touch here, I don't know what it does, but it works... // do NOT touch here, I don't know what it does, but it works...
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.#currentTab.style.display = "none"; this.#currentTab.style.display = 'none';
this.browserWrapper.removeAttribute("animate"); this.browserWrapper.removeAttribute('animate');
this.browserWrapper.removeAttribute("animate-end"); this.browserWrapper.removeAttribute('animate-end');
this.overlay.setAttribute("fade-out", true); this.overlay.setAttribute('fade-out', true);
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.quickCloseGlance({ justAnimateParent: true }); this.quickCloseGlance({ justAnimateParent: true });
this.browserWrapper.setAttribute("animate", true); this.browserWrapper.setAttribute('animate', true);
setTimeout(() => { setTimeout(() => {
if (!this.currentParentTab) { if (!this.currentParentTab) {
return; return;
@ -171,12 +165,12 @@
if (!onTabClose || quikcCloseZen) { if (!onTabClose || quikcCloseZen) {
this.quickCloseGlance(); this.quickCloseGlance();
} }
this.overlay.removeAttribute("fade-out"); this.overlay.removeAttribute('fade-out');
this.browserWrapper.removeAttribute("animate"); this.browserWrapper.removeAttribute('animate');
this.lastCurrentTab = this.#currentTab; this.lastCurrentTab = this.#currentTab;
this.overlay.classList.remove("zen-glance-overlay"); this.overlay.classList.remove('zen-glance-overlay');
gBrowser._getSwitcher().setTabStateNoAction(this.lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED); gBrowser._getSwitcher().setTabStateNoAction(this.lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED);
if (!onTabClose && gBrowser.selectedTab === this.lastCurrentTab) { if (!onTabClose && gBrowser.selectedTab === this.lastCurrentTab) {
@ -190,7 +184,7 @@
this.overlay = null; this.overlay = null;
this.contentWrapper = null; this.contentWrapper = null;
this.lastCurrentTab.removeAttribute("zen-glance-tab"); this.lastCurrentTab.removeAttribute('zen-glance-tab');
this.lastCurrentTab._closingGlance = true; this.lastCurrentTab._closingGlance = true;
gBrowser.tabContainer._invalidateCachedTabs(); gBrowser.tabContainer._invalidateCachedTabs();
@ -215,26 +209,28 @@
gBrowser.selectedTab = this.#currentTab; gBrowser.selectedTab = this.#currentTab;
} catch (e) {} } catch (e) {}
this.currentParentTab.linkedBrowser.closest(".browserSidebarContainer").classList.add("deck-selected", "zen-glance-background"); this.currentParentTab.linkedBrowser
this.currentParentTab.linkedBrowser.closest(".browserSidebarContainer").classList.remove("zen-glance-overlay"); .closest('.browserSidebarContainer')
.classList.add('deck-selected', 'zen-glance-background');
this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-overlay');
this.currentParentTab.linkedBrowser.zenModeActive = true; this.currentParentTab.linkedBrowser.zenModeActive = true;
this.#currentBrowser.zenModeActive = true; this.#currentBrowser.zenModeActive = true;
this.currentParentTab.linkedBrowser.docShellIsActive = true; this.currentParentTab.linkedBrowser.docShellIsActive = true;
this.#currentBrowser.docShellIsActive = true; this.#currentBrowser.docShellIsActive = true;
this.#currentBrowser.setAttribute("zen-glance-selected", true); this.#currentBrowser.setAttribute('zen-glance-selected', true);
this.currentParentTab._visuallySelected = true; this.currentParentTab._visuallySelected = true;
this.overlay.classList.add("deck-selected"); this.overlay.classList.add('deck-selected');
this._duringOpening = false; this._duringOpening = false;
} }
quickCloseGlance({ closeCurrentTab = true, closeParentTab = true, justAnimateParent = false } = {}) { quickCloseGlance({ closeCurrentTab = true, closeParentTab = true, justAnimateParent = false } = {}) {
const parentHasBrowser = !!(this.currentParentTab.linkedBrowser); const parentHasBrowser = !!this.currentParentTab.linkedBrowser;
if (!justAnimateParent) { if (!justAnimateParent) {
if (parentHasBrowser) { if (parentHasBrowser) {
if (closeParentTab) { if (closeParentTab) {
this.currentParentTab.linkedBrowser.closest(".browserSidebarContainer").classList.remove("deck-selected"); this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('deck-selected');
} }
this.currentParentTab.linkedBrowser.zenModeActive = false; this.currentParentTab.linkedBrowser.zenModeActive = false;
} }
@ -244,15 +240,15 @@
} }
if (closeCurrentTab) { if (closeCurrentTab) {
this.#currentBrowser.docShellIsActive = false; this.#currentBrowser.docShellIsActive = false;
this.overlay.classList.remove("deck-selected"); this.overlay.classList.remove('deck-selected');
} }
if (!this.currentParentTab._visuallySelected && closeParentTab) { if (!this.currentParentTab._visuallySelected && closeParentTab) {
this.currentParentTab._visuallySelected = false; this.currentParentTab._visuallySelected = false;
} }
this.#currentBrowser.removeAttribute("zen-glance-selected"); this.#currentBrowser.removeAttribute('zen-glance-selected');
} }
if (parentHasBrowser) { if (parentHasBrowser) {
this.currentParentTab.linkedBrowser.closest(".browserSidebarContainer").classList.remove("zen-glance-background"); this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
} }
} }
@ -285,15 +281,15 @@
this.animatingFullOpen = true; this.animatingFullOpen = true;
this.currentParentTab._visuallySelected = false; this.currentParentTab._visuallySelected = false;
this.browserWrapper.removeAttribute("has-finished-animation"); this.browserWrapper.removeAttribute('has-finished-animation');
this.browserWrapper.setAttribute("animate-full", true); this.browserWrapper.setAttribute('animate-full', true);
this.#currentTab.removeAttribute("zen-glance-tab"); this.#currentTab.removeAttribute('zen-glance-tab');
gBrowser.selectedTab = this.#currentTab; gBrowser.selectedTab = this.#currentTab;
this.currentParentTab.linkedBrowser.closest(".browserSidebarContainer").classList.remove("zen-glance-background"); this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
setTimeout(() => { setTimeout(() => {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.browserWrapper.setAttribute("animate-full-end", true); this.browserWrapper.setAttribute('animate-full-end', true);
this.overlay.classList.remove("zen-glance-overlay"); this.overlay.classList.remove('zen-glance-overlay');
setTimeout(() => { setTimeout(() => {
this.animatingFullOpen = false; this.animatingFullOpen = false;
this.closeGlance({ noAnimation: true }); this.closeGlance({ noAnimation: true });
@ -338,13 +334,13 @@
window.gZenGlanceManager = new ZenGlanceManager(); window.gZenGlanceManager = new ZenGlanceManager();
function registerWindowActors() { function registerWindowActors() {
if (Services.prefs.getBoolPref("zen.glance.enabled", true)) { if (Services.prefs.getBoolPref('zen.glance.enabled', true)) {
gZenActorsManager.addJSWindowActor("ZenGlance", { gZenActorsManager.addJSWindowActor('ZenGlance', {
parent: { parent: {
esModuleURI: "chrome://browser/content/zen-components/actors/ZenGlanceParent.sys.mjs", esModuleURI: 'chrome://browser/content/zen-components/actors/ZenGlanceParent.sys.mjs',
}, },
child: { child: {
esModuleURI: "chrome://browser/content/zen-components/actors/ZenGlanceChild.sys.mjs", esModuleURI: 'chrome://browser/content/zen-components/actors/ZenGlanceChild.sys.mjs',
events: { events: {
DOMContentLoaded: {}, DOMContentLoaded: {},
}, },

View file

@ -18,8 +18,12 @@
ChromeUtils.defineLazyGetter(this, 'panel', () => document.getElementById('PanelUI-zen-gradient-generator')); ChromeUtils.defineLazyGetter(this, 'panel', () => document.getElementById('PanelUI-zen-gradient-generator'));
ChromeUtils.defineLazyGetter(this, 'toolbox', () => document.getElementById('TabsToolbar')); ChromeUtils.defineLazyGetter(this, 'toolbox', () => document.getElementById('TabsToolbar'));
ChromeUtils.defineLazyGetter(this, 'customColorInput', () => document.getElementById('PanelUI-zen-gradient-generator-custom-input')); ChromeUtils.defineLazyGetter(this, 'customColorInput', () =>
ChromeUtils.defineLazyGetter(this, 'customColorList', () => document.getElementById('PanelUI-zen-gradient-generator-custom-list')); document.getElementById('PanelUI-zen-gradient-generator-custom-input')
);
ChromeUtils.defineLazyGetter(this, 'customColorList', () =>
document.getElementById('PanelUI-zen-gradient-generator-custom-list')
);
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
this, this,
@ -27,7 +31,7 @@
'zen.theme.color-prefs.use-workspace-colors', 'zen.theme.color-prefs.use-workspace-colors',
true, true,
this.onDarkModeChange.bind(this) this.onDarkModeChange.bind(this)
) );
this.initRotation(); this.initRotation();
this.initCanvas(); this.initCanvas();
@ -74,7 +78,6 @@
this.image.onload = this.onImageLoad.bind(this); this.image.onload = this.onImageLoad.bind(this);
} }
onImageLoad() { onImageLoad() {
// resize the image to fit the panel // resize the image to fit the panel
const imageSize = 300 - 20; // 20 is the padding (10px) const imageSize = 300 - 20; // 20 is the padding (10px)
@ -145,7 +148,7 @@
x = event.clientX; x = event.clientX;
y = event.clientY; y = event.clientY;
} }
const degrees = Math.round(Math.atan2(y - centerY, x - centerX) * 180 / Math.PI); const degrees = Math.round((Math.atan2(y - centerY, x - centerX) * 180) / Math.PI);
this.setRotationInput(degrees); this.setRotationInput(degrees);
this.updateCurrentWorkspace(); this.updateCurrentWorkspace();
} }
@ -200,7 +203,7 @@
// Check if there's an exact match // Check if there's an exact match
for (const pixel of similarPixels) { for (const pixel of similarPixels) {
const x = (pixel / 4) % this.canvas.width; const x = (pixel / 4) % this.canvas.width;
const y = Math.floor((pixel / 4) / this.canvas.width); const y = Math.floor(pixel / 4 / this.canvas.width);
const pixelColor = this.getColorFromPosition(x, y); const pixelColor = this.getColorFromPosition(x, y);
if (pixelColor[0] === r && pixelColor[1] === g && pixelColor[2] === b) { if (pixelColor[0] === r && pixelColor[1] === g && pixelColor[2] === b) {
return { x: x / this.canvas.width, y: y / this.canvas.height }; return { x: x / this.canvas.width, y: y / this.canvas.height };
@ -209,7 +212,7 @@
// If there's no exact match, return the first similar pixel // If there's no exact match, return the first similar pixel
const pixel = similarPixels[0]; const pixel = similarPixels[0];
const x = (pixel / 4) % this.canvas.width; const x = (pixel / 4) % this.canvas.width;
const y = Math.floor((pixel / 4) / this.canvas.width); const y = Math.floor(pixel / 4 / this.canvas.width);
return { x: x / this.canvas.width, y: y / this.canvas.height }; return { x: x / this.canvas.width, y: y / this.canvas.height };
} }
@ -268,7 +271,6 @@
// Only proceed if not clicking on an existing dot // Only proceed if not clicking on an existing dot
if (!isExistingDot) { if (!isExistingDot) {
const relativeX = event.clientX - rect.left; const relativeX = event.clientX - rect.left;
const relativeY = event.clientY - rect.top; const relativeY = event.clientY - rect.top;
@ -287,11 +289,8 @@
this.updateCurrentWorkspace(true); this.updateCurrentWorkspace(true);
} }
} }
onDotMouseDown(event) { onDotMouseDown(event) {
event.preventDefault(); event.preventDefault();
if (event.button === 2) { if (event.button === 2) {
@ -305,11 +304,10 @@
// Store the starting position of the drag // Store the starting position of the drag
this.dragStartPosition = { this.dragStartPosition = {
x: event.clientX, x: event.clientX,
y: event.clientY y: event.clientY,
}; };
} }
onDotMouseMove(event) { onDotMouseMove(event) {
if (this.dragging) { if (this.dragging) {
event.preventDefault(); event.preventDefault();
@ -436,7 +434,7 @@
// Store the starting position of the drag // Store the starting position of the drag
this.dragStartPosition = { this.dragStartPosition = {
x: event.clientX, x: event.clientX,
y: event.clientY y: event.clientY,
}; };
} }
@ -465,19 +463,16 @@
this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length; this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length;
} }
themedColors(colors) { themedColors(colors) {
const isDarkMode = this.isDarkMode; const isDarkMode = this.isDarkMode;
const factor = isDarkMode ? 0.5 : 1.1; const factor = isDarkMode ? 0.5 : 1.1;
return colors.map(color => { return colors.map((color) => {
return { return {
c: color.isCustom ? color.c : [ c: color.isCustom
Math.min(255, color.c[0] * factor), ? color.c
Math.min(255, color.c[1] * factor), : [Math.min(255, color.c[0] * factor), Math.min(255, color.c[1] * factor), Math.min(255, color.c[2] * factor)],
Math.min(255, color.c[2] * factor),
],
isCustom: color.isCustom, isCustom: color.isCustom,
} };
}); });
} }
@ -492,8 +487,8 @@
} }
getToolbarModifiedBase() { getToolbarModifiedBase() {
return this.isDarkMode ? return this.isDarkMode
'color-mix(in srgb, var(--zen-themed-toolbar-bg) 80%, #fff 20%)' ? 'color-mix(in srgb, var(--zen-themed-toolbar-bg) 80%, #fff 20%)'
: 'color-mix(in srgb, var(--zen-themed-toolbar-bg) 95%, #000 5%)'; : 'color-mix(in srgb, var(--zen-themed-toolbar-bg) 95%, #000 5%)';
} }
@ -508,17 +503,17 @@
getGradient(colors, forToolbar = false) { getGradient(colors, forToolbar = false) {
const themedColors = this.themedColors(colors); const themedColors = this.themedColors(colors);
if (themedColors.length === 0) { if (themedColors.length === 0) {
return forToolbar ? "var(--zen-themed-toolbar-bg)" : "var(--zen-themed-toolbar-bg-transparent)"; return forToolbar ? 'var(--zen-themed-toolbar-bg)' : 'var(--zen-themed-toolbar-bg-transparent)';
} else if (themedColors.length === 1) { } else if (themedColors.length === 1) {
return this.getSingleRGBColor(themedColors[0], forToolbar); return this.getSingleRGBColor(themedColors[0], forToolbar);
} }
return `linear-gradient(${this.currentRotation}deg, ${themedColors.map(color => this.getSingleRGBColor(color, forToolbar)).join(', ')})`; return `linear-gradient(${this.currentRotation}deg, ${themedColors.map((color) => this.getSingleRGBColor(color, forToolbar)).join(', ')})`;
} }
static getTheme(colors = [], opacity = 0.5, rotation = 45, texture = 0) { static getTheme(colors = [], opacity = 0.5, rotation = 45, texture = 0) {
return { return {
type: 'gradient', type: 'gradient',
gradientColors: colors ? colors.filter(color => color) : [], // remove undefined gradientColors: colors ? colors.filter((color) => color) : [], // remove undefined
opacity, opacity,
rotation, rotation,
texture, texture,
@ -535,43 +530,70 @@
hex = hex.substring(1); hex = hex.substring(1);
} }
if (hex.length === 3) { if (hex.length === 3) {
hex = hex.split('').map(char => char + char).join(''); hex = hex
.split('')
.map((char) => char + char)
.join('');
} }
return [ return [parseInt(hex.substring(0, 2), 16), parseInt(hex.substring(2, 4), 16), parseInt(hex.substring(4, 6), 16)];
parseInt(hex.substring(0, 2), 16),
parseInt(hex.substring(2, 4), 16),
parseInt(hex.substring(4, 6), 16),
];
} }
pSBC = (p, c0, c1, l) => { pSBC = (p, c0, c1, l) => {
let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string"; let r,
if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null; g,
if(!this.pSBCr)this.pSBCr=(d)=>{ b,
let n=d.length,x={}; P,
f,
t,
h,
i = parseInt,
m = Math.round,
a = typeof c1 == 'string';
if (typeof p != 'number' || p < -1 || p > 1 || typeof c0 != 'string' || (c0[0] != 'r' && c0[0] != '#') || (c1 && !a))
return null;
if (!this.pSBCr)
this.pSBCr = (d) => {
let n = d.length,
x = {};
if (n > 9) { if (n > 9) {
[r,g,b,a]=d=d.split(","),n=d.length; ([r, g, b, a] = d = d.split(',')), (n = d.length);
if (n < 3 || n > 4) return null; if (n < 3 || n > 4) return null;
x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1 (x.r = i(r[3] == 'a' ? r.slice(5) : r.slice(4))), (x.g = i(g)), (x.b = i(b)), (x.a = a ? parseFloat(a) : -1);
} else { } else {
if (n == 8 || n == 6 || n < 4) return null; if (n == 8 || n == 6 || n < 4) return null;
if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:""); if (n < 6) d = '#' + d[1] + d[1] + d[2] + d[2] + d[3] + d[3] + (n > 4 ? d[4] + d[4] : '');
d = i(d.slice(1), 16); d = i(d.slice(1), 16);
if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000; if (n == 9 || n == 5)
else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1 (x.r = (d >> 24) & 255), (x.g = (d >> 16) & 255), (x.b = (d >> 8) & 255), (x.a = m((d & 255) / 0.255) / 1000);
}return x}; else (x.r = d >> 16), (x.g = (d >> 8) & 255), (x.b = d & 255), (x.a = -1);
h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
if(!f||!t)return null;
if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
} }
return x;
};
(h = c0.length > 9),
(h = a ? (c1.length > 9 ? true : c1 == 'c' ? !h : false) : h),
(f = this.pSBCr(c0)),
(P = p < 0),
(t = c1 && c1 != 'c' ? this.pSBCr(c1) : P ? { r: 0, g: 0, b: 0, a: -1 } : { r: 255, g: 255, b: 255, a: -1 }),
(p = P ? p * -1 : p),
(P = 1 - p);
if (!f || !t) return null;
if (l) (r = m(P * f.r + p * t.r)), (g = m(P * f.g + p * t.g)), (b = m(P * f.b + p * t.b));
else
(r = m((P * f.r ** 2 + p * t.r ** 2) ** 0.5)),
(g = m((P * f.g ** 2 + p * t.g ** 2) ** 0.5)),
(b = m((P * f.b ** 2 + p * t.b ** 2) ** 0.5));
(a = f.a), (t = t.a), (f = a >= 0 || t >= 0), (a = f ? (a < 0 ? t : t < 0 ? a : a * P + t * p) : 0);
if (h) return 'rgb' + (f ? 'a(' : '(') + r + ',' + g + ',' + b + (f ? ',' + m(a * 1000) / 1000 : '') + ')';
else
return (
'#' +
(4294967296 + r * 16777216 + g * 65536 + b * 256 + (f ? m(a * 255) : 0)).toString(16).slice(1, f ? undefined : -2)
);
};
getMostDominantColor(allColors) { getMostDominantColor(allColors) {
const colors = this.themedColors(allColors); const colors = this.themedColors(allColors);
const themedColors = colors.filter(color => !color.isCustom); const themedColors = colors.filter((color) => !color.isCustom);
if (themedColors.length === 0 || !this.allowWorkspaceColors) { if (themedColors.length === 0 || !this.allowWorkspaceColors) {
return null; return null;
} }
@ -579,7 +601,9 @@
let dominantColor = themedColors[0].c; let dominantColor = themedColors[0].c;
let dominantColorCount = 0; let dominantColorCount = 0;
for (const color of themedColors) { for (const color of themedColors) {
const count = themedColors.filter(c => c.c[0] === color.c[0] && c.c[1] === color.c[1] && c.c[2] === color.c[2]).length; const count = themedColors.filter(
(c) => c.c[0] === color.c[0] && c.c[1] === color.c[1] && c.c[2] === color.c[2]
).length;
if (count > dominantColorCount) { if (count > dominantColorCount) {
dominantColorCount = count; dominantColorCount = count;
dominantColor = color.c; dominantColor = color.c;
@ -587,12 +611,12 @@
} }
const result = this.pSBC( const result = this.pSBC(
this.isDarkMode ? 0.2 : -0.5, this.isDarkMode ? 0.2 : -0.5,
`rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})`); `rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})`
);
return result?.match(/\d+/g).map(Number); return result?.match(/\d+/g).map(Number);
} }
async onWorkspaceChange(workspace, skipUpdate = false, theme = null) { async onWorkspaceChange(workspace, skipUpdate = false, theme = null) {
const uuid = workspace.uuid; const uuid = workspace.uuid;
// Use theme from workspace object or passed theme // Use theme from workspace object or passed theme
let workspaceTheme = theme || workspace.theme; let workspaceTheme = theme || workspace.theme;
@ -616,12 +640,12 @@
} }
} }
const appWrapper = browser.document.getElementById('browser'); const appWrapper = browser.document.getElementById('browser');
if (!skipUpdate && !this._animatingBackground) { if (!skipUpdate && !this._animatingBackground) {
this._animatingBackground = true; this._animatingBackground = true;
appWrapper.removeAttribute('animating'); appWrapper.removeAttribute('animating');
browser.document.documentElement.style.setProperty('--zen-main-browser-background-old', browser.document.documentElement.style.setProperty(
'--zen-main-browser-background-old',
browser.document.documentElement.style.getPropertyValue('--zen-main-browser-background') browser.document.documentElement.style.getPropertyValue('--zen-main-browser-background')
); );
browser.window.requestAnimationFrame(() => { browser.window.requestAnimationFrame(() => {
@ -656,8 +680,10 @@
browser.gZenThemePicker.numberOfDots = workspaceTheme.gradientColors.length; browser.gZenThemePicker.numberOfDots = workspaceTheme.gradientColors.length;
browser.document.getElementById('PanelUI-zen-gradient-generator-opacity').value = browser.gZenThemePicker.currentOpacity; browser.document.getElementById('PanelUI-zen-gradient-generator-opacity').value =
browser.document.getElementById('PanelUI-zen-gradient-generator-texture').value = browser.gZenThemePicker.currentTexture; browser.gZenThemePicker.currentOpacity;
browser.document.getElementById('PanelUI-zen-gradient-generator-texture').value =
browser.gZenThemePicker.currentTexture;
browser.gZenThemePicker.setRotationInput(browser.gZenThemePicker.currentRotation); browser.gZenThemePicker.setRotationInput(browser.gZenThemePicker.currentRotation);
const gradient = browser.gZenThemePicker.getGradient(workspaceTheme.gradientColors); const gradient = browser.gZenThemePicker.getGradient(workspaceTheme.gradientColors);
@ -675,7 +701,10 @@
const dominantColor = this.getMostDominantColor(workspaceTheme.gradientColors); const dominantColor = this.getMostDominantColor(workspaceTheme.gradientColors);
if (dominantColor) { if (dominantColor) {
browser.document.documentElement.style.setProperty('--zen-primary-color', `rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})`); browser.document.documentElement.style.setProperty(
'--zen-primary-color',
`rgb(${dominantColor[0]}, ${dominantColor[1]}, ${dominantColor[2]})`
);
} }
if (!skipUpdate) { if (!skipUpdate) {
@ -726,10 +755,9 @@
} }
async updateCurrentWorkspace(skipSave = true) { async updateCurrentWorkspace(skipSave = true) {
this.updated = skipSave; this.updated = skipSave;
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot'); const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
const colors = Array.from(dots).map(dot => { const colors = Array.from(dots).map((dot) => {
const color = dot.style.getPropertyValue('--zen-theme-picker-dot-color'); const color = dot.style.getPropertyValue('--zen-theme-picker-dot-color');
if (color === 'undefined') { if (color === 'undefined') {
return; return;
@ -743,7 +771,7 @@
if (!skipSave) { if (!skipSave) {
await ZenWorkspacesStorage.saveWorkspaceTheme(currentWorkspace.uuid, gradient); await ZenWorkspacesStorage.saveWorkspaceTheme(currentWorkspace.uuid, gradient);
await ZenWorkspaces._propagateWorkspaceData(); await ZenWorkspaces._propagateWorkspaceData();
ConfirmationHint.show(document.getElementById("PanelUI-menu-button"), "zen-panel-ui-gradient-generator-saved-message"); ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-panel-ui-gradient-generator-saved-message');
currentWorkspace = await ZenWorkspaces.getActiveWorkspace(); currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
} }
@ -754,7 +782,6 @@
if (this.updated) { if (this.updated) {
await this.updateCurrentWorkspace(false); await this.updateCurrentWorkspace(false);
} }
} }
} }

View file

@ -103,7 +103,9 @@ const defaultKeyboardGroups = {
'zen-bidi-switch-direction-shortcut', 'zen-bidi-switch-direction-shortcut',
'zen-screenshot-shortcut', 'zen-screenshot-shortcut',
], ],
devTools: [/*Filled automatically*/], devTools: [
/*Filled automatically*/
],
}; };
const fixedL10nIds = { const fixedL10nIds = {
@ -215,9 +217,9 @@ class KeyShortcutModifiers {
this.#shift == other.#shift && this.#shift == other.#shift &&
this.#control == other.#control && this.#control == other.#control &&
(AppConstants.platform == 'macosx' (AppConstants.platform == 'macosx'
? ((this.#meta || this.#accel) == (other.#meta || other.#accel) && this.#control == other.#control) ? (this.#meta || this.#accel) == (other.#meta || other.#accel) && this.#control == other.#control
// In other platforms, we can have control and accel counting as the same thing : // In other platforms, we can have control and accel counting as the same thing
: (this.#meta == other.#meta && (this.#control || this.#accel) == (other.#control || other.#accel))) this.#meta == other.#meta && (this.#control || this.#accel) == (other.#control || other.#accel))
); );
} }
@ -362,7 +364,8 @@ class KeyShortcut {
key.getAttribute('id'), key.getAttribute('id'),
key.getAttribute('key'), key.getAttribute('key'),
key.getAttribute('keycode'), key.getAttribute('keycode'),
group ?? KeyShortcut.getGroupFromL10nId(KeyShortcut.sanitizeL10nId(key.getAttribute('data-l10n-id')), key.getAttribute('id')), group ??
KeyShortcut.getGroupFromL10nId(KeyShortcut.sanitizeL10nId(key.getAttribute('data-l10n-id')), key.getAttribute('id')),
KeyShortcutModifiers.parseFromXHTMLAttribute(key.getAttribute('modifiers')), KeyShortcutModifiers.parseFromXHTMLAttribute(key.getAttribute('modifiers')),
key.getAttribute('command'), key.getAttribute('command'),
key.getAttribute('data-l10n-id'), key.getAttribute('data-l10n-id'),
@ -737,9 +740,14 @@ class ZenKeyboardShortcutsLoader {
} }
// Make sure to stay in sync with https://searchfox.org/mozilla-central/source/devtools/startup/DevToolsStartup.sys.mjs#879 // Make sure to stay in sync with https://searchfox.org/mozilla-central/source/devtools/startup/DevToolsStartup.sys.mjs#879
static IGNORED_DEVTOOLS_SHORTCUTS = ['key_toggleToolboxF12', 'profilerStartStop', static IGNORED_DEVTOOLS_SHORTCUTS = [
'profilerStartStopAlternate', 'profilerCapture', 'profilerCaptureAlternate', 'key_toggleToolboxF12',
'javascriptTracingToggle']; 'profilerStartStop',
'profilerStartStopAlternate',
'profilerCapture',
'profilerCaptureAlternate',
'javascriptTracingToggle',
];
static zenGetDefaultDevToolsShortcuts() { static zenGetDefaultDevToolsShortcuts() {
let keySet = document.getElementById(ZEN_DEVTOOLS_KEYSET_ID); let keySet = document.getElementById(ZEN_DEVTOOLS_KEYSET_ID);
@ -925,7 +933,7 @@ var gZenKeyboardShortcutsManager = {
// Create the main keyset before calling the async init function, // Create the main keyset before calling the async init function,
// This is because other browser-sets needs this element and the JS event // This is because other browser-sets needs this element and the JS event
// handled wont wait for the async function to finish. // handled wont wait for the async function to finish.
void(this.getZenKeyset()); void this.getZenKeyset();
this._hasCleared = Services.prefs.getBoolPref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false); this._hasCleared = Services.prefs.getBoolPref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false);
window.addEventListener('zen-devtools-keyset-added', this._hasAddedDevtoolShortcuts.bind(this)); window.addEventListener('zen-devtools-keyset-added', this._hasAddedDevtoolShortcuts.bind(this));
@ -962,10 +970,10 @@ var gZenKeyboardShortcutsManager = {
} catch (e) { } catch (e) {
console.error('Zen CKS: Error parsing saved shortcuts. Resetting to defaults...', e); console.error('Zen CKS: Error parsing saved shortcuts. Resetting to defaults...', e);
gNotificationBox.appendNotification( gNotificationBox.appendNotification(
"zen-shortcuts-corrupted", 'zen-shortcuts-corrupted',
{ {
label: { "l10n-id": "zen-shortcuts-corrupted" }, label: { 'l10n-id': 'zen-shortcuts-corrupted' },
image: "chrome://browser/skin/notification-icons/persistent-storage-blocked.svg", image: 'chrome://browser/skin/notification-icons/persistent-storage-blocked.svg',
priority: gNotificationBox.PRIORITY_WARNING_HIGH, priority: gNotificationBox.PRIORITY_WARNING_HIGH,
}, },
[] []
@ -1179,8 +1187,12 @@ var gZenKeyboardShortcutsManager = {
}, },
}; };
document.addEventListener("MozBeforeInitialXULLayout", () => { document.addEventListener(
'MozBeforeInitialXULLayout',
() => {
if (Services.prefs.getBoolPref('zen.keyboard.shortcuts.enabled', false)) { if (Services.prefs.getBoolPref('zen.keyboard.shortcuts.enabled', false)) {
gZenKeyboardShortcutsManager.beforeInit(); gZenKeyboardShortcutsManager.beforeInit();
} }
}, { once: true }); },
{ once: true }
);

View file

@ -7,9 +7,19 @@
#listeners = []; #listeners = [];
constructor() { constructor() {
XPCOMUtils.defineLazyPreferenceGetter(lazy, 'zenPinnedTabRestorePinnedTabsToPinnedUrl', 'zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false); XPCOMUtils.defineLazyPreferenceGetter(
XPCOMUtils.defineLazyPreferenceGetter(lazy, 'zenPinnedTabCloseShortcutBehavior', 'zen.pinned-tab-manager.close-shortcut-behavior', 'switch'); lazy,
ChromeUtils.defineESModuleGetters(lazy, {E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs"}); 'zenPinnedTabRestorePinnedTabsToPinnedUrl',
'zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url',
false
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
'zenPinnedTabCloseShortcutBehavior',
'zen.pinned-tab-manager.close-shortcut-behavior',
'switch'
);
ChromeUtils.defineESModuleGetters(lazy, { E10SUtils: 'resource://gre/modules/E10SUtils.sys.mjs' });
this.#listenPinnedTabEvents(); this.#listenPinnedTabEvents();
} }
@ -37,7 +47,6 @@
} }
class ZenPinnedTabManager extends ZenDOMOperatedFeature { class ZenPinnedTabManager extends ZenDOMOperatedFeature {
init() { init() {
if (!this.enabled) { if (!this.enabled) {
return; return;
@ -81,30 +90,31 @@
const pins = await ZenPinnedTabsStorage.getPins(); const pins = await ZenPinnedTabsStorage.getPins();
// Enhance pins with favicons // Enhance pins with favicons
const enhancedPins = await Promise.all(pins.map(async pin => { const enhancedPins = await Promise.all(
pins.map(async (pin) => {
try { try {
const image = await this.getFaviconAsBase64(Services.io.newURI(pin.url).spec); const image = await this.getFaviconAsBase64(Services.io.newURI(pin.url).spec);
return { return {
...pin, ...pin,
iconUrl: image || null iconUrl: image || null,
}; };
} catch (ex) { } catch (ex) {
// If favicon fetch fails, continue without icon // If favicon fetch fails, continue without icon
return { return {
...pin, ...pin,
iconUrl: null iconUrl: null,
}; };
} }
})); })
);
this._pinsCache = enhancedPins.sort((a, b) => { this._pinsCache = enhancedPins.sort((a, b) => {
if (!a.workspaceUuid && b.workspaceUuid) return -1; if (!a.workspaceUuid && b.workspaceUuid) return -1;
if (a.workspaceUuid && !b.workspaceUuid) return 1; if (a.workspaceUuid && !b.workspaceUuid) return 1;
return 0; return 0;
}); });
} catch (ex) { } catch (ex) {
console.error("Failed to initialize pins cache:", ex); console.error('Failed to initialize pins cache:', ex);
this._pinsCache = []; this._pinsCache = [];
} }
@ -121,11 +131,11 @@
const activeTab = gBrowser.selectedTab; const activeTab = gBrowser.selectedTab;
const pinnedTabsByUUID = new Map(); const pinnedTabsByUUID = new Map();
const pinsToCreate = new Set(pins.map(p => p.uuid)); const pinsToCreate = new Set(pins.map((p) => p.uuid));
// First pass: identify existing tabs and remove those without pins // First pass: identify existing tabs and remove those without pins
for (let tab of gBrowser.tabs) { for (let tab of gBrowser.tabs) {
const pinId = tab.getAttribute("zen-pin-id"); const pinId = tab.getAttribute('zen-pin-id');
if (!pinId) { if (!pinId) {
continue; continue;
} }
@ -161,7 +171,7 @@
userContextId: pin.containerTabId || 0, userContextId: pin.containerTabId || 0,
createLazyBrowser: true, createLazyBrowser: true,
skipLoad: true, skipLoad: true,
noInitialLabel: false noInitialLabel: false,
}; };
// Create and initialize the tab // Create and initialize the tab
@ -177,26 +187,28 @@
gBrowser.setIcon(newTab, pin.iconUrl); gBrowser.setIcon(newTab, pin.iconUrl);
} }
newTab.setAttribute("zen-pin-id", pin.uuid); newTab.setAttribute('zen-pin-id', pin.uuid);
if (pin.workspaceUuid) { if (pin.workspaceUuid) {
newTab.setAttribute("zen-workspace-id", pin.workspaceUuid); newTab.setAttribute('zen-workspace-id', pin.workspaceUuid);
} }
if (pin.isEssential) { if (pin.isEssential) {
newTab.setAttribute("zen-essential", "true"); newTab.setAttribute('zen-essential', 'true');
} }
// Initialize browser state if needed // Initialize browser state if needed
if (!newTab.linkedBrowser._remoteAutoRemoved) { if (!newTab.linkedBrowser._remoteAutoRemoved) {
let state = { let state = {
entries: [{ entries: [
{
url: pin.url, url: pin.url,
title: pin.title, title: pin.title,
triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL,
}], },
],
userContextId: pin.containerTabId || 0, userContextId: pin.containerTabId || 0,
image: pin.iconUrl image: pin.iconUrl,
}; };
SessionStore.setTabState(newTab, state); SessionStore.setTabState(newTab, state);
@ -204,7 +216,6 @@
gBrowser.pinTab(newTab); gBrowser.pinTab(newTab);
newTab.initialize(); newTab.initialize();
} }
@ -219,8 +230,8 @@
_shouldShowPin(pin, currentWorkspace, workspaces) { _shouldShowPin(pin, currentWorkspace, workspaces) {
const isEssential = pin.isEssential; const isEssential = pin.isEssential;
const pinWorkspaceUuid = pin.workspaceUuid; const pinWorkspaceUuid = pin.workspaceUuid;
const pinContextId = pin.containerTabId ? pin.containerTabId.toString() : "0"; const pinContextId = pin.containerTabId ? pin.containerTabId.toString() : '0';
const workspaceContextId = currentWorkspace.containerTabId?.toString() || "0"; const workspaceContextId = currentWorkspace.containerTabId?.toString() || '0';
const containerSpecificEssentials = ZenWorkspaces.containerSpecificEssentials; const containerSpecificEssentials = ZenWorkspaces.containerSpecificEssentials;
// Handle essential pins // Handle essential pins
@ -229,14 +240,16 @@
return true; // Show all essential pins when containerSpecificEssentials is false return true; // Show all essential pins when containerSpecificEssentials is false
} }
if (workspaceContextId !== "0") { if (workspaceContextId !== '0') {
// In workspaces with default container: Show essentials that match the container // In workspaces with default container: Show essentials that match the container
return pinContextId === workspaceContextId; return pinContextId === workspaceContextId;
} else { } else {
// In workspaces without a default container: Show essentials that aren't in container-specific workspaces // In workspaces without a default container: Show essentials that aren't in container-specific workspaces
// or have userContextId="0" or no userContextId // or have userContextId="0" or no userContextId
return !pinContextId || pinContextId === "0" || !workspaces.workspaces.some( return (
workspace => workspace.containerTabId === parseInt(pinContextId, 10) !pinContextId ||
pinContextId === '0' ||
!workspaces.workspaces.some((workspace) => workspace.containerTabId === parseInt(pinContextId, 10))
); );
} }
} }
@ -255,19 +268,19 @@
if (!this.enabled) return; if (!this.enabled) return;
const tab = event.target; const tab = event.target;
switch (action) { switch (action) {
case "TabPinned": case 'TabPinned':
tab._zenClickEventListener = this._zenClickEventListener; tab._zenClickEventListener = this._zenClickEventListener;
tab.addEventListener("click", tab._zenClickEventListener); tab.addEventListener('click', tab._zenClickEventListener);
this._setPinnedAttributes(tab); this._setPinnedAttributes(tab);
break; break;
case "TabUnpinned": case 'TabUnpinned':
this._removePinnedAttributes(tab); this._removePinnedAttributes(tab);
if (tab._zenClickEventListener) { if (tab._zenClickEventListener) {
tab.removeEventListener("click", tab._zenClickEventListener); tab.removeEventListener('click', tab._zenClickEventListener);
delete tab._zenClickEventListener; delete tab._zenClickEventListener;
} }
break; break;
case "TabMove": case 'TabMove':
this._onTabMove(tab); this._onTabMove(tab);
break; break;
default: default:
@ -288,26 +301,25 @@
for (let otherTab of gBrowser.tabs) { for (let otherTab of gBrowser.tabs) {
if (otherTab.pinned && otherTab._tPos > tab.position) { if (otherTab.pinned && otherTab._tPos > tab.position) {
const actualPin = this._pinsCache.find(pin => pin.uuid === otherTab.getAttribute("zen-pin-id")); const actualPin = this._pinsCache.find((pin) => pin.uuid === otherTab.getAttribute('zen-pin-id'));
actualPin.position = otherTab._tPos; actualPin.position = otherTab._tPos;
await ZenPinnedTabsStorage.savePin(actualPin, false); await ZenPinnedTabsStorage.savePin(actualPin, false);
} }
} }
const actualPin = this._pinsCache.find(pin => pin.uuid === tab.getAttribute("zen-pin-id")); const actualPin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
actualPin.position = tab.position; actualPin.position = tab.position;
await ZenPinnedTabsStorage.savePin(actualPin); await ZenPinnedTabsStorage.savePin(actualPin);
} }
_onTabClick(e) { _onTabClick(e) {
const tab = e.target?.closest("tab"); const tab = e.target?.closest('tab');
if (e.button === 1 && tab) { if (e.button === 1 && tab) {
this._onCloseTabShortcut(e, tab); this._onCloseTabShortcut(e, tab);
} }
} }
async resetPinnedTab(tab) { async resetPinnedTab(tab) {
if (!tab) { if (!tab) {
tab = TabContextMenu.contextTab; tab = TabContextMenu.contextTab;
} }
@ -321,23 +333,23 @@
async replacePinnedUrlWithCurrent() { async replacePinnedUrlWithCurrent() {
const tab = TabContextMenu.contextTab; const tab = TabContextMenu.contextTab;
if (!tab || !tab.pinned || !tab.getAttribute("zen-pin-id")) { if (!tab || !tab.pinned || !tab.getAttribute('zen-pin-id')) {
return; return;
} }
const browser = tab.linkedBrowser; const browser = tab.linkedBrowser;
const pin = this._pinsCache.find(pin => pin.uuid === tab.getAttribute("zen-pin-id")); const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if (!pin) { if (!pin) {
return; return;
} }
const userContextId = tab.getAttribute("usercontextid"); const userContextId = tab.getAttribute('usercontextid');
pin.title = tab.label || browser.contentTitle; pin.title = tab.label || browser.contentTitle;
pin.url = browser.currentURI.spec; pin.url = browser.currentURI.spec;
pin.workspaceUuid = tab.getAttribute("zen-workspace-id"); pin.workspaceUuid = tab.getAttribute('zen-workspace-id');
pin.userContextId = userContextId ? parseInt(userContextId, 10) : 0; pin.userContextId = userContextId ? parseInt(userContextId, 10) : 0;
await ZenPinnedTabsStorage.savePin(pin); await ZenPinnedTabsStorage.savePin(pin);
@ -346,20 +358,19 @@
} }
async _setPinnedAttributes(tab) { async _setPinnedAttributes(tab) {
if (tab.hasAttribute('zen-pin-id')) {
if (tab.hasAttribute("zen-pin-id")) {
return; return;
} }
const browser = tab.linkedBrowser; const browser = tab.linkedBrowser;
const uuid = gZenUIManager.generateUuidv4(); const uuid = gZenUIManager.generateUuidv4();
const userContextId = tab.getAttribute("usercontextid"); const userContextId = tab.getAttribute('usercontextid');
let entry = null; let entry = null;
if(tab.getAttribute("zen-pinned-entry")) { if (tab.getAttribute('zen-pinned-entry')) {
entry = JSON.parse(tab.getAttribute("zen-pinned-entry")); entry = JSON.parse(tab.getAttribute('zen-pinned-entry'));
} }
await ZenPinnedTabsStorage.savePin({ await ZenPinnedTabsStorage.savePin({
@ -367,15 +378,15 @@
title: entry?.title || tab.label || browser.contentTitle, title: entry?.title || tab.label || browser.contentTitle,
url: entry?.url || browser.currentURI.spec, url: entry?.url || browser.currentURI.spec,
containerTabId: userContextId ? parseInt(userContextId, 10) : 0, containerTabId: userContextId ? parseInt(userContextId, 10) : 0,
workspaceUuid: tab.getAttribute("zen-workspace-id"), workspaceUuid: tab.getAttribute('zen-workspace-id'),
isEssential: tab.getAttribute("zen-essential") === "true" isEssential: tab.getAttribute('zen-essential') === 'true',
}); });
tab.setAttribute("zen-pin-id", uuid); tab.setAttribute('zen-pin-id', uuid);
// This is used while migrating old pins to new system - we don't want to refresh when migrating // This is used while migrating old pins to new system - we don't want to refresh when migrating
if (tab.getAttribute("zen-pinned-entry")) { if (tab.getAttribute('zen-pinned-entry')) {
tab.removeAttribute("zen-pinned-entry"); tab.removeAttribute('zen-pinned-entry');
return; return;
} }
const currentWorkspace = await ZenWorkspaces.getActiveWorkspace(); const currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
@ -383,19 +394,19 @@
} }
async _removePinnedAttributes(tab, isClosing = false) { async _removePinnedAttributes(tab, isClosing = false) {
if(!tab.getAttribute("zen-pin-id") || this._temporarilyUnpiningEssential) { if (!tab.getAttribute('zen-pin-id') || this._temporarilyUnpiningEssential) {
this._temporarilyUnpiningEssential = false; this._temporarilyUnpiningEssential = false;
return; return;
} }
await ZenPinnedTabsStorage.removePin(tab.getAttribute("zen-pin-id")); await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
if (!isClosing) { if (!isClosing) {
tab.removeAttribute("zen-pin-id"); tab.removeAttribute('zen-pin-id');
if (!tab.hasAttribute("zen-workspace-id") && ZenWorkspaces.workspaceEnabled) { if (!tab.hasAttribute('zen-workspace-id') && ZenWorkspaces.workspaceEnabled) {
const workspace = await ZenWorkspaces.getActiveWorkspace(); const workspace = await ZenWorkspaces.getActiveWorkspace();
tab.setAttribute("zen-workspace-id", workspace.uuid); tab.setAttribute('zen-workspace-id', workspace.uuid);
} }
} }
const currentWorkspace = await ZenWorkspaces.getActiveWorkspace(); const currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
@ -411,9 +422,7 @@
} }
_onCloseTabShortcut(event, selectedTab = gBrowser.selectedTab) { _onCloseTabShortcut(event, selectedTab = gBrowser.selectedTab) {
if ( if (!selectedTab?.pinned) {
!selectedTab?.pinned
) {
return; return;
} }
@ -454,7 +463,7 @@
const findNextTab = (direction) => const findNextTab = (direction) =>
gBrowser.tabContainer.findNextTab(selectedTab, { gBrowser.tabContainer.findNextTab(selectedTab, {
direction, direction,
filter: tab => !tab.hidden && !tab.pinned, filter: (tab) => !tab.hidden && !tab.pinned,
}); });
let nextTab = findNextTab(1) || findNextTab(-1); let nextTab = findNextTab(1) || findNextTab(-1);
@ -471,12 +480,12 @@
} }
async _resetTabToStoredState(tab) { async _resetTabToStoredState(tab) {
const id = tab.getAttribute("zen-pin-id"); const id = tab.getAttribute('zen-pin-id');
if (!id) { if (!id) {
return; return;
} }
const pin = this._pinsCache.find(pin => pin.uuid === id); const pin = this._pinsCache.find((pin) => pin.uuid === id);
if (!pin) { if (!pin) {
return; return;
} }
@ -484,11 +493,13 @@
const tabState = SessionStore.getTabState(tab); const tabState = SessionStore.getTabState(tab);
const state = JSON.parse(tabState); const state = JSON.parse(tabState);
state.entries = [{ state.entries = [
{
url: pin.url, url: pin.url,
title: pin.title, title: pin.title,
triggeringPrincipal_base64: lazy.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL triggeringPrincipal_base64: lazy.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL,
}]; },
];
state.image = pin.iconUrl || null; state.image = pin.iconUrl || null;
state.index = 0; state.index = 0;
@ -508,7 +519,7 @@
// Convert to base64 // Convert to base64
const base64String = btoa( const base64String = btoa(
Array.from(array) Array.from(array)
.map(b => String.fromCharCode(b)) .map((b) => String.fromCharCode(b))
.join('') .join('')
); );
@ -524,9 +535,9 @@
const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab]; const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
for (let i = 0; i < tabs.length; i++) { for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i]; const tab = tabs[i];
tab.setAttribute("zen-essential", "true"); tab.setAttribute('zen-essential', 'true');
if(tab.hasAttribute("zen-workspace-id")) { if (tab.hasAttribute('zen-workspace-id')) {
tab.removeAttribute("zen-workspace-id"); tab.removeAttribute('zen-workspace-id');
} }
if (tab.pinned) { if (tab.pinned) {
this._temporarilyUnpiningEssential = true; this._temporarilyUnpiningEssential = true;
@ -540,9 +551,9 @@
const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab]; const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
for (let i = 0; i < tabs.length; i++) { for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i]; const tab = tabs[i];
tab.removeAttribute("zen-essential"); tab.removeAttribute('zen-essential');
if (ZenWorkspaces.workspaceEnabled && ZenWorkspaces.getActiveWorkspaceFromCache.uuid) { if (ZenWorkspaces.workspaceEnabled && ZenWorkspaces.getActiveWorkspaceFromCache.uuid) {
tab.setAttribute("zen-workspace-id", ZenWorkspaces.getActiveWorkspaceFromCache.uuid); tab.setAttribute('zen-workspace-id', ZenWorkspaces.getActiveWorkspaceFromCache.uuid);
} }
gBrowser.unpinTab(tab); gBrowser.unpinTab(tab);
} }
@ -590,13 +601,15 @@
return; return;
} }
const isVisible = contextTab.pinned && !contextTab.multiselected; const isVisible = contextTab.pinned && !contextTab.multiselected;
document.getElementById("context_zen-reset-pinned-tab").hidden = !isVisible || !contextTab.getAttribute("zen-pin-id"); document.getElementById('context_zen-reset-pinned-tab').hidden = !isVisible || !contextTab.getAttribute('zen-pin-id');
document.getElementById("context_zen-replace-pinned-url-with-current").hidden = !isVisible; document.getElementById('context_zen-replace-pinned-url-with-current').hidden = !isVisible;
document.getElementById("context_zen-add-essential").hidden = contextTab.getAttribute("zen-essential"); document.getElementById('context_zen-add-essential').hidden = contextTab.getAttribute('zen-essential');
document.getElementById("context_zen-remove-essential").hidden = !contextTab.getAttribute("zen-essential"); document.getElementById('context_zen-remove-essential').hidden = !contextTab.getAttribute('zen-essential');
document.getElementById("context_unpinTab").hidden = document.getElementById("context_unpinTab").hidden || contextTab.getAttribute("zen-essential"); document.getElementById('context_unpinTab').hidden =
document.getElementById("context_unpinSelectedTabs").hidden = document.getElementById("context_unpinSelectedTabs").hidden || contextTab.getAttribute("zen-essential"); document.getElementById('context_unpinTab').hidden || contextTab.getAttribute('zen-essential');
document.getElementById("context_zen-pinned-tab-separator").hidden = !isVisible; document.getElementById('context_unpinSelectedTabs').hidden =
document.getElementById('context_unpinSelectedTabs').hidden || contextTab.getAttribute('zen-essential');
document.getElementById('context_zen-pinned-tab-separator').hidden = !isVisible;
} }
} }

View file

@ -24,7 +24,6 @@ var ZenPinnedTabsStorage = {
) )
`); `);
// Create indices // Create indices
await db.execute(` await db.execute(`
CREATE INDEX IF NOT EXISTS idx_zen_pins_uuid ON zen_pins(uuid) CREATE INDEX IF NOT EXISTS idx_zen_pins_uuid ON zen_pins(uuid)
@ -75,17 +74,21 @@ var ZenPinnedTabsStorage = {
newPosition = pin.position; newPosition = pin.position;
} else { } else {
// Get the maximum position within the same parent group (or null for root level) // Get the maximum position within the same parent group (or null for root level)
const maxPositionResult = await db.execute(` const maxPositionResult = await db.execute(
`
SELECT MAX("position") as max_position SELECT MAX("position") as max_position
FROM zen_pins FROM zen_pins
WHERE COALESCE(parent_uuid, '') = COALESCE(:parent_uuid, '') WHERE COALESCE(parent_uuid, '') = COALESCE(:parent_uuid, '')
`, { parent_uuid: pin.parentUuid || null }); `,
{ parent_uuid: pin.parentUuid || null }
);
const maxPosition = maxPositionResult[0].getResultByName('max_position') || 0; const maxPosition = maxPositionResult[0].getResultByName('max_position') || 0;
newPosition = maxPosition + 1000; newPosition = maxPosition + 1000;
} }
// Insert or replace the pin // Insert or replace the pin
await db.executeCached(` await db.executeCached(
`
INSERT OR REPLACE INTO zen_pins ( INSERT OR REPLACE INTO zen_pins (
uuid, title, url, container_id, workspace_uuid, position, uuid, title, url, container_id, workspace_uuid, position,
is_essential, is_group, parent_uuid, created_at, updated_at is_essential, is_group, parent_uuid, created_at, updated_at
@ -95,7 +98,8 @@ var ZenPinnedTabsStorage = {
COALESCE((SELECT created_at FROM zen_pins WHERE uuid = :uuid), :now), COALESCE((SELECT created_at FROM zen_pins WHERE uuid = :uuid), :now),
:now :now
) )
`, { `,
{
uuid: pin.uuid, uuid: pin.uuid,
title: pin.title, title: pin.title,
url: pin.isGroup ? null : pin.url, url: pin.isGroup ? null : pin.url,
@ -105,16 +109,20 @@ var ZenPinnedTabsStorage = {
is_essential: pin.isEssential || false, is_essential: pin.isEssential || false,
is_group: pin.isGroup || false, is_group: pin.isGroup || false,
parent_uuid: pin.parentUuid || null, parent_uuid: pin.parentUuid || null,
now now,
}); }
);
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid: pin.uuid, uuid: pin.uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
changedUUIDs.add(pin.uuid); changedUUIDs.add(pin.uuid);
await this.updateLastChangeTimestamp(db); await this.updateLastChangeTimestamp(db);
@ -122,7 +130,7 @@ var ZenPinnedTabsStorage = {
}); });
if (notifyObservers) { if (notifyObservers) {
this._notifyPinsChanged("zen-pin-updated", Array.from(changedUUIDs)); this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
} }
}, },
@ -141,17 +149,20 @@ var ZenPinnedTabsStorage = {
position: row.getResultByName('position'), position: row.getResultByName('position'),
isEssential: Boolean(row.getResultByName('is_essential')), isEssential: Boolean(row.getResultByName('is_essential')),
isGroup: Boolean(row.getResultByName('is_group')), isGroup: Boolean(row.getResultByName('is_group')),
parentUuid: row.getResultByName('parent_uuid') parentUuid: row.getResultByName('parent_uuid'),
})); }));
}, },
async getGroupChildren(groupUuid) { async getGroupChildren(groupUuid) {
const db = await PlacesUtils.promiseDBConnection(); const db = await PlacesUtils.promiseDBConnection();
const rows = await db.executeCached(` const rows = await db.executeCached(
`
SELECT * FROM zen_pins SELECT * FROM zen_pins
WHERE parent_uuid = :groupUuid WHERE parent_uuid = :groupUuid
ORDER BY position ASC ORDER BY position ASC
`, { groupUuid }); `,
{ groupUuid }
);
return rows.map((row) => ({ return rows.map((row) => ({
uuid: row.getResultByName('uuid'), uuid: row.getResultByName('uuid'),
@ -162,7 +173,7 @@ var ZenPinnedTabsStorage = {
position: row.getResultByName('position'), position: row.getResultByName('position'),
isEssential: Boolean(row.getResultByName('is_essential')), isEssential: Boolean(row.getResultByName('is_essential')),
isGroup: Boolean(row.getResultByName('is_group')), isGroup: Boolean(row.getResultByName('is_group')),
parentUuid: row.getResultByName('parent_uuid') parentUuid: row.getResultByName('parent_uuid'),
})); }));
}, },
@ -172,10 +183,7 @@ var ZenPinnedTabsStorage = {
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.removePin', async (db) => { await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.removePin', async (db) => {
await db.executeTransaction(async () => { await db.executeTransaction(async () => {
// Get all child UUIDs first for change tracking // Get all child UUIDs first for change tracking
const children = await db.execute( const children = await db.execute(`SELECT uuid FROM zen_pins WHERE parent_uuid = :uuid`, { uuid });
`SELECT uuid FROM zen_pins WHERE parent_uuid = :uuid`,
{ uuid }
);
// Add child UUIDs to changedUUIDs array // Add child UUIDs to changedUUIDs array
for (const child of children) { for (const child of children) {
@ -183,27 +191,24 @@ var ZenPinnedTabsStorage = {
} }
// Delete all children in a single statement // Delete all children in a single statement
await db.execute( await db.execute(`DELETE FROM zen_pins WHERE parent_uuid = :uuid`, { uuid });
`DELETE FROM zen_pins WHERE parent_uuid = :uuid`,
{ uuid }
);
// Delete the pin/group itself // Delete the pin/group itself
await db.execute( await db.execute(`DELETE FROM zen_pins WHERE uuid = :uuid`, { uuid });
`DELETE FROM zen_pins WHERE uuid = :uuid`,
{ uuid }
);
// Record the changes // Record the changes
const now = Math.floor(Date.now() / 1000); const now = Math.floor(Date.now() / 1000);
for (const changedUuid of changedUUIDs) { for (const changedUuid of changedUUIDs) {
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid: changedUuid, uuid: changedUuid,
timestamp: now timestamp: now,
}); }
);
} }
await this.updateLastChangeTimestamp(db); await this.updateLastChangeTimestamp(db);
@ -211,7 +216,7 @@ var ZenPinnedTabsStorage = {
}); });
if (notifyObservers) { if (notifyObservers) {
this._notifyPinsChanged("zen-pin-removed", changedUUIDs); this._notifyPinsChanged('zen-pin-removed', changedUUIDs);
} }
}, },
@ -226,13 +231,16 @@ var ZenPinnedTabsStorage = {
async markChanged(uuid) { async markChanged(uuid) {
await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.markChanged', async (db) => { await PlacesUtils.withConnectionWrapper('ZenPinnedTabsStorage.markChanged', async (db) => {
const now = Date.now(); const now = Date.now();
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid, uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
}); });
}, },
@ -268,21 +276,27 @@ var ZenPinnedTabsStorage = {
for (let i = 0; i < pins.length; i++) { for (let i = 0; i < pins.length; i++) {
const newPosition = (i + 1) * 1000; // Use large increments const newPosition = (i + 1) * 1000; // Use large increments
await db.execute(` await db.execute(
`
UPDATE zen_pins UPDATE zen_pins
SET position = :newPosition SET position = :newPosition
WHERE uuid = :uuid WHERE uuid = :uuid
`, { newPosition, uuid: pins[i].getResultByName('uuid') }); `,
{ newPosition, uuid: pins[i].getResultByName('uuid') }
);
changedUUIDs.add(pins[i].getResultByName('uuid')); changedUUIDs.add(pins[i].getResultByName('uuid'));
} }
}, },
async updateLastChangeTimestamp(db) { async updateLastChangeTimestamp(db) {
const now = Date.now(); const now = Date.now();
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO moz_meta (key, value) INSERT OR REPLACE INTO moz_meta (key, value)
VALUES ('zen_pins_last_change', :now) VALUES ('zen_pins_last_change', :now)
`, { now }); `,
{ now }
);
}, },
async getLastChangeTimestamp() { async getLastChangeTimestamp() {
@ -304,29 +318,35 @@ var ZenPinnedTabsStorage = {
const pin = pins[i]; const pin = pins[i];
const newPosition = (i + 1) * 1000; const newPosition = (i + 1) * 1000;
await db.execute(` await db.execute(
`
UPDATE zen_pins UPDATE zen_pins
SET position = :newPosition SET position = :newPosition
WHERE uuid = :uuid WHERE uuid = :uuid
`, { newPosition, uuid: pin.uuid }); `,
{ newPosition, uuid: pin.uuid }
);
changedUUIDs.add(pin.uuid); changedUUIDs.add(pin.uuid);
// Record the change // Record the change
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_pins_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid: pin.uuid, uuid: pin.uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
} }
await this.updateLastChangeTimestamp(db); await this.updateLastChangeTimestamp(db);
}); });
}); });
this._notifyPinsChanged("zen-pin-updated", Array.from(changedUUIDs)); this._notifyPinsChanged('zen-pin-updated', Array.from(changedUUIDs));
}, },
async __dropTables() { async __dropTables() {
@ -334,7 +354,7 @@ var ZenPinnedTabsStorage = {
await db.execute(`DROP TABLE IF EXISTS zen_pins`); await db.execute(`DROP TABLE IF EXISTS zen_pins`);
await db.execute(`DROP TABLE IF EXISTS zen_pins_changes`); await db.execute(`DROP TABLE IF EXISTS zen_pins_changes`);
}); });
} },
}; };
ZenPinnedTabsStorage.init(); ZenPinnedTabsStorage.init();

View file

@ -1,6 +1,5 @@
{ {
const ZEN_RICE_API = Services.prefs.getStringPref("zen.rice.api.url", ''); const ZEN_RICE_API = Services.prefs.getStringPref('zen.rice.api.url', '');
class ZenRiceCollector { class ZenRiceCollector {
constructor() {} constructor() {}
@ -14,9 +13,13 @@
} }
async gatherAll({ async gatherAll({
userUserChrome = true, userContent = true, userUserChrome = true,
enabledMods = true, preferences = true, userContent = true,
modPrefs = true, workspaceThemes = true } = {}) { enabledMods = true,
preferences = true,
modPrefs = true,
workspaceThemes = true,
} = {}) {
this.clear(); this.clear();
// Get the mods first, as they may be needed for the preferences // Get the mods first, as they may be needed for the preferences
if (enabledMods) { if (enabledMods) {
@ -39,7 +42,7 @@
const path = PathUtils.join(this.profileDir, 'chrome', 'userChrome.css'); const path = PathUtils.join(this.profileDir, 'chrome', 'userChrome.css');
this._userChrome = await IOUtils.readUTF8(path); this._userChrome = await IOUtils.readUTF8(path);
} catch (e) { } catch (e) {
console.warn("[ZenRiceCollector]: Error reading userChrome.css: ", e); console.warn('[ZenRiceCollector]: Error reading userChrome.css: ', e);
return null; return null;
} }
} }
@ -49,7 +52,7 @@
const path = PathUtils.join(this.profileDir, 'chrome', 'userContent.css'); const path = PathUtils.join(this.profileDir, 'chrome', 'userContent.css');
this._userContent = await IOUtils.readUTF8(path); this._userContent = await IOUtils.readUTF8(path);
} catch (e) { } catch (e) {
console.warn("[ZenRiceCollector]: Error reading userContent.css: ", e); console.warn('[ZenRiceCollector]: Error reading userContent.css: ', e);
return null; return null;
} }
} }
@ -85,18 +88,12 @@
'zen.tabs.vertical.right-side', 'zen.tabs.vertical.right-side',
'zen.view.experimental-no-window-controls', 'zen.view.experimental-no-window-controls',
'zen.view.hide-window-controls', 'zen.view.hide-window-controls',
...(gZenOperatingSystemCommonUtils.currentOperatingSystem === "windows" ...(gZenOperatingSystemCommonUtils.currentOperatingSystem === 'windows' ? ['widget.windows.mica'] : []),
? ['widget.windows.mica'] ...(gZenOperatingSystemCommonUtils.currentOperatingSystem === 'macos'
: []
),
...(gZenOperatingSystemCommonUtils.currentOperatingSystem === "macos"
? ['widget.macos.titlebar-blend-mode.behind-window'] ? ['widget.macos.titlebar-blend-mode.behind-window']
: [] : []),
),
];
const stringPrefsToCollect = [
'browser.uiCustomization.state'
]; ];
const stringPrefsToCollect = ['browser.uiCustomization.state'];
for (const pref of boolPrefsToCollect) { for (const pref of boolPrefsToCollect) {
this._preferences[pref] = Services.prefs.getBoolPref(pref); this._preferences[pref] = Services.prefs.getBoolPref(pref);
} }
@ -107,7 +104,7 @@
async gatherWorkspaceThemes() { async gatherWorkspaceThemes() {
const workspaces = (await ZenWorkspaces._workspaces()).workspaces; const workspaces = (await ZenWorkspaces._workspaces()).workspaces;
this._workspaceThemes = workspaces.map(w => w.theme); this._workspaceThemes = workspaces.map((w) => w.theme);
} }
async packRice(...args) { async packRice(...args) {
@ -115,7 +112,7 @@
const rice = { const rice = {
userChrome: this._userChrome, userChrome: this._userChrome,
userContent: this._userContent, userContent: this._userContent,
enabledMods: this._enabledMods?.map(t => t.id), enabledMods: this._enabledMods?.map((t) => t.id),
preferences: this._preferences, preferences: this._preferences,
workspaceThemes: this._workspaceThemes, workspaceThemes: this._workspaceThemes,
}; };
@ -128,12 +125,11 @@
this._collector = new ZenRiceCollector(); this._collector = new ZenRiceCollector();
} }
init() { init() {}
}
get conffettiWrapper() { get conffettiWrapper() {
if (!this.confetti) { if (!this.confetti) {
Services.scriptloader.loadSubScript("chrome://browser/content/zen-vendor/tsparticles.confetti.bundle.min.js", this); Services.scriptloader.loadSubScript('chrome://browser/content/zen-vendor/tsparticles.confetti.bundle.min.js', this);
} }
return this.confetti; return this.confetti;
} }
@ -204,57 +200,54 @@
</vbox> </vbox>
</vbox> </vbox>
`); `);
document.getElementById("zen-main-app-wrapper").appendChild(this._shareDialog); document.getElementById('zen-main-app-wrapper').appendChild(this._shareDialog);
this._shareDialog = document.getElementById("zen-rice-share-dialog-overlay"); this._shareDialog = document.getElementById('zen-rice-share-dialog-overlay');
return this._shareDialog; return this._shareDialog;
} }
get hasAcceptedNotice() { get hasAcceptedNotice() {
return Services.prefs.getBoolPref("zen.rice.share.notice.accepted", false); return Services.prefs.getBoolPref('zen.rice.share.notice.accepted', false);
} }
set hasAcceptedNotice(value) { set hasAcceptedNotice(value) {
Services.prefs.setBoolPref("zen.rice.share.notice.accepted", value); Services.prefs.setBoolPref('zen.rice.share.notice.accepted', value);
} }
openLink(event) { openLink(event) {
event.stopPropagation(); event.stopPropagation();
this.cancel(); this.cancel();
gZenUIManager.openAndChangeToTab("https://docs.zen-browser.app/guides/"); gZenUIManager.openAndChangeToTab('https://docs.zen-browser.app/guides/');
} }
acceptNotice() { acceptNotice() {
this.hasAcceptedNotice = true; this.hasAcceptedNotice = true;
const notice = document.getElementById("zen-rice-share-dialog-notice"); const notice = document.getElementById('zen-rice-share-dialog-notice');
notice.setAttribute("hidden", "true"); notice.setAttribute('hidden', 'true');
this.openShareDialog(); this.openShareDialog();
} }
toggleOptions(event) { toggleOptions(event) {
if (event.originalTarget.closest(".options-header")) { if (event.originalTarget.closest('.options-header')) {
const options = document.getElementById("zen-rice-share-options"); const options = document.getElementById('zen-rice-share-options');
options.setAttribute("zen-collapsed", options.getAttribute("zen-collapsed") === "true" ? "false" : "true"); options.setAttribute('zen-collapsed', options.getAttribute('zen-collapsed') === 'true' ? 'false' : 'true');
} }
this.validateShareDialog(); this.validateShareDialog();
} }
openShareDialog() { openShareDialog() {
window.docShell.treeOwner window.docShell.treeOwner.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIAppWindow).rollupAllPopups();
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIAppWindow)
.rollupAllPopups();
const dialog = this.shareDialog; const dialog = this.shareDialog;
dialog.removeAttribute("hidden"); dialog.removeAttribute('hidden');
if (!this.hasAcceptedNotice) { if (!this.hasAcceptedNotice) {
const notice = document.getElementById("zen-rice-share-dialog-notice"); const notice = document.getElementById('zen-rice-share-dialog-notice');
notice.removeAttribute("hidden"); notice.removeAttribute('hidden');
return; return;
} }
document.getElementById("zen-rice-share-dialog").removeAttribute("hidden"); document.getElementById('zen-rice-share-dialog').removeAttribute('hidden');
document.getElementById("zen-rice-share-dialog-notice").setAttribute("hidden", "true"); document.getElementById('zen-rice-share-dialog-notice').setAttribute('hidden', 'true');
document.getElementById("zen-rice-share-name").focus(); document.getElementById('zen-rice-share-name').focus();
// Initialize the dialog with the current values // Initialize the dialog with the current values
this.validateShareDialog(); this.validateShareDialog();
@ -262,17 +255,17 @@
resetShareDialog() { resetShareDialog() {
const dialog = this.shareDialog; const dialog = this.shareDialog;
dialog.setAttribute("hidden", "true"); dialog.setAttribute('hidden', 'true');
document.getElementById("zen-rice-share-dialog").removeAttribute("animate"); document.getElementById('zen-rice-share-dialog').removeAttribute('animate');
document.getElementById("zen-rice-share-name").value = ""; document.getElementById('zen-rice-share-name').value = '';
document.getElementById("zen-rice-share-author").value = ""; document.getElementById('zen-rice-share-author').value = '';
document.getElementById("zen-rice-share-save").disabled = true; document.getElementById('zen-rice-share-save').disabled = true;
document.getElementById("zen-rice-share-first-form").removeAttribute("fade-out"); document.getElementById('zen-rice-share-first-form').removeAttribute('fade-out');
document.getElementById("zen-rice-share-second-form").setAttribute("hidden", "true"); document.getElementById('zen-rice-share-second-form').setAttribute('hidden', 'true');
document.getElementById("zen-rice-share-second-form").removeAttribute("fade-out"); document.getElementById('zen-rice-share-second-form').removeAttribute('fade-out');
document.getElementById("zen-rice-share-error").setAttribute("hidden", "true"); document.getElementById('zen-rice-share-error').setAttribute('hidden', 'true');
document.getElementById("zen-rice-share-success").setAttribute("hidden", "true"); document.getElementById('zen-rice-share-success').setAttribute('hidden', 'true');
document.getElementById("zen-rice-share-options").setAttribute("zen-collapsed", "true"); document.getElementById('zen-rice-share-options').setAttribute('zen-collapsed', 'true');
// Remove confetti module from memory // Remove confetti module from memory
this.confetti = null; this.confetti = null;
@ -284,12 +277,12 @@
getAllowedRice() { getAllowedRice() {
return { return {
userChrome: document.getElementById("zen-rice-share-include-userchrome").checked, userChrome: document.getElementById('zen-rice-share-include-userchrome').checked,
userContent: document.getElementById("zen-rice-share-include-usercontent").checked, userContent: document.getElementById('zen-rice-share-include-usercontent').checked,
mods: document.getElementById("zen-rice-share-include-mods").checked, mods: document.getElementById('zen-rice-share-include-mods').checked,
modPrefs: document.getElementById("zen-rice-share-include-mod-prefs").checked, modPrefs: document.getElementById('zen-rice-share-include-mod-prefs').checked,
preferences: document.getElementById("zen-rice-share-include-preferences").checked, preferences: document.getElementById('zen-rice-share-include-preferences').checked,
workspaceThemes: document.getElementById("zen-rice-share-include-workspace-themes").checked, workspaceThemes: document.getElementById('zen-rice-share-include-workspace-themes').checked,
}; };
} }
@ -299,37 +292,41 @@
canShareRice() { canShareRice() {
const allowedRice = this.getAllowedRice(); const allowedRice = this.getAllowedRice();
const modsPrefs = document.getElementById("zen-rice-share-include-mod-prefs"); const modsPrefs = document.getElementById('zen-rice-share-include-mod-prefs');
// remove "share mod prefs" if mods are not included // remove "share mod prefs" if mods are not included
if (!allowedRice.mods) { if (!allowedRice.mods) {
allowedRice.modPrefs = false; allowedRice.modPrefs = false;
modsPrefs.disabled = true; modsPrefs.disabled = true;
} }
modsPrefs.disabled = !allowedRice.mods; modsPrefs.disabled = !allowedRice.mods;
return Object.values(allowedRice).some(v => v); return Object.values(allowedRice).some((v) => v);
} }
validateShareDialog() { validateShareDialog() {
const saveButton = document.getElementById("zen-rice-share-save"); const saveButton = document.getElementById('zen-rice-share-save');
const authorInput = document.getElementById("zen-rice-share-author"); const authorInput = document.getElementById('zen-rice-share-author');
const input = document.getElementById("zen-rice-share-name"); const input = document.getElementById('zen-rice-share-name');
saveButton.disabled = !this.canShareRice() || input.value.trim().length < 3 || input.value.trim().length > 30 saveButton.disabled =
|| authorInput.value.trim().length < 3 || authorInput.value.trim().length > 15; !this.canShareRice() ||
input.value.trim().length < 3 ||
input.value.trim().length > 30 ||
authorInput.value.trim().length < 3 ||
authorInput.value.trim().length > 15;
} }
async submit() { async submit() {
const firstForm = document.getElementById("zen-rice-share-first-form"); const firstForm = document.getElementById('zen-rice-share-first-form');
const secondForm = document.getElementById("zen-rice-share-second-form"); const secondForm = document.getElementById('zen-rice-share-second-form');
firstForm.setAttribute("fade-out", "true"); firstForm.setAttribute('fade-out', 'true');
secondForm.removeAttribute("hidden"); secondForm.removeAttribute('hidden');
await this._submit(); await this._submit();
} }
async _submit() { async _submit() {
const allowedRice = this.getAllowedRice(); const allowedRice = this.getAllowedRice();
const rice = await this._collector.packRice(allowedRice); const rice = await this._collector.packRice(allowedRice);
const name = document.getElementById("zen-rice-share-name").value; const name = document.getElementById('zen-rice-share-name').value;
const author = document.getElementById("zen-rice-share-author").value; const author = document.getElementById('zen-rice-share-author').value;
const response = await this._sendRice({ name, author, rice }); const response = await this._sendRice({ name, author, rice });
if (response) { if (response) {
this.showSuccessDialog(response); this.showSuccessDialog(response);
@ -338,20 +335,20 @@
async _sendRice({ name, author, rice }) { async _sendRice({ name, author, rice }) {
const headers = new Headers(); const headers = new Headers();
headers.append("X-Zen-Rice-Name", name); headers.append('X-Zen-Rice-Name', name);
headers.append("X-Zen-Rice-Author", author); headers.append('X-Zen-Rice-Author', author);
headers.append("User-Agent", this.userAgent); headers.append('User-Agent', this.userAgent);
headers.append("Content-Type", "application/json"); headers.append('Content-Type', 'application/json');
headers.append("Accept", "application/json"); headers.append('Accept', 'application/json');
let response; let response;
try { try {
response = await fetch(`${ZEN_RICE_API}/rices`, { response = await fetch(`${ZEN_RICE_API}/rices`, {
method: "POST", method: 'POST',
headers, headers,
body: JSON.stringify(rice), body: JSON.stringify(rice),
}); });
} catch (e) { } catch (e) {
this.showErrorMessage("An error occurred while sharing your rice. Please try again later."); this.showErrorMessage('An error occurred while sharing your rice. Please try again later.');
console.error(e); console.error(e);
return null; return null;
} }
@ -362,7 +359,7 @@
async _verifyResponse(response) { async _verifyResponse(response) {
const json = await response.json(); const json = await response.json();
if (!response.ok) { if (!response.ok) {
const message = json.message || "An error occurred while sharing your rice."; const message = json.message || 'An error occurred while sharing your rice.';
this.showErrorMessage(message); this.showErrorMessage(message);
console.error(json); console.error(json);
return null; return null;
@ -371,20 +368,20 @@
} }
showErrorMessage(message) { showErrorMessage(message) {
const errorBox = document.getElementById("zen-rice-share-error"); const errorBox = document.getElementById('zen-rice-share-error');
errorBox.removeAttribute("hidden"); errorBox.removeAttribute('hidden');
errorBox.querySelector("label").textContent = message; errorBox.querySelector('label').textContent = message;
} }
showSuccessDialog(riceInfo) { showSuccessDialog(riceInfo) {
const { slug, token } = riceInfo; const { slug, token } = riceInfo;
// 'token' is like some sort of password to edit the rice, do NOT expose it // 'token' is like some sort of password to edit the rice, do NOT expose it
setTimeout(() => { setTimeout(() => {
document.getElementById("zen-rice-share-dialog").setAttribute("animate", "true"); document.getElementById('zen-rice-share-dialog').setAttribute('animate', 'true');
const successBox = document.getElementById("zen-rice-share-success"); const successBox = document.getElementById('zen-rice-share-success');
document.getElementById("zen-rice-share-second-form").setAttribute("fade-out", "true"); document.getElementById('zen-rice-share-second-form').setAttribute('fade-out', 'true');
successBox.removeAttribute("hidden"); successBox.removeAttribute('hidden');
const link = document.getElementById("zen-rice-share-success-link"); const link = document.getElementById('zen-rice-share-success-link');
link.value = `${ZEN_RICE_API}/rices/${slug}`; link.value = `${ZEN_RICE_API}/rices/${slug}`;
this.showConffetti(); this.showConffetti();
}, 2000); }, 2000);
@ -422,7 +419,7 @@
} }
openRicePage({ name, id, author }) { openRicePage({ name, id, author }) {
console.log("Opening rice page: ", name, id, author); console.log('Opening rice page: ', name, id, author);
gBrowser.removeTab(gBrowser.selectedTab); gBrowser.removeTab(gBrowser.selectedTab);
} }
} }

View file

@ -38,10 +38,10 @@ var ZenThemesCommon = {
await IOUtils.writeJSON(this.themesDataFile, {}); await IOUtils.writeJSON(this.themesDataFile, {});
this.themes = {}; this.themes = {};
gNotificationBox.appendNotification( gNotificationBox.appendNotification(
"zen-themes-corrupted", 'zen-themes-corrupted',
{ {
label: { "l10n-id": "zen-themes-corrupted" }, label: { 'l10n-id': 'zen-themes-corrupted' },
image: "chrome://browser/skin/notification-icons/persistent-storage-blocked.svg", image: 'chrome://browser/skin/notification-icons/persistent-storage-blocked.svg',
priority: gNotificationBox.PRIORITY_WARNING_HIGH, priority: gNotificationBox.PRIORITY_WARNING_HIGH,
}, },
[] []

View file

@ -303,15 +303,15 @@ var gZenThemesImporter = new (class {
} }
})(); })();
gZenActorsManager.addJSWindowActor("ZenThemeMarketplace", { gZenActorsManager.addJSWindowActor('ZenThemeMarketplace', {
parent: { parent: {
esModuleURI: "chrome://browser/content/zen-components/actors/ZenThemeMarketplaceParent.sys.mjs", esModuleURI: 'chrome://browser/content/zen-components/actors/ZenThemeMarketplaceParent.sys.mjs',
}, },
child: { child: {
esModuleURI: "chrome://browser/content/zen-components/actors/ZenThemeMarketplaceChild.sys.mjs", esModuleURI: 'chrome://browser/content/zen-components/actors/ZenThemeMarketplaceChild.sys.mjs',
events: { events: {
DOMContentLoaded: {}, DOMContentLoaded: {},
}, },
}, },
matches: [...Services.prefs.getStringPref("zen.injections.match-urls").split(","), "about:preferences"], matches: [...Services.prefs.getStringPref('zen.injections.match-urls').split(','), 'about:preferences'],
}); });

View file

@ -41,7 +41,7 @@ class SplitNode extends SplitLeafNode {
} }
set children(children) { set children(children) {
if (children) children.forEach(c => c.parent = this); if (children) children.forEach((c) => (c.parent = this));
this._children = children; this._children = children;
} }
@ -74,17 +74,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
XPCOMUtils.defineLazyPreferenceGetter(this, 'minResizeWidth', 'zen.splitView.min-resize-width', 7); XPCOMUtils.defineLazyPreferenceGetter(this, 'minResizeWidth', 'zen.splitView.min-resize-width', 7);
XPCOMUtils.defineLazyPreferenceGetter(this, '_edgeHoverSize', 'zen.splitView.rearrange-edge-hover-size', 24); XPCOMUtils.defineLazyPreferenceGetter(this, '_edgeHoverSize', 'zen.splitView.rearrange-edge-hover-size', 24);
ChromeUtils.defineLazyGetter( ChromeUtils.defineLazyGetter(this, 'overlay', () => document.getElementById('zen-splitview-overlay'));
this,
'overlay',
() => document.getElementById('zen-splitview-overlay')
);
ChromeUtils.defineLazyGetter( ChromeUtils.defineLazyGetter(this, 'dropZone', () => document.getElementById('zen-splitview-dropzone'));
this,
'dropZone',
() => document.getElementById('zen-splitview-dropzone')
);
window.addEventListener('TabClose', this.handleTabClose.bind(this)); window.addEventListener('TabClose', this.handleTabClose.bind(this));
this.initializeContextMenu(); this.initializeContextMenu();
@ -150,7 +142,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
parent.children.splice(childIndex, 1); parent.children.splice(childIndex, 1);
if (parent.children.length !== 1) { if (parent.children.length !== 1) {
const otherNodeIncrease = 100 / (100 - toRemove.sizeInParent); const otherNodeIncrease = 100 / (100 - toRemove.sizeInParent);
parent.children.forEach(c => c.sizeInParent *= otherNodeIncrease); parent.children.forEach((c) => (c.sizeInParent *= otherNodeIncrease));
return parent; return parent;
} }
// node that is not a leaf cannot have less than 2 children, this makes for better resizing // node that is not a leaf cannot have less than 2 children, this makes for better resizing
@ -164,8 +156,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
parent.parent.children[idx] = leftOverChild; parent.parent.children[idx] = leftOverChild;
} else { } else {
// node cannot have same direction as it's parent // node cannot have same direction as it's parent
leftOverChild.children.forEach(c => { leftOverChild.children.forEach((c) => {
c.sizeInParent *= leftOverChild.sizeInParent / 100 c.sizeInParent *= leftOverChild.sizeInParent / 100;
c.parent = parent.parent; c.parent = parent.parent;
}); });
parent.parent.children.splice(idx, 1, ...leftOverChild.children); parent.parent.children.splice(idx, 1, ...leftOverChild.children);
@ -174,7 +166,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this._removeNodeSplitters(parent, false); this._removeNodeSplitters(parent, false);
return parent.parent; return parent.parent;
} else { } else {
const viewData = Object.values(this._data).find(s => s.layoutTree === parent); const viewData = Object.values(this._data).find((s) => s.layoutTree === parent);
viewData.layoutTree = leftOverChild; viewData.layoutTree = leftOverChild;
leftOverChild.positionToRoot = null; leftOverChild.positionToRoot = null;
leftOverChild.parent = null; leftOverChild.parent = null;
@ -188,26 +180,26 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
* @private * @private
*/ */
_removeNodeSplitters(node, recursive) { _removeNodeSplitters(node, recursive) {
this.getSplitters(node)?.forEach(s => s.remove()); this.getSplitters(node)?.forEach((s) => s.remove());
this._splitNodeToSplitters.delete(node); this._splitNodeToSplitters.delete(node);
if (!recursive) return; if (!recursive) return;
if (node.children) node.children.forEach(c => this._removeNodeSplitters(c)); if (node.children) node.children.forEach((c) => this._removeNodeSplitters(c));
} }
get rearangeActionTarget() { get rearangeActionTarget() {
return document.getElementById("urlbar-container"); return document.getElementById('urlbar-container');
} }
afterRearangeAction() { afterRearangeAction() {
document.getElementById("zenSplitViewModifier").hidePopup(); document.getElementById('zenSplitViewModifier').hidePopup();
ConfirmationHint.show(document.getElementById("zen-split-views-box"), "zen-split-view-modifier-enabled-toast", { ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-enabled-toast', {
descriptionId: "zen-split-view-modifier-enabled-toast-description", descriptionId: 'zen-split-view-modifier-enabled-toast-description',
showDescription: true, showDescription: true,
}); });
} }
afterRearangeRemove() { afterRearangeRemove() {
ConfirmationHint.show(document.getElementById("zen-split-views-box"), "zen-split-view-modifier-disabled-toast"); ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-disabled-toast');
} }
toggleWrapperDisplay(value) { toggleWrapperDisplay(value) {
@ -222,20 +214,20 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this.rearrangeViewEnabled = true; this.rearrangeViewEnabled = true;
this.rearrangeViewView = this.currentView; this.rearrangeViewView = this.currentView;
if (!this._thumnailCanvas) { if (!this._thumnailCanvas) {
this._thumnailCanvas = document.createElement("canvas"); this._thumnailCanvas = document.createElement('canvas');
this._thumnailCanvas.width = 280 * devicePixelRatio; this._thumnailCanvas.width = 280 * devicePixelRatio;
this._thumnailCanvas.height = 140 * devicePixelRatio; this._thumnailCanvas.height = 140 * devicePixelRatio;
} }
const browsers = this._data[this.currentView].tabs.map(t => t.linkedBrowser); const browsers = this._data[this.currentView].tabs.map((t) => t.linkedBrowser);
browsers.forEach(b => { browsers.forEach((b) => {
b.style.pointerEvents = 'none'; b.style.pointerEvents = 'none';
b.style.opacity = '.85'; b.style.opacity = '.85';
}); });
this.tabBrowserPanel.addEventListener('dragstart', this.onBrowserDragStart); this.tabBrowserPanel.addEventListener('dragstart', this.onBrowserDragStart);
this.tabBrowserPanel.addEventListener('dragover', this.onBrowserDragOver); this.tabBrowserPanel.addEventListener('dragover', this.onBrowserDragOver);
this.tabBrowserPanel.addEventListener('drop', this.onBrowserDrop); this.tabBrowserPanel.addEventListener('drop', this.onBrowserDrop);
this.tabBrowserPanel.addEventListener('dragend', this.onBrowserDragEnd) this.tabBrowserPanel.addEventListener('dragend', this.onBrowserDragEnd);
this.tabBrowserPanel.addEventListener('click', this.disableTabRearrangeView); this.tabBrowserPanel.addEventListener('click', this.disableTabRearrangeView);
window.addEventListener('keydown', this.disableTabRearrangeView); window.addEventListener('keydown', this.disableTabRearrangeView);
this.afterRearangeAction(); this.afterRearangeAction();
@ -245,8 +237,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
if (!this.rearrangeViewEnabled) return; if (!this.rearrangeViewEnabled) return;
if (event) { if (event) {
// Click or "ESC" key // Click or "ESC" key
if (event.type === 'click' && event.button !== 0 if ((event.type === 'click' && event.button !== 0) || (event.type === 'keydown' && event.key !== 'Escape')) {
|| event.type === 'keydown' && event.key !== 'Escape') {
return; return;
} }
} }
@ -260,15 +251,15 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this.tabBrowserPanel.removeEventListener('drop', this.onBrowserDrop); this.tabBrowserPanel.removeEventListener('drop', this.onBrowserDrop);
this.tabBrowserPanel.removeEventListener('click', this.disableTabRearrangeView); this.tabBrowserPanel.removeEventListener('click', this.disableTabRearrangeView);
window.removeEventListener('keydown', this.disableTabRearrangeView); window.removeEventListener('keydown', this.disableTabRearrangeView);
const browsers = this._data[this.rearrangeViewView].tabs.map(t => t.linkedBrowser); const browsers = this._data[this.rearrangeViewView].tabs.map((t) => t.linkedBrowser);
browsers.forEach(b => { browsers.forEach((b) => {
b.style.pointerEvents = ''; b.style.pointerEvents = '';
b.style.opacity = ''; b.style.opacity = '';
}); });
this.rearrangeViewEnabled = false; this.rearrangeViewEnabled = false;
this.rearrangeViewView = null; this.rearrangeViewView = null;
this.afterRearangeRemove(); this.afterRearangeRemove();
} };
onBrowserDragStart = (event) => { onBrowserDragStart = (event) => {
if (!this.splitViewActive) return; if (!this.splitViewActive) return;
@ -285,12 +276,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let scale = window.devicePixelRatio; let scale = window.devicePixelRatio;
let canvas = this._dndCanvas; let canvas = this._dndCanvas;
if (!canvas) { if (!canvas) {
this._dndCanvas = canvas = document.createElementNS( this._dndCanvas = canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
"http://www.w3.org/1999/xhtml", canvas.style.width = '100%';
"canvas" canvas.style.height = '100%';
);
canvas.style.width = "100%";
canvas.style.height = "100%";
} }
canvas.width = 160 * scale; canvas.width = 160 * scale;
@ -298,15 +286,15 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let toDrag = canvas; let toDrag = canvas;
let dragImageOffset = -16; let dragImageOffset = -16;
if (gMultiProcessBrowser) { if (gMultiProcessBrowser) {
var context = canvas.getContext("2d"); var context = canvas.getContext('2d');
context.fillStyle = "white"; context.fillStyle = 'white';
context.fillRect(0, 0, canvas.width, canvas.height); context.fillRect(0, 0, canvas.width, canvas.height);
let captureListener; let captureListener;
let platform = AppConstants.platform; let platform = AppConstants.platform;
// On Windows and Mac we can update the drag image during a drag // On Windows and Mac we can update the drag image during a drag
// using updateDragImage. On Linux, we can use a panel. // using updateDragImage. On Linux, we can use a panel.
if (platform === "win" || platform === "macosx") { if (platform === 'win' || platform === 'macosx') {
captureListener = function () { captureListener = function () {
dt.updateDragImage(canvas, dragImageOffset, dragImageOffset); dt.updateDragImage(canvas, dragImageOffset, dragImageOffset);
}; };
@ -316,15 +304,12 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
// the pointer while a dnd session is on. // the pointer while a dnd session is on.
if (!this._dndPanel) { if (!this._dndPanel) {
this._dndCanvas = canvas; this._dndCanvas = canvas;
this._dndPanel = document.createXULElement("panel"); this._dndPanel = document.createXULElement('panel');
this._dndPanel.className = "dragfeedback-tab"; this._dndPanel.className = 'dragfeedback-tab';
this._dndPanel.setAttribute("type", "drag"); this._dndPanel.setAttribute('type', 'drag');
let wrapper = document.createElementNS( let wrapper = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
"http://www.w3.org/1999/xhtml", wrapper.style.width = '160px';
"div" wrapper.style.height = '90px';
);
wrapper.style.width = "160px";
wrapper.style.height = "90px";
wrapper.appendChild(canvas); wrapper.appendChild(canvas);
this._dndPanel.appendChild(wrapper); this._dndPanel.appendChild(wrapper);
document.documentElement.appendChild(this._dndPanel); document.documentElement.appendChild(this._dndPanel);
@ -335,18 +320,16 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
// since we can update the image during the dnd. // since we can update the image during the dnd.
PageThumbs.captureToCanvas(browser, canvas) PageThumbs.captureToCanvas(browser, canvas)
.then(captureListener) .then(captureListener)
.catch(e => console.error(e)); .catch((e) => console.error(e));
} else { } else {
// For the non e10s case we can just use PageThumbs // For the non e10s case we can just use PageThumbs
// sync, so let's use the canvas for setDragImage. // sync, so let's use the canvas for setDragImage.
PageThumbs.captureToCanvas(browser, canvas).catch(e => PageThumbs.captureToCanvas(browser, canvas).catch((e) => console.error(e));
console.error(e)
);
dragImageOffset = dragImageOffset * scale; dragImageOffset = dragImageOffset * scale;
} }
dt.setDragImage(toDrag, dragImageOffset, dragImageOffset); dt.setDragImage(toDrag, dragImageOffset, dragImageOffset);
return true; return true;
} };
onBrowserDragOver = (event) => { onBrowserDragOver = (event) => {
event.preventDefault(); event.preventDefault();
@ -371,23 +354,22 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
if (hoverSide !== 'center') { if (hoverSide !== 'center') {
const isVertical = hoverSide === 'top' || hoverSide === 'bottom'; const isVertical = hoverSide === 'top' || hoverSide === 'bottom';
const browserSize = 100 - (isVertical ? posToRoot.top + posToRoot.bottom : posToRoot.right + posToRoot.left); const browserSize = 100 - (isVertical ? posToRoot.top + posToRoot.bottom : posToRoot.right + posToRoot.left);
const reduce= browserSize * .5; const reduce = browserSize * 0.5;
posToRoot[this._oppositeSide(hoverSide)] += reduce; posToRoot[this._oppositeSide(hoverSide)] += reduce;
} }
const newInset = const newInset = `${posToRoot.top}% ${posToRoot.right}% ${posToRoot.bottom}% ${posToRoot.left}%`;
`${posToRoot.top}% ${posToRoot.right}% ${posToRoot.bottom}% ${posToRoot.left}%`;
if (this.dropZone.style.inset !== newInset) { if (this.dropZone.style.inset !== newInset) {
window.requestAnimationFrame(() => this.dropZone.style.inset = newInset); window.requestAnimationFrame(() => (this.dropZone.style.inset = newInset));
}
} }
};
onBrowserDragEnd = (event) => { onBrowserDragEnd = (event) => {
this.dropZone.removeAttribute('enabled'); this.dropZone.removeAttribute('enabled');
const draggingBrowser = this._draggingTab.linkedBrowser; const draggingBrowser = this._draggingTab.linkedBrowser;
draggingBrowser.style.opacity = '.85'; draggingBrowser.style.opacity = '.85';
this._draggingTab = null; this._draggingTab = null;
} };
_oppositeSide(side) { _oppositeSide(side) {
if (side === 'top') return 'bottom'; if (side === 'top') return 'bottom';
@ -397,8 +379,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
} }
calculateHoverSide(x, y, elementRect) { calculateHoverSide(x, y, elementRect) {
const hPixelHoverSize = (elementRect.right - elementRect.left) * this._edgeHoverSize / 100; const hPixelHoverSize = ((elementRect.right - elementRect.left) * this._edgeHoverSize) / 100;
const vPixelHoverSize = (elementRect.bottom - elementRect.top) * this._edgeHoverSize / 100; const vPixelHoverSize = ((elementRect.bottom - elementRect.top) * this._edgeHoverSize) / 100;
if (x <= elementRect.left + hPixelHoverSize) return 'left'; if (x <= elementRect.left + hPixelHoverSize) return 'left';
if (x > elementRect.right - hPixelHoverSize) return 'right'; if (x > elementRect.right - hPixelHoverSize) return 'right';
if (y <= elementRect.top + vPixelHoverSize) return 'top'; if (y <= elementRect.top + vPixelHoverSize) return 'top';
@ -412,9 +394,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
const droppedTab = this._draggingTab; const droppedTab = this._draggingTab;
if (!droppedTab) return; if (!droppedTab) return;
const droppedOnTab = gBrowser.getTabForBrowser( const droppedOnTab = gBrowser.getTabForBrowser(event.target.querySelector('browser'));
event.target.querySelector('browser')
);
if (droppedTab === droppedOnTab) return; if (droppedTab === droppedOnTab) return;
const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserDroppedOn.getBoundingClientRect()); const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserDroppedOn.getBoundingClientRect());
@ -426,9 +406,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
return; return;
} }
this.removeNode(droppedSplitNode); this.removeNode(droppedSplitNode);
this.splitIntoNode(droppedOnSplitNode, droppedSplitNode, hoverSide, .5); this.splitIntoNode(droppedOnSplitNode, droppedSplitNode, hoverSide, 0.5);
this.activateSplitView(this._data[this.currentView], true); this.activateSplitView(this._data[this.currentView], true);
} };
/** /**
* *
@ -470,7 +450,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
const nodeIndex = node.parent.children.indexOf(node); const nodeIndex = node.parent.children.indexOf(node);
node.parent.children[nodeIndex] = newParent; node.parent.children[nodeIndex] = newParent;
} else { } else {
const viewData = Object.values(this._data).find(s => s.layoutTree === node); const viewData = Object.values(this._data).find((s) => s.layoutTree === node);
viewData.layoutTree = newParent; viewData.layoutTree = newParent;
} }
newParent.addChild(node); newParent.addChild(node);
@ -595,7 +575,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
* Splits a link in a new tab. * Splits a link in a new tab.
*/ */
splitLinkInNewTab() { splitLinkInNewTab() {
const url = window.gContextMenu.linkURL || window.gContextMenu.mediaURL || window.gContextMenu.contentData.docLocation || window.gContextMenu.target.ownerDocument.location.href; const url =
window.gContextMenu.linkURL ||
window.gContextMenu.mediaURL ||
window.gContextMenu.contentData.docLocation ||
window.gContextMenu.target.ownerDocument.location.href;
const currentTab = window.gBrowser.selectedTab; const currentTab = window.gBrowser.selectedTab;
const newTab = this.openAndSwitchToTab(url); const newTab = this.openAndSwitchToTab(url);
this.splitTabs([currentTab, newTab]); this.splitTabs([currentTab, newTab]);
@ -656,8 +640,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
if (existingSplitTab) { if (existingSplitTab) {
const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab)); const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab));
const group = this._data[groupIndex]; const group = this._data[groupIndex];
const gridTypeChange = gridType && (group.gridType !== gridType); const gridTypeChange = gridType && group.gridType !== gridType;
const newTabsAdded = tabs.find(t => !group.tabs.includes(t)); const newTabsAdded = tabs.find((t) => !group.tabs.includes(t));
if (gridTypeChange || !newTabsAdded) { if (gridTypeChange || !newTabsAdded) {
// reset layout // reset layout
group.gridType = gridType; group.gridType = gridType;
@ -680,7 +664,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
tabs, tabs,
gridType, gridType,
layoutTree: this.calculateLayoutTree(tabs, gridType), layoutTree: this.calculateLayoutTree(tabs, gridType),
} };
this._data.push(splitData); this._data.push(splitData);
window.gBrowser.selectedTab = tabs[0]; window.gBrowser.selectedTab = tabs[0];
this.activateSplitView(splitData); this.activateSplitView(splitData);
@ -688,7 +672,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
addTabToSplit(tab, splitNode) { addTabToSplit(tab, splitNode) {
const reduce = splitNode.children.length / (splitNode.children.length + 1); const reduce = splitNode.children.length / (splitNode.children.length + 1);
splitNode.children.forEach(c => c.sizeInParent *= reduce); splitNode.children.forEach((c) => (c.sizeInParent *= reduce));
splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100)); splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100));
} }
@ -757,10 +741,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let rootNode; let rootNode;
if (gridType === 'vsep' || (tabs.length === 2 && gridType === 'grid')) { if (gridType === 'vsep' || (tabs.length === 2 && gridType === 'grid')) {
rootNode = new SplitNode('row'); rootNode = new SplitNode('row');
rootNode.children = tabs.map(tab => new SplitLeafNode(tab, 100 / tabs.length)); rootNode.children = tabs.map((tab) => new SplitLeafNode(tab, 100 / tabs.length));
} else if (gridType === 'hsep') { } else if (gridType === 'hsep') {
rootNode = new SplitNode('column'); rootNode = new SplitNode('column');
rootNode.children = tabs.map(tab => new SplitLeafNode(tab, 100 / tabs.length)); rootNode.children = tabs.map((tab) => new SplitLeafNode(tab, 100 / tabs.length));
} else if (gridType === 'grid') { } else if (gridType === 'grid') {
rootNode = new SplitNode('row'); rootNode = new SplitNode('row');
const rowWidth = 100 / Math.ceil(tabs.length / 2); const rowWidth = 100 / Math.ceil(tabs.length / 2);
@ -808,8 +792,8 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
return; return;
} }
const rootToNodeWidthRatio = ((100 - nodeRootPosition.right) - nodeRootPosition.left) / 100; const rootToNodeWidthRatio = (100 - nodeRootPosition.right - nodeRootPosition.left) / 100;
const rootToNodeHeightRatio = ((100 - nodeRootPosition.bottom) - nodeRootPosition.top) / 100; const rootToNodeHeightRatio = (100 - nodeRootPosition.bottom - nodeRootPosition.top) / 100;
const splittersNeeded = splitNode.children.length - 1; const splittersNeeded = splitNode.children.length - 1;
const currentSplitters = this.getSplitters(splitNode, splittersNeeded); const currentSplitters = this.getSplitters(splitNode, splittersNeeded);
@ -817,7 +801,12 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let leftOffset = nodeRootPosition.left; let leftOffset = nodeRootPosition.left;
let topOffset = nodeRootPosition.top; let topOffset = nodeRootPosition.top;
splitNode.children.forEach((childNode, i) => { splitNode.children.forEach((childNode, i) => {
const childRootPosition = {top: topOffset, right: 100 - (leftOffset + childNode.widthInParent * rootToNodeWidthRatio), bottom: 100 - (topOffset + childNode.heightInParent * rootToNodeHeightRatio), left: leftOffset}; const childRootPosition = {
top: topOffset,
right: 100 - (leftOffset + childNode.widthInParent * rootToNodeWidthRatio),
bottom: 100 - (topOffset + childNode.heightInParent * rootToNodeHeightRatio),
left: leftOffset,
};
childNode.positionToRoot = childRootPosition; childNode.positionToRoot = childRootPosition;
this.applyGridLayout(childNode); this.applyGridLayout(childNode);
@ -849,7 +838,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
splitter.className = 'zen-split-view-splitter'; splitter.className = 'zen-split-view-splitter';
splitter.setAttribute('orient', orient); splitter.setAttribute('orient', orient);
splitter.setAttribute('gridIdx', idx); splitter.setAttribute('gridIdx', idx);
this.overlay.insertAdjacentElement("afterbegin", splitter); this.overlay.insertAdjacentElement('afterbegin', splitter);
splitter.addEventListener('mousedown', this.handleSplitterMouseDown); splitter.addEventListener('mousedown', this.handleSplitterMouseDown);
return splitter; return splitter;
@ -863,13 +852,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let currentSplitters = this._splitNodeToSplitters.get(parentNode) || []; let currentSplitters = this._splitNodeToSplitters.get(parentNode) || [];
if (!splittersNeeded || currentSplitters.length === splittersNeeded) return currentSplitters; if (!splittersNeeded || currentSplitters.length === splittersNeeded) return currentSplitters;
for (let i = currentSplitters?.length || 0; i < splittersNeeded; i++) { for (let i = currentSplitters?.length || 0; i < splittersNeeded; i++) {
currentSplitters.push( currentSplitters.push(this.createSplitter(parentNode.direction === 'column' ? 'horizontal' : 'vertical', parentNode, i));
this.createSplitter(parentNode.direction === 'column' ? 'horizontal' : 'vertical', parentNode, i)
);
currentSplitters[i].parentSplitNode = parentNode; currentSplitters[i].parentSplitNode = parentNode;
} }
if (currentSplitters.length > splittersNeeded) { if (currentSplitters.length > splittersNeeded) {
currentSplitters.slice(splittersNeeded - currentSplitters.length).forEach(s => s.remove()); currentSplitters.slice(splittersNeeded - currentSplitters.length).forEach((s) => s.remove());
currentSplitters = currentSplitters.slice(0, splittersNeeded); currentSplitters = currentSplitters.slice(0, splittersNeeded);
} }
this._splitNodeToSplitters.set(parentNode, currentSplitters); this._splitNodeToSplitters.set(parentNode, currentSplitters);
@ -877,7 +864,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
} }
removeSplitters() { removeSplitters() {
[...this.overlay.children].filter(c => c.classList.contains('zen-split-view-splitter')).forEach(s => s.remove()); [...this.overlay.children].filter((c) => c.classList.contains('zen-split-view-splitter')).forEach((s) => s.remove());
this._splitNodeToSplitters.clear(); this._splitNodeToSplitters.clear();
} }
@ -928,17 +915,21 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let rootToNodeSize; let rootToNodeSize;
if (isVertical) rootToNodeSize = 100 / (100 - splitNode.positionToRoot.right - splitNode.positionToRoot.left); if (isVertical) rootToNodeSize = 100 / (100 - splitNode.positionToRoot.right - splitNode.positionToRoot.left);
else rootToNodeSize = 100 / (100 - splitNode.positionToRoot.bottom - splitNode.positionToRoot.top); else rootToNodeSize = 100 / (100 - splitNode.positionToRoot.bottom - splitNode.positionToRoot.top);
const originalSizes = splitNode.children.map(c => c.sizeInParent); const originalSizes = splitNode.children.map((c) => c.sizeInParent);
const dragFunc = (dEvent) => { const dragFunc = (dEvent) => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
originalSizes.forEach((s, i) => splitNode.children[i].sizeInParent = s); // reset changes originalSizes.forEach((s, i) => (splitNode.children[i].sizeInParent = s)); // reset changes
const movement = dEvent[clientAxis] - startPosition; const movement = dEvent[clientAxis] - startPosition;
let movementPercent = (movement / this.tabBrowserPanel.getBoundingClientRect()[dimension] * rootToNodeSize) * 100; let movementPercent = (movement / this.tabBrowserPanel.getBoundingClientRect()[dimension]) * rootToNodeSize * 100;
let reducingMovement = Math.max(movementPercent, -movementPercent); let reducingMovement = Math.max(movementPercent, -movementPercent);
for (let i = gridIdx + (movementPercent < 0 ? 0 : 1); 0 <= i && i < originalSizes.length; i += movementPercent < 0 ? -1 : 1) { for (
let i = gridIdx + (movementPercent < 0 ? 0 : 1);
0 <= i && i < originalSizes.length;
i += movementPercent < 0 ? -1 : 1
) {
const current = originalSizes[i]; const current = originalSizes[i];
const newSize = Math.max(this.minResizeWidth, current - reducingMovement); const newSize = Math.max(this.minResizeWidth, current - reducingMovement);
splitNode.children[i].sizeInParent = newSize; splitNode.children[i].sizeInParent = newSize;
@ -951,16 +942,20 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
splitNode.children[increaseIndex].sizeInParent = originalSizes[increaseIndex] + increasingMovement; splitNode.children[increaseIndex].sizeInParent = originalSizes[increaseIndex] + increasingMovement;
this.applyGridLayout(splitNode); this.applyGridLayout(splitNode);
}); });
} };
setCursor(isVertical ? 'ew-resize' : 'ns-resize'); setCursor(isVertical ? 'ew-resize' : 'ns-resize');
document.addEventListener('mousemove', dragFunc); document.addEventListener('mousemove', dragFunc);
document.addEventListener('mouseup', () => { document.addEventListener(
'mouseup',
() => {
document.removeEventListener('mousemove', dragFunc); document.removeEventListener('mousemove', dragFunc);
setCursor('auto'); setCursor('auto');
this.tabBrowserPanel.removeAttribute('zen-split-resizing'); this.tabBrowserPanel.removeAttribute('zen-split-resizing');
}, {once: true}); },
} { once: true }
);
};
/** /**
* Sets the docshell state for the tabs. * Sets the docshell state for the tabs.

View file

@ -9,16 +9,16 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
_swipeState = { _swipeState = {
isGestureActive: true, isGestureActive: true,
cumulativeDelta: 0, cumulativeDelta: 0,
direction: null direction: null,
}; };
_hoveringSidebar = false; _hoveringSidebar = false;
_lastScrollTime = 0; _lastScrollTime = 0;
bookmarkMenus = [ bookmarkMenus = [
"PlacesToolbar", 'PlacesToolbar',
"bookmarks-menu-button", 'bookmarks-menu-button',
"BMB_bookmarksToolbar", 'BMB_bookmarksToolbar',
"BMB_unsortedBookmarks", 'BMB_unsortedBookmarks',
"BMB_mobileBookmarks" 'BMB_mobileBookmarks',
]; ];
async init() { async init() {
@ -29,24 +29,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
this.ownerWindow = window; this.ownerWindow = window;
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(this, 'activationMethod', 'zen.workspaces.scroll-modifier-key', 'ctrl');
this, XPCOMUtils.defineLazyPreferenceGetter(this, 'naturalScroll', 'zen.workspaces.natural-scroll', true);
'activationMethod', XPCOMUtils.defineLazyPreferenceGetter(this, 'shouldWrapAroundNavigation', 'zen.workspaces.wrap-around-navigation', true);
'zen.workspaces.scroll-modifier-key',
'ctrl',
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
'naturalScroll',
'zen.workspaces.natural-scroll',
true
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
'shouldWrapAroundNavigation',
'zen.workspaces.wrap-around-navigation',
true
);
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
this, this,
'shouldShowIconStrip', 'shouldShowIconStrip',
@ -90,11 +75,14 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
Services.obs.addObserver(this, 'weave:engine:sync:finish'); Services.obs.addObserver(this, 'weave:engine:sync:finish');
Services.obs.addObserver(async function observe(subject) { Services.obs.addObserver(
async function observe(subject) {
this._workspaceBookmarksCache = null; this._workspaceBookmarksCache = null;
await this.workspaceBookmarks(); await this.workspaceBookmarks();
this._invalidateBookmarkContainers(); this._invalidateBookmarkContainers();
}.bind(this), "workspace-bookmarks-updated"); }.bind(this),
'workspace-bookmarks-updated'
);
} }
initializeWorkspaceNavigation() { initializeWorkspaceNavigation() {
@ -104,13 +92,13 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
_setupAppCommandHandlers() { _setupAppCommandHandlers() {
// Remove existing handler temporarily - this is needed so that _handleAppCommand is called before the original // Remove existing handler temporarily - this is needed so that _handleAppCommand is called before the original
window.removeEventListener("AppCommand", HandleAppCommandEvent, true); window.removeEventListener('AppCommand', HandleAppCommandEvent, true);
// Add our handler first // Add our handler first
window.addEventListener("AppCommand", this._handleAppCommand.bind(this), true); window.addEventListener('AppCommand', this._handleAppCommand.bind(this), true);
// Re-add original handler // Re-add original handler
window.addEventListener("AppCommand", HandleAppCommandEvent, true); window.addEventListener('AppCommand', HandleAppCommandEvent, true);
} }
_handleAppCommand(event) { _handleAppCommand(event) {
@ -121,12 +109,12 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const direction = this.naturalScroll ? -1 : 1; const direction = this.naturalScroll ? -1 : 1;
// event is forward or back // event is forward or back
switch (event.command) { switch (event.command) {
case "Forward": case 'Forward':
this.changeWorkspaceShortcut(1 * direction); this.changeWorkspaceShortcut(1 * direction);
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.preventDefault(); event.preventDefault();
break; break;
case "Back": case 'Back':
this.changeWorkspaceShortcut(-1 * direction); this.changeWorkspaceShortcut(-1 * direction);
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.preventDefault(); event.preventDefault();
@ -148,7 +136,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const scrollCooldown = 200; // Milliseconds to wait before allowing another scroll const scrollCooldown = 200; // Milliseconds to wait before allowing another scroll
const scrollThreshold = 2; // Minimum scroll delta to trigger workspace change const scrollThreshold = 2; // Minimum scroll delta to trigger workspace change
toolbox.addEventListener('wheel', async (event) => { toolbox.addEventListener(
'wheel',
async (event) => {
if (!this.workspaceEnabled) return; if (!this.workspaceEnabled) return;
// Only process non-gesture scrolls // Only process non-gesture scrolls
@ -159,7 +149,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
//if the scroll is vertical this checks that a modifier key is used before proceeding //if the scroll is vertical this checks that a modifier key is used before proceeding
if (isVerticalScroll) { if (isVerticalScroll) {
const activationKeyMap = { const activationKeyMap = {
ctrl: event.ctrlKey, ctrl: event.ctrlKey,
alt: event.altKey, alt: event.altKey,
@ -186,14 +175,16 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this.changeWorkspaceShortcut(rawDirection * direction); this.changeWorkspaceShortcut(rawDirection * direction);
this._lastScrollTime = currentTime; this._lastScrollTime = currentTime;
}, { passive: true }); },
{ passive: true }
);
} }
initializeGestureHandlers() { initializeGestureHandlers() {
const elements = [ const elements = [
document.getElementById('navigator-toolbox'), document.getElementById('navigator-toolbox'),
// event handlers do not work on elements inside shadow DOM so we need to attach them directly // event handlers do not work on elements inside shadow DOM so we need to attach them directly
document.getElementById("tabbrowser-arrowscrollbox").shadowRoot.querySelector("scrollbox"), document.getElementById('tabbrowser-arrowscrollbox').shadowRoot.querySelector('scrollbox'),
]; ];
// Attach gesture handlers to each element // Attach gesture handlers to each element
@ -233,7 +224,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._swipeState = { this._swipeState = {
isGestureActive: true, isGestureActive: true,
cumulativeDelta: 0, cumulativeDelta: 0,
direction: null direction: null,
}; };
} }
@ -261,7 +252,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
let rawDirection = moveForward ? 1 : -1; let rawDirection = moveForward ? 1 : -1;
if (this._swipeState.direction) { if (this._swipeState.direction) {
let direction = this.naturalScroll ? -1 : 1; let direction = this.naturalScroll ? -1 : 1;
this.changeWorkspaceShortcut(rawDirection * direction); this.changeWorkspaceShortcut(rawDirection * direction);
} }
@ -270,7 +260,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._swipeState = { this._swipeState = {
isGestureActive: false, isGestureActive: false,
cumulativeDelta: 0, cumulativeDelta: 0,
direction: null direction: null,
}; };
} }
@ -450,9 +440,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const shouldOpenNewTabIfLastUnpinnedTabIsClosed = this.shouldOpenNewTabIfLastUnpinnedTabIsClosed; const shouldOpenNewTabIfLastUnpinnedTabIsClosed = this.shouldOpenNewTabIfLastUnpinnedTabIsClosed;
let tabs = gBrowser.tabs.filter(t => let tabs = gBrowser.tabs.filter(
(t) =>
t.getAttribute('zen-workspace-id') === workspaceID && t.getAttribute('zen-workspace-id') === workspaceID &&
(!shouldOpenNewTabIfLastUnpinnedTabIsClosed ||!t.pinned || t.getAttribute("pending") !== "true") (!shouldOpenNewTabIfLastUnpinnedTabIsClosed || !t.pinned || t.getAttribute('pending') !== 'true')
); );
if (tabs.length === 1 && tabs[0] === tab) { if (tabs.length === 1 && tabs[0] === tab) {
@ -479,7 +470,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
searchIcons(input, icons) { searchIcons(input, icons) {
input = input.toLowerCase(); input = input.toLowerCase();
if ((input === ':') || (input === '')) { if (input === ':' || input === '') {
return icons; return icons;
} }
const emojiScores = []; const emojiScores = [];
@ -492,8 +483,8 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
let alignmentScore = -1; let alignmentScore = -1;
let normalizedEmojiName = currentEmoji[1].toLowerCase(); let normalizedEmojiName = currentEmoji[1].toLowerCase();
let keywordList = currentEmoji[2].split(',').map(keyword => keyword.trim().toLowerCase()); let keywordList = currentEmoji[2].split(',').map((keyword) => keyword.trim().toLowerCase());
if (input[0] === ":") { if (input[0] === ':') {
let searchTerm = input.slice(1); let searchTerm = input.slice(1);
let nameMatchIndex = normalizedEmojiName.indexOf(searchTerm); let nameMatchIndex = normalizedEmojiName.indexOf(searchTerm);
@ -508,7 +499,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (nameMatchIndex !== -1) { if (nameMatchIndex !== -1) {
if (nameMatchIndex === 0) { if (nameMatchIndex === 0) {
alignmentScore = calculateSearchScore(input.length, normalizedEmojiName.length, 150); alignmentScore = calculateSearchScore(input.length, normalizedEmojiName.length, 150);
} else if (input[input.length - 1] !== " ") { } else if (input[input.length - 1] !== ' ') {
alignmentScore += calculateSearchScore(input.length, normalizedEmojiName.length, 40); alignmentScore += calculateSearchScore(input.length, normalizedEmojiName.length, 40);
} }
} }
@ -517,7 +508,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (keywordMatchIndex !== -1) { if (keywordMatchIndex !== -1) {
if (keywordMatchIndex === 0) { if (keywordMatchIndex === 0) {
alignmentScore += calculateSearchScore(input.length, keyword.length, 50); alignmentScore += calculateSearchScore(input.length, keyword.length, 50);
} else if (input[input.length - 1] !== " ") { } else if (input[input.length - 1] !== ' ') {
alignmentScore += calculateSearchScore(input.length, keyword.length, 5); alignmentScore += calculateSearchScore(input.length, keyword.length, 5);
} }
} }
@ -526,7 +517,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
//if match score is not -1, add it //if match score is not -1, add it
if (alignmentScore !== -1) { if (alignmentScore !== -1) {
emojiScores.push({ "emoji": currentEmoji[0], "score": alignmentScore }); emojiScores.push({ emoji: currentEmoji[0], score: alignmentScore });
} }
} }
// Sort the emojis by their score in descending order // Sort the emojis by their score in descending order
@ -534,7 +525,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
// Return the emojis in the order of their rank // Return the emojis in the order of their rank
let filteredEmojiScores = emojiScores; let filteredEmojiScores = emojiScores;
return filteredEmojiScores.map(score => score.emoji); return filteredEmojiScores.map((score) => score.emoji);
} }
resetWorkspaceIconSearch() { resetWorkspaceIconSearch() {
@ -586,14 +577,12 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
const buttons = Array.from(container.querySelectorAll('.toolbarbutton-1')); const buttons = Array.from(container.querySelectorAll('.toolbarbutton-1'));
buttons.forEach(button => button.style.display = 'none'); buttons.forEach((button) => (button.style.display = 'none'));
const filteredIcons = this.searchIcons(query, this.emojis); const filteredIcons = this.searchIcons(query, this.emojis);
filteredIcons.forEach(emoji => { filteredIcons.forEach((emoji) => {
const matchingButton = buttons.find(button => const matchingButton = buttons.find((button) => button.getAttribute('label') === emoji);
button.getAttribute('label') === emoji
);
if (matchingButton) { if (matchingButton) {
matchingButton.style.display = ''; matchingButton.style.display = '';
container.appendChild(matchingButton); container.appendChild(matchingButton);
@ -1020,11 +1009,11 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (!this.workspaceEnabled) { if (!this.workspaceEnabled) {
return; return;
} }
let target = event.target.closest("#zen-current-workspace-indicator") || document.getElementById('zen-workspaces-button'); let target = event.target.closest('#zen-current-workspace-indicator') || document.getElementById('zen-workspaces-button');
let panel = document.getElementById('PanelUI-zen-workspaces'); let panel = document.getElementById('PanelUI-zen-workspaces');
await this._propagateWorkspaceData({ await this._propagateWorkspaceData({
ignoreStrip: true, ignoreStrip: true,
clearCache: false clearCache: false,
}); });
PanelMultiView.openPopup(panel, target, { PanelMultiView.openPopup(panel, target, {
position: 'bottomright topright', position: 'bottomright topright',
@ -1197,7 +1186,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
document.documentElement.setAttribute('zen-workspace-id', window.uuid); document.documentElement.setAttribute('zen-workspace-id', window.uuid);
let tabCount = 0; let tabCount = 0;
for (let tab of gBrowser.tabs) { for (let tab of gBrowser.tabs) {
const isEssential = tab.getAttribute("zen-essential") === "true"; const isEssential = tab.getAttribute('zen-essential') === 'true';
if (!tab.hasAttribute('zen-workspace-id') && !tab.pinned && !isEssential) { if (!tab.hasAttribute('zen-workspace-id') && !tab.pinned && !isEssential) {
tab.setAttribute('zen-workspace-id', window.uuid); tab.setAttribute('zen-workspace-id', window.uuid);
tabCount++; tabCount++;
@ -1310,9 +1299,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
// Animate acordingly // Animate acordingly
if (previousWorkspace && !this._animatingChange) { if (previousWorkspace && !this._animatingChange) {
// we want to know if we are moving forward or backward in sense of animation // we want to know if we are moving forward or backward in sense of animation
let isNextWorkspace = onInit || let isNextWorkspace =
(workspaces.workspaces.findIndex((w) => w.uuid === previousWorkspace.uuid) onInit ||
< workspaces.workspaces.findIndex((w) => w.uuid === window.uuid)); workspaces.workspaces.findIndex((w) => w.uuid === previousWorkspace.uuid) <
workspaces.workspaces.findIndex((w) => w.uuid === window.uuid);
gBrowser.tabContainer.setAttribute('zen-workspace-animation', isNextWorkspace ? 'next' : 'previous'); gBrowser.tabContainer.setAttribute('zen-workspace-animation', isNextWorkspace ? 'next' : 'previous');
this._animatingChange = true; this._animatingChange = true;
setTimeout(() => { setTimeout(() => {
@ -1322,7 +1312,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
} }
_processTabVisibility(workspaceUuid, containerId, workspaces) { _processTabVisibility(workspaceUuid, containerId, workspaces) {
const visibleTabs = new Set(); const visibleTabs = new Set();
const lastSelectedTab = this._lastSelectedWorkspaceTabs[workspaceUuid]; const lastSelectedTab = this._lastSelectedWorkspaceTabs[workspaceUuid];
@ -1330,7 +1319,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this.tabContainer.setAttribute('dont-animate-tabs', 'true'); this.tabContainer.setAttribute('dont-animate-tabs', 'true');
for (const tab of gBrowser.tabs) { for (const tab of gBrowser.tabs) {
const tabWorkspaceId = tab.getAttribute('zen-workspace-id'); const tabWorkspaceId = tab.getAttribute('zen-workspace-id');
const isEssential = tab.getAttribute("zen-essential") === "true"; const isEssential = tab.getAttribute('zen-essential') === 'true';
// Always hide last selected tabs from other workspaces // Always hide last selected tabs from other workspaces
if (lastSelectedTab === tab && tabWorkspaceId !== workspaceUuid && !isEssential) { if (lastSelectedTab === tab && tabWorkspaceId !== workspaceUuid && !isEssential) {
@ -1358,9 +1347,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
_shouldShowTab(tab, workspaceUuid, containerId, workspaces) { _shouldShowTab(tab, workspaceUuid, containerId, workspaces) {
const isEssential = tab.getAttribute("zen-essential") === "true"; const isEssential = tab.getAttribute('zen-essential') === 'true';
const tabWorkspaceId = tab.getAttribute('zen-workspace-id'); const tabWorkspaceId = tab.getAttribute('zen-workspace-id');
const tabContextId = tab.getAttribute("usercontextid"); const tabContextId = tab.getAttribute('usercontextid');
// Handle essential tabs // Handle essential tabs
if (isEssential) { if (isEssential) {
@ -1374,8 +1363,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} else { } else {
// In workspaces without a default container: Show essentials that aren't in container-specific workspaces // In workspaces without a default container: Show essentials that aren't in container-specific workspaces
// or have usercontextid="0" or no usercontextid // or have usercontextid="0" or no usercontextid
return !tabContextId || tabContextId === "0" || !workspaces.workspaces.some( return (
workspace => workspace.containerTabId === parseInt(tabContextId, 10) !tabContextId ||
tabContextId === '0' ||
!workspaces.workspaces.some((workspace) => workspace.containerTabId === parseInt(tabContextId, 10))
); );
} }
} }
@ -1408,13 +1399,16 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
tabToSelect = currentSelectedTab; tabToSelect = currentSelectedTab;
} }
// Try last selected tab if it is visible // Try last selected tab if it is visible
else if (lastSelectedTab && this._shouldShowTab(lastSelectedTab, window.uuid, containerId, workspaces) && visibleTabs.has(lastSelectedTab)) { else if (
lastSelectedTab &&
this._shouldShowTab(lastSelectedTab, window.uuid, containerId, workspaces) &&
visibleTabs.has(lastSelectedTab)
) {
tabToSelect = lastSelectedTab; tabToSelect = lastSelectedTab;
} }
// Find first suitable tab // Find first suitable tab
else { else {
tabToSelect = Array.from(visibleTabs) tabToSelect = Array.from(visibleTabs).find((tab) => !tab.pinned);
.find(tab => !tab.pinned);
} }
const previousSelectedTab = gBrowser.selectedTab; const previousSelectedTab = gBrowser.selectedTab;
@ -1436,7 +1430,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
} }
async _updateWorkspaceState(window, onInit) { async _updateWorkspaceState(window, onInit) {
// Update document state // Update document state
document.documentElement.setAttribute('zen-workspace-id', window.uuid); document.documentElement.setAttribute('zen-workspace-id', window.uuid);
@ -1535,7 +1528,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
async onTabBrowserInserted(event) { async onTabBrowserInserted(event) {
let tab = event.originalTarget; let tab = event.originalTarget;
const isEssential = tab.getAttribute("zen-essential") === "true"; const isEssential = tab.getAttribute('zen-essential') === 'true';
if (tab.getAttribute('zen-workspace-id') || !this.workspaceEnabled || isEssential) { if (tab.getAttribute('zen-workspace-id') || !this.workspaceEnabled || isEssential) {
return; return;
} }
@ -1555,7 +1548,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const parent = browser.ownerGlobal; const parent = browser.ownerGlobal;
const tab = gBrowser.getTabForBrowser(browser); const tab = gBrowser.getTabForBrowser(browser);
const workspaceID = tab.getAttribute('zen-workspace-id'); const workspaceID = tab.getAttribute('zen-workspace-id');
const isEssential = tab.getAttribute("zen-essential") === "true"; const isEssential = tab.getAttribute('zen-essential') === 'true';
if (!isEssential) { if (!isEssential) {
const activeWorkspace = await parent.ZenWorkspaces.getActiveWorkspace(); const activeWorkspace = await parent.ZenWorkspaces.getActiveWorkspace();
if (!activeWorkspace) { if (!activeWorkspace) {
@ -1660,7 +1653,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
return this._emojis; return this._emojis;
} }
const lazy = {}; const lazy = {};
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenEmojies.mjs", lazy); Services.scriptloader.loadSubScript('chrome://browser/content/zen-components/ZenEmojies.mjs', lazy);
this._emojis = lazy.zenGlobalEmojis(); this._emojis = lazy.zenGlobalEmojis();
return this._emojis; return this._emojis;
} }
@ -1686,7 +1679,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
targetIndex = Math.max(0, Math.min(workspaces.workspaces.length - 1, targetIndex)); targetIndex = Math.max(0, Math.min(workspaces.workspaces.length - 1, targetIndex));
} }
let nextWorkspace = workspaces.workspaces[(targetIndex)]; let nextWorkspace = workspaces.workspaces[targetIndex];
await this.changeWorkspace(nextWorkspace); await this.changeWorkspace(nextWorkspace);
} }
@ -1739,7 +1732,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (this.shouldForceContainerTabsToWorkspace && typeof userContextId !== 'undefined' && this._workspaceCache?.workspaces) { if (this.shouldForceContainerTabsToWorkspace && typeof userContextId !== 'undefined' && this._workspaceCache?.workspaces) {
// Find all workspaces that match the given userContextId // Find all workspaces that match the given userContextId
const matchingWorkspaces = this._workspaceCache.workspaces.filter((workspace) => workspace.containerTabId === userContextId); const matchingWorkspaces = this._workspaceCache.workspaces.filter(
(workspace) => workspace.containerTabId === userContextId
);
// Check if exactly one workspace matches // Check if exactly one workspace matches
if (matchingWorkspaces.length === 1) { if (matchingWorkspaces.length === 1) {
@ -1794,5 +1789,4 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
// Return true only if the bookmark is in another workspace and not in the active one // Return true only if the bookmark is in another workspace and not in the active one
return isInOtherWorkspace && !isInActiveWorkspace; return isInOtherWorkspace && !isInActiveWorkspace;
} }
})(); })();

View file

@ -3,8 +3,8 @@ var ZenWorkspacesStorage = {
async init() { async init() {
ChromeUtils.defineESModuleGetters(this.lazy, { ChromeUtils.defineESModuleGetters(this.lazy, {
PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", PlacesUtils: 'resource://gre/modules/PlacesUtils.sys.mjs',
Weave: "resource://services-sync/main.sys.mjs", Weave: 'resource://services-sync/main.sys.mjs',
}); });
await this._ensureTable(); await this._ensureTable();
@ -32,7 +32,7 @@ var ZenWorkspacesStorage = {
// SQLite doesn't have a direct "ADD COLUMN IF NOT EXISTS" syntax, // SQLite doesn't have a direct "ADD COLUMN IF NOT EXISTS" syntax,
// so we need to check if the columns exist first // so we need to check if the columns exist first
const columns = await db.execute(`PRAGMA table_info(zen_workspaces)`); const columns = await db.execute(`PRAGMA table_info(zen_workspaces)`);
const columnNames = columns.map(row => row.getResultByName('name')); const columnNames = columns.map((row) => row.getResultByName('name'));
// Helper function to add column if it doesn't exist // Helper function to add column if it doesn't exist
const addColumnIfNotExists = async (columnName, definition) => { const addColumnIfNotExists = async (columnName, definition) => {
@ -111,7 +111,9 @@ var ZenWorkspacesStorage = {
// Handle default workspace // Handle default workspace
if (workspace.default) { if (workspace.default) {
await db.execute(`UPDATE zen_workspaces SET is_default = 0 WHERE uuid != :uuid`, { uuid: workspace.uuid }); await db.execute(`UPDATE zen_workspaces SET is_default = 0 WHERE uuid != :uuid`, { uuid: workspace.uuid });
const unsetDefaultRows = await db.execute(`SELECT uuid FROM zen_workspaces WHERE is_default = 0 AND uuid != :uuid`, { uuid: workspace.uuid }); const unsetDefaultRows = await db.execute(`SELECT uuid FROM zen_workspaces WHERE is_default = 0 AND uuid != :uuid`, {
uuid: workspace.uuid,
});
for (const row of unsetDefaultRows) { for (const row of unsetDefaultRows) {
changedUUIDs.add(row.getResultByName('uuid')); changedUUIDs.add(row.getResultByName('uuid'));
} }
@ -128,7 +130,8 @@ var ZenWorkspacesStorage = {
} }
// Insert or replace the workspace // Insert or replace the workspace
await db.executeCached(` await db.executeCached(
`
INSERT OR REPLACE INTO zen_workspaces ( INSERT OR REPLACE INTO zen_workspaces (
uuid, name, icon, is_default, container_id, created_at, updated_at, "position", uuid, name, icon, is_default, container_id, created_at, updated_at, "position",
theme_type, theme_colors, theme_opacity, theme_rotation, theme_texture theme_type, theme_colors, theme_opacity, theme_rotation, theme_texture
@ -139,7 +142,8 @@ var ZenWorkspacesStorage = {
:position, :position,
:theme_type, :theme_colors, :theme_opacity, :theme_rotation, :theme_texture :theme_type, :theme_colors, :theme_opacity, :theme_rotation, :theme_texture
) )
`, { `,
{
uuid: workspace.uuid, uuid: workspace.uuid,
name: workspace.name, name: workspace.name,
icon: workspace.icon || null, icon: workspace.icon || null,
@ -151,17 +155,21 @@ var ZenWorkspacesStorage = {
theme_colors: workspace.theme ? JSON.stringify(workspace.theme.gradientColors) : null, theme_colors: workspace.theme ? JSON.stringify(workspace.theme.gradientColors) : null,
theme_opacity: workspace.theme?.opacity || null, theme_opacity: workspace.theme?.opacity || null,
theme_rotation: workspace.theme?.rotation || null, theme_rotation: workspace.theme?.rotation || null,
theme_texture: workspace.theme?.texture || null theme_texture: workspace.theme?.texture || null,
}); }
);
// Record the change // Record the change
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid: workspace.uuid, uuid: workspace.uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
changedUUIDs.add(workspace.uuid); changedUUIDs.add(workspace.uuid);
@ -170,7 +178,7 @@ var ZenWorkspacesStorage = {
}); });
if (notifyObservers) { if (notifyObservers) {
this._notifyWorkspacesChanged("zen-workspace-updated", Array.from(changedUUIDs)); this._notifyWorkspacesChanged('zen-workspace-updated', Array.from(changedUUIDs));
} }
}, },
@ -186,13 +194,15 @@ var ZenWorkspacesStorage = {
default: !!row.getResultByName('is_default'), default: !!row.getResultByName('is_default'),
containerTabId: row.getResultByName('container_id'), containerTabId: row.getResultByName('container_id'),
position: row.getResultByName('position'), position: row.getResultByName('position'),
theme: row.getResultByName('theme_type') ? { theme: row.getResultByName('theme_type')
? {
type: row.getResultByName('theme_type'), type: row.getResultByName('theme_type'),
gradientColors: JSON.parse(row.getResultByName('theme_colors')), gradientColors: JSON.parse(row.getResultByName('theme_colors')),
opacity: row.getResultByName('theme_opacity'), opacity: row.getResultByName('theme_opacity'),
rotation: row.getResultByName('theme_rotation'), rotation: row.getResultByName('theme_rotation'),
texture: row.getResultByName('theme_texture') texture: row.getResultByName('theme_texture'),
} : null }
: null,
})); }));
}, },
@ -209,19 +219,22 @@ var ZenWorkspacesStorage = {
// Record the removal as a change // Record the removal as a change
const now = Date.now(); const now = Date.now();
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid, uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
await this.updateLastChangeTimestamp(db); await this.updateLastChangeTimestamp(db);
}); });
if (notifyObservers) { if (notifyObservers) {
this._notifyWorkspacesChanged("zen-workspace-removed", changedUUIDs); this._notifyWorkspacesChanged('zen-workspace-removed', changedUUIDs);
} }
}, },
@ -243,7 +256,9 @@ var ZenWorkspacesStorage = {
await db.execute(`UPDATE zen_workspaces SET is_default = 0 WHERE uuid != :uuid`, { uuid }); await db.execute(`UPDATE zen_workspaces SET is_default = 0 WHERE uuid != :uuid`, { uuid });
// Collect UUIDs of workspaces that were unset as default // Collect UUIDs of workspaces that were unset as default
const unsetDefaultRows = await db.execute(`SELECT uuid FROM zen_workspaces WHERE is_default = 0 AND uuid != :uuid`, { uuid }); const unsetDefaultRows = await db.execute(`SELECT uuid FROM zen_workspaces WHERE is_default = 0 AND uuid != :uuid`, {
uuid,
});
for (const row of unsetDefaultRows) { for (const row of unsetDefaultRows) {
changedUUIDs.push(row.getResultByName('uuid')); changedUUIDs.push(row.getResultByName('uuid'));
} }
@ -252,13 +267,16 @@ var ZenWorkspacesStorage = {
await db.execute(`UPDATE zen_workspaces SET is_default = 1 WHERE uuid = :uuid`, { uuid }); await db.execute(`UPDATE zen_workspaces SET is_default = 1 WHERE uuid = :uuid`, { uuid });
// Record the change for the specified workspace // Record the change for the specified workspace
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid, uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
// Add the main workspace UUID to the changed set // Add the main workspace UUID to the changed set
changedUUIDs.push(uuid); changedUUIDs.push(uuid);
@ -268,27 +286,31 @@ var ZenWorkspacesStorage = {
}); });
if (notifyObservers) { if (notifyObservers) {
this._notifyWorkspacesChanged("zen-workspace-updated", changedUUIDs); this._notifyWorkspacesChanged('zen-workspace-updated', changedUUIDs);
} }
}, },
async markChanged(uuid) { async markChanged(uuid) {
await this.lazy.PlacesUtils.withConnectionWrapper('ZenWorkspacesStorage.markChanged', async (db) => { await this.lazy.PlacesUtils.withConnectionWrapper('ZenWorkspacesStorage.markChanged', async (db) => {
const now = Date.now(); const now = Date.now();
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid, uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
}); });
}, },
async saveWorkspaceTheme(uuid, theme, notifyObservers = true) { async saveWorkspaceTheme(uuid, theme, notifyObservers = true) {
const changedUUIDs = [uuid]; const changedUUIDs = [uuid];
await this.lazy.PlacesUtils.withConnectionWrapper('saveWorkspaceTheme', async (db) => { await this.lazy.PlacesUtils.withConnectionWrapper('saveWorkspaceTheme', async (db) => {
await db.execute(` await db.execute(
`
UPDATE zen_workspaces UPDATE zen_workspaces
SET SET
theme_type = :type, theme_type = :type,
@ -298,22 +320,24 @@ var ZenWorkspacesStorage = {
theme_texture = :texture, theme_texture = :texture,
updated_at = :now updated_at = :now
WHERE uuid = :uuid WHERE uuid = :uuid
`, { `,
{
type: theme.type, type: theme.type,
colors: JSON.stringify(theme.gradientColors), colors: JSON.stringify(theme.gradientColors),
opacity: theme.opacity, opacity: theme.opacity,
rotation: theme.rotation, rotation: theme.rotation,
texture: theme.texture, texture: theme.texture,
now: Date.now(), now: Date.now(),
uuid uuid,
}); }
);
await this.markChanged(uuid); await this.markChanged(uuid);
await this.updateLastChangeTimestamp(db); await this.updateLastChangeTimestamp(db);
}); });
if (notifyObservers) { if (notifyObservers) {
this._notifyWorkspacesChanged("zen-workspace-updated", changedUUIDs); this._notifyWorkspacesChanged('zen-workspace-updated', changedUUIDs);
} }
}, },
@ -349,21 +373,27 @@ var ZenWorkspacesStorage = {
for (let i = 0; i < workspaces.length; i++) { for (let i = 0; i < workspaces.length; i++) {
const newPosition = (i + 1) * 1000; // Use large increments const newPosition = (i + 1) * 1000; // Use large increments
await db.execute(` await db.execute(
`
UPDATE zen_workspaces UPDATE zen_workspaces
SET "position" = :newPosition SET "position" = :newPosition
WHERE uuid = :uuid WHERE uuid = :uuid
`, { newPosition, uuid: workspaces[i].getResultByName('uuid') }); `,
{ newPosition, uuid: workspaces[i].getResultByName('uuid') }
);
changedUUIDs.add(workspaces[i].getResultByName('uuid')); changedUUIDs.add(workspaces[i].getResultByName('uuid'));
} }
}, },
async updateLastChangeTimestamp(db) { async updateLastChangeTimestamp(db) {
const now = Date.now(); const now = Date.now();
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO moz_meta (key, value) INSERT OR REPLACE INTO moz_meta (key, value)
VALUES ('zen_workspaces_last_change', :now) VALUES ('zen_workspaces_last_change', :now)
`, { now }); `,
{ now }
);
}, },
async getLastChangeTimestamp() { async getLastChangeTimestamp() {
@ -385,29 +415,35 @@ var ZenWorkspacesStorage = {
const workspace = workspaces[i]; const workspace = workspaces[i];
const newPosition = (i + 1) * 1000; const newPosition = (i + 1) * 1000;
await db.execute(` await db.execute(
`
UPDATE zen_workspaces UPDATE zen_workspaces
SET "position" = :newPosition SET "position" = :newPosition
WHERE uuid = :uuid WHERE uuid = :uuid
`, { newPosition, uuid: workspace.uuid }); `,
{ newPosition, uuid: workspace.uuid }
);
changedUUIDs.add(workspace.uuid); changedUUIDs.add(workspace.uuid);
// Record the change // Record the change
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp) INSERT OR REPLACE INTO zen_workspaces_changes (uuid, timestamp)
VALUES (:uuid, :timestamp) VALUES (:uuid, :timestamp)
`, { `,
{
uuid: workspace.uuid, uuid: workspace.uuid,
timestamp: Math.floor(now / 1000) timestamp: Math.floor(now / 1000),
}); }
);
} }
await this.updateLastChangeTimestamp(db); await this.updateLastChangeTimestamp(db);
}); });
}); });
this._notifyWorkspacesChanged("zen-workspace-updated", Array.from(changedUUIDs)); this._notifyWorkspacesChanged('zen-workspace-updated', Array.from(changedUUIDs));
}, },
}; };
@ -458,7 +494,6 @@ var ZenWorkspaceBookmarksStorage = {
CREATE INDEX IF NOT EXISTS idx_bookmarks_workspaces_changes CREATE INDEX IF NOT EXISTS idx_bookmarks_workspaces_changes
ON zen_bookmarks_workspaces_changes(bookmark_guid, workspace_uuid) ON zen_bookmarks_workspaces_changes(bookmark_guid, workspace_uuid)
`); `);
}); });
}, },
@ -468,10 +503,13 @@ var ZenWorkspaceBookmarksStorage = {
*/ */
async updateLastChangeTimestamp(db) { async updateLastChangeTimestamp(db) {
const now = Date.now(); const now = Date.now();
await db.execute(` await db.execute(
`
INSERT OR REPLACE INTO moz_meta (key, value) INSERT OR REPLACE INTO moz_meta (key, value)
VALUES ('zen_bookmarks_workspaces_last_change', :now) VALUES ('zen_bookmarks_workspaces_last_change', :now)
`, { now }); `,
{ now }
);
}, },
/** /**
@ -489,13 +527,16 @@ var ZenWorkspaceBookmarksStorage = {
async getBookmarkWorkspaces(bookmarkGuid) { async getBookmarkWorkspaces(bookmarkGuid) {
const db = await ZenWorkspacesStorage.lazy.PlacesUtils.promiseDBConnection(); const db = await ZenWorkspacesStorage.lazy.PlacesUtils.promiseDBConnection();
const rows = await db.execute(` const rows = await db.execute(
`
SELECT workspace_uuid SELECT workspace_uuid
FROM zen_bookmarks_workspaces FROM zen_bookmarks_workspaces
WHERE bookmark_guid = :bookmark_guid WHERE bookmark_guid = :bookmark_guid
`, { bookmark_guid: bookmarkGuid }); `,
{ bookmark_guid: bookmarkGuid }
);
return rows.map(row => row.getResultByName("workspace_uuid")); return rows.map((row) => row.getResultByName('workspace_uuid'));
}, },
/** /**
@ -519,8 +560,8 @@ var ZenWorkspaceBookmarksStorage = {
const result = {}; const result = {};
for (const row of rows) { for (const row of rows) {
const workspaceUuid = row.getResultByName("workspace_uuid"); const workspaceUuid = row.getResultByName('workspace_uuid');
const bookmarkGuids = row.getResultByName("bookmark_guids"); const bookmarkGuids = row.getResultByName('bookmark_guids');
result[workspaceUuid] = bookmarkGuids ? bookmarkGuids.split(',') : []; result[workspaceUuid] = bookmarkGuids ? bookmarkGuids.split(',') : [];
} }
@ -543,7 +584,7 @@ var ZenWorkspaceBookmarksStorage = {
const key = `${row.getResultByName('bookmark_guid')}:${row.getResultByName('workspace_uuid')}`; const key = `${row.getResultByName('bookmark_guid')}:${row.getResultByName('workspace_uuid')}`;
changes[key] = { changes[key] = {
type: row.getResultByName('change_type'), type: row.getResultByName('change_type'),
timestamp: row.getResultByName('timestamp') timestamp: row.getResultByName('timestamp'),
}; };
} }
return changes; return changes;
@ -553,11 +594,13 @@ var ZenWorkspaceBookmarksStorage = {
* Clear all recorded changes. * Clear all recorded changes.
*/ */
async clearChangedIDs() { async clearChangedIDs() {
await ZenWorkspacesStorage.lazy.PlacesUtils.withConnectionWrapper('ZenWorkspaceBookmarksStorage.clearChangedIDs', async (db) => { await ZenWorkspacesStorage.lazy.PlacesUtils.withConnectionWrapper(
'ZenWorkspaceBookmarksStorage.clearChangedIDs',
async (db) => {
await db.execute(`DELETE FROM zen_bookmarks_workspaces_changes`); await db.execute(`DELETE FROM zen_bookmarks_workspaces_changes`);
}); }
);
}, },
}; };
ZenWorkspacesStorage.init(); ZenWorkspacesStorage.init();

View file

@ -1,9 +1,7 @@
var { Tracker, Store, SyncEngine } = ChromeUtils.importESModule("resource://services-sync/engines.sys.mjs"); var { Tracker, Store, SyncEngine } = ChromeUtils.importESModule('resource://services-sync/engines.sys.mjs');
var { CryptoWrapper } = ChromeUtils.importESModule("resource://services-sync/record.sys.mjs"); var { CryptoWrapper } = ChromeUtils.importESModule('resource://services-sync/record.sys.mjs');
var { Utils } = ChromeUtils.importESModule("resource://services-sync/util.sys.mjs"); var { Utils } = ChromeUtils.importESModule('resource://services-sync/util.sys.mjs');
var { SCORE_INCREMENT_XLARGE } = ChromeUtils.importESModule("resource://services-sync/constants.sys.mjs"); var { SCORE_INCREMENT_XLARGE } = ChromeUtils.importESModule('resource://services-sync/constants.sys.mjs');
// Define ZenWorkspaceRecord // Define ZenWorkspaceRecord
function ZenWorkspaceRecord(collection, id) { function ZenWorkspaceRecord(collection, id) {
@ -13,19 +11,19 @@ function ZenWorkspaceRecord(collection, id) {
ZenWorkspaceRecord.prototype = Object.create(CryptoWrapper.prototype); ZenWorkspaceRecord.prototype = Object.create(CryptoWrapper.prototype);
ZenWorkspaceRecord.prototype.constructor = ZenWorkspaceRecord; ZenWorkspaceRecord.prototype.constructor = ZenWorkspaceRecord;
ZenWorkspaceRecord.prototype._logName = "Sync.Record.ZenWorkspace"; ZenWorkspaceRecord.prototype._logName = 'Sync.Record.ZenWorkspace';
Utils.deferGetSet(ZenWorkspaceRecord, "cleartext", [ Utils.deferGetSet(ZenWorkspaceRecord, 'cleartext', [
"name", 'name',
"icon", 'icon',
"default", 'default',
"containerTabId", 'containerTabId',
"position", 'position',
"theme_type", 'theme_type',
"theme_colors", 'theme_colors',
"theme_opacity", 'theme_opacity',
"theme_rotation", 'theme_rotation',
"theme_texture" 'theme_texture',
]); ]);
// Define ZenWorkspacesStore // Define ZenWorkspacesStore
@ -57,7 +55,7 @@ ZenWorkspacesStore.prototype.getAllIDs = async function () {
} }
return ids; return ids;
} catch (error) { } catch (error) {
this._log.error("Error fetching all workspace IDs", error); this._log.error('Error fetching all workspace IDs', error);
throw error; throw error;
} }
}; };
@ -70,7 +68,7 @@ ZenWorkspacesStore.prototype.getAllIDs = async function () {
ZenWorkspacesStore.prototype.changeItemID = async function (oldID, newID) { ZenWorkspacesStore.prototype.changeItemID = async function (oldID, newID) {
try { try {
const workspaces = await ZenWorkspacesStorage.getWorkspaces(); const workspaces = await ZenWorkspacesStorage.getWorkspaces();
const workspace = workspaces.find(ws => ws.uuid === oldID); const workspace = workspaces.find((ws) => ws.uuid === oldID);
if (workspace) { if (workspace) {
workspace.uuid = newID; workspace.uuid = newID;
await ZenWorkspacesStorage.saveWorkspace(workspace, false); await ZenWorkspacesStorage.saveWorkspace(workspace, false);
@ -91,7 +89,7 @@ ZenWorkspacesStore.prototype.changeItemID = async function (oldID, newID) {
ZenWorkspacesStore.prototype.itemExists = async function (id) { ZenWorkspacesStore.prototype.itemExists = async function (id) {
try { try {
const workspaces = await ZenWorkspacesStorage.getWorkspaces(); const workspaces = await ZenWorkspacesStorage.getWorkspaces();
return workspaces.some(ws => ws.uuid === id); return workspaces.some((ws) => ws.uuid === id);
} catch (error) { } catch (error) {
this._log.error(`Error checking if workspace exists with ID ${id}`, error); this._log.error(`Error checking if workspace exists with ID ${id}`, error);
throw error; throw error;
@ -107,7 +105,7 @@ ZenWorkspacesStore.prototype.itemExists = async function (id) {
ZenWorkspacesStore.prototype.createRecord = async function (id, collection) { ZenWorkspacesStore.prototype.createRecord = async function (id, collection) {
try { try {
const workspaces = await ZenWorkspacesStorage.getWorkspaces(); const workspaces = await ZenWorkspacesStorage.getWorkspaces();
const workspace = workspaces.find(ws => ws.uuid === id); const workspace = workspaces.find((ws) => ws.uuid === id);
const record = new ZenWorkspaceRecord(collection, id); const record = new ZenWorkspaceRecord(collection, id);
if (workspace) { if (workspace) {
@ -149,13 +147,15 @@ ZenWorkspacesStore.prototype.create = async function (record) {
default: record.default, default: record.default,
containerTabId: record.containerTabId, containerTabId: record.containerTabId,
position: record.position, position: record.position,
theme: record.theme_type ? { theme: record.theme_type
? {
type: record.theme_type, type: record.theme_type,
gradientColors: JSON.parse(record.theme_colors), gradientColors: JSON.parse(record.theme_colors),
opacity: record.theme_opacity, opacity: record.theme_opacity,
rotation: record.theme_rotation, rotation: record.theme_rotation,
texture: record.theme_texture texture: record.theme_texture,
} : null }
: null,
}; };
await ZenWorkspacesStorage.saveWorkspace(workspace, false); await ZenWorkspacesStorage.saveWorkspace(workspace, false);
} catch (error) { } catch (error) {
@ -198,7 +198,7 @@ ZenWorkspacesStore.prototype.wipe = async function () {
try { try {
await ZenWorkspacesStorage.wipeAllWorkspaces(); await ZenWorkspacesStorage.wipeAllWorkspaces();
} catch (error) { } catch (error) {
this._log.error("Error wiping all workspaces", error); this._log.error('Error wiping all workspaces', error);
throw error; throw error;
} }
}; };
@ -208,31 +208,31 @@ ZenWorkspacesStore.prototype.wipe = async function () {
* @param {ZenWorkspaceRecord} record - The workspace record to validate. * @param {ZenWorkspaceRecord} record - The workspace record to validate.
*/ */
ZenWorkspacesStore.prototype._validateRecord = function (record) { ZenWorkspacesStore.prototype._validateRecord = function (record) {
if (!record.id || typeof record.id !== "string") { if (!record.id || typeof record.id !== 'string') {
throw new Error("Invalid workspace ID"); throw new Error('Invalid workspace ID');
} }
if (!record.name || typeof record.name !== "string") { if (!record.name || typeof record.name !== 'string') {
throw new Error(`Invalid workspace name for ID ${record.id}`); throw new Error(`Invalid workspace name for ID ${record.id}`);
} }
if (typeof record.default !== "boolean") { if (typeof record.default !== 'boolean') {
record.default = false; record.default = false;
} }
if (record.icon != null && typeof record.icon !== "string") { if (record.icon != null && typeof record.icon !== 'string') {
throw new Error(`Invalid icon for workspace ID ${record.id}`); throw new Error(`Invalid icon for workspace ID ${record.id}`);
} }
if (record.containerTabId != null && typeof record.containerTabId !== "number") { if (record.containerTabId != null && typeof record.containerTabId !== 'number') {
throw new Error(`Invalid containerTabId for workspace ID ${record.id}`); throw new Error(`Invalid containerTabId for workspace ID ${record.id}`);
} }
if(record.position != null && typeof record.position !== "number") { if (record.position != null && typeof record.position !== 'number') {
throw new Error(`Invalid position for workspace ID ${record.id}`); throw new Error(`Invalid position for workspace ID ${record.id}`);
} }
// Validate theme properties if they exist // Validate theme properties if they exist
if (record.theme_type) { if (record.theme_type) {
if (typeof record.theme_type !== "string") { if (typeof record.theme_type !== 'string') {
throw new Error(`Invalid theme_type for workspace ID ${record.id}`); throw new Error(`Invalid theme_type for workspace ID ${record.id}`);
} }
if (!record.theme_colors || typeof record.theme_colors !== "string") { if (!record.theme_colors || typeof record.theme_colors !== 'string') {
throw new Error(`Invalid theme_colors for workspace ID ${record.id}`); throw new Error(`Invalid theme_colors for workspace ID ${record.id}`);
} }
try { try {
@ -240,13 +240,13 @@ ZenWorkspacesStore.prototype._validateRecord = function (record) {
} catch (e) { } catch (e) {
throw new Error(`Invalid theme_colors JSON for workspace ID ${record.id}`); throw new Error(`Invalid theme_colors JSON for workspace ID ${record.id}`);
} }
if (record.theme_opacity != null && typeof record.theme_opacity !== "number") { if (record.theme_opacity != null && typeof record.theme_opacity !== 'number') {
throw new Error(`Invalid theme_opacity for workspace ID ${record.id}`); throw new Error(`Invalid theme_opacity for workspace ID ${record.id}`);
} }
if (record.theme_rotation != null && typeof record.theme_rotation !== "number") { if (record.theme_rotation != null && typeof record.theme_rotation !== 'number') {
throw new Error(`Invalid theme_rotation for workspace ID ${record.id}`); throw new Error(`Invalid theme_rotation for workspace ID ${record.id}`);
} }
if (record.theme_texture != null && typeof record.theme_texture !== "number") { if (record.theme_texture != null && typeof record.theme_texture !== 'number') {
throw new Error(`Invalid theme_texture for workspace ID ${record.id}`); throw new Error(`Invalid theme_texture for workspace ID ${record.id}`);
} }
} }
@ -260,7 +260,7 @@ ZenWorkspacesStore.prototype.getChangedIDs = async function () {
try { try {
return await ZenWorkspacesStorage.getChangedIDs(); return await ZenWorkspacesStorage.getChangedIDs();
} catch (error) { } catch (error) {
this._log.error("Error retrieving changed IDs from storage", error); this._log.error('Error retrieving changed IDs from storage', error);
throw error; throw error;
} }
}; };
@ -272,7 +272,7 @@ ZenWorkspacesStore.prototype.clearChangedIDs = async function () {
try { try {
await ZenWorkspacesStorage.clearChangedIDs(); await ZenWorkspacesStorage.clearChangedIDs();
} catch (error) { } catch (error) {
this._log.error("Error clearing changed IDs in storage", error); this._log.error('Error clearing changed IDs in storage', error);
throw error; throw error;
} }
}; };
@ -297,14 +297,13 @@ ZenWorkspacesStore.prototype.finalize = async function () {
await Store.prototype.finalize.call(this); await Store.prototype.finalize.call(this);
}; };
// Define ZenWorkspacesTracker // Define ZenWorkspacesTracker
function ZenWorkspacesTracker(name, engine) { function ZenWorkspacesTracker(name, engine) {
Tracker.call(this, name, engine); Tracker.call(this, name, engine);
this._ignoreAll = false; this._ignoreAll = false;
// Observe profile-before-change to stop the tracker gracefully // Observe profile-before-change to stop the tracker gracefully
Services.obs.addObserver(this.asyncObserver, "profile-before-change"); Services.obs.addObserver(this.asyncObserver, 'profile-before-change');
} }
ZenWorkspacesTracker.prototype = Object.create(Tracker.prototype); ZenWorkspacesTracker.prototype = Object.create(Tracker.prototype);
@ -318,7 +317,7 @@ ZenWorkspacesTracker.prototype.getChangedIDs = async function () {
try { try {
return await this.engine._store.getChangedIDs(); return await this.engine._store.getChangedIDs();
} catch (error) { } catch (error) {
this._log.error("Error retrieving changed IDs from store", error); this._log.error('Error retrieving changed IDs from store', error);
throw error; throw error;
} }
}; };
@ -330,7 +329,7 @@ ZenWorkspacesTracker.prototype.clearChangedIDs = async function () {
try { try {
await this.engine._store.clearChangedIDs(); await this.engine._store.clearChangedIDs();
} catch (error) { } catch (error) {
this._log.error("Error clearing changed IDs in store", error); this._log.error('Error clearing changed IDs in store', error);
throw error; throw error;
} }
}; };
@ -342,11 +341,11 @@ ZenWorkspacesTracker.prototype.onStart = function () {
if (this._started) { if (this._started) {
return; return;
} }
this._log.trace("Starting tracker"); this._log.trace('Starting tracker');
// Register observers for workspace changes // Register observers for workspace changes
Services.obs.addObserver(this.asyncObserver, "zen-workspace-added"); Services.obs.addObserver(this.asyncObserver, 'zen-workspace-added');
Services.obs.addObserver(this.asyncObserver, "zen-workspace-removed"); Services.obs.addObserver(this.asyncObserver, 'zen-workspace-removed');
Services.obs.addObserver(this.asyncObserver, "zen-workspace-updated"); Services.obs.addObserver(this.asyncObserver, 'zen-workspace-updated');
this._started = true; this._started = true;
}; };
@ -357,11 +356,11 @@ ZenWorkspacesTracker.prototype.onStop = function () {
if (!this._started) { if (!this._started) {
return; return;
} }
this._log.trace("Stopping tracker"); this._log.trace('Stopping tracker');
// Unregister observers for workspace changes // Unregister observers for workspace changes
Services.obs.removeObserver(this.asyncObserver, "zen-workspace-added"); Services.obs.removeObserver(this.asyncObserver, 'zen-workspace-added');
Services.obs.removeObserver(this.asyncObserver, "zen-workspace-removed"); Services.obs.removeObserver(this.asyncObserver, 'zen-workspace-removed');
Services.obs.removeObserver(this.asyncObserver, "zen-workspace-updated"); Services.obs.removeObserver(this.asyncObserver, 'zen-workspace-updated');
this._started = false; this._started = false;
}; };
@ -378,18 +377,18 @@ ZenWorkspacesTracker.prototype.observe = async function (subject, topic, data) {
try { try {
switch (topic) { switch (topic) {
case "profile-before-change": case 'profile-before-change':
await this.stop(); await this.stop();
break; break;
case "zen-workspace-removed": case 'zen-workspace-removed':
case "zen-workspace-updated": case 'zen-workspace-updated':
case "zen-workspace-added": case 'zen-workspace-added':
let workspaceIDs; let workspaceIDs;
if (data) { if (data) {
try { try {
workspaceIDs = JSON.parse(data); workspaceIDs = JSON.parse(data);
if (!Array.isArray(workspaceIDs)) { if (!Array.isArray(workspaceIDs)) {
throw new Error("Parsed data is not an array"); throw new Error('Parsed data is not an array');
} }
} catch (parseError) { } catch (parseError) {
this._log.error(`Failed to parse workspace UUIDs from data: ${data}`, parseError); this._log.error(`Failed to parse workspace UUIDs from data: ${data}`, parseError);
@ -400,11 +399,11 @@ ZenWorkspacesTracker.prototype.observe = async function (subject, topic, data) {
return; return;
} }
this._log.trace(`Observed ${topic} for UUIDs: ${workspaceIDs.join(", ")}`); this._log.trace(`Observed ${topic} for UUIDs: ${workspaceIDs.join(', ')}`);
// Process each UUID // Process each UUID
for (const workspaceID of workspaceIDs) { for (const workspaceID of workspaceIDs) {
if (typeof workspaceID === "string") { if (typeof workspaceID === 'string') {
// Inform the store about the change // Inform the store about the change
await this.engine._store.markChanged(workspaceID); await this.engine._store.markChanged(workspaceID);
} else { } else {
@ -430,10 +429,9 @@ ZenWorkspacesTracker.prototype.finalize = async function () {
await Tracker.prototype.finalize.call(this); await Tracker.prototype.finalize.call(this);
}; };
// Define ZenWorkspacesEngine // Define ZenWorkspacesEngine
function ZenWorkspacesEngine(service) { function ZenWorkspacesEngine(service) {
SyncEngine.call(this, "Workspaces", service); SyncEngine.call(this, 'Workspaces', service);
} }
ZenWorkspacesEngine.prototype = Object.create(SyncEngine.prototype); ZenWorkspacesEngine.prototype = Object.create(SyncEngine.prototype);
@ -448,5 +446,3 @@ ZenWorkspacesEngine.prototype.syncPriority = 10;
ZenWorkspacesEngine.prototype.allowSkippedRecord = false; ZenWorkspacesEngine.prototype.allowSkippedRecord = false;
Object.setPrototypeOf(ZenWorkspacesEngine.prototype, SyncEngine.prototype); Object.setPrototypeOf(ZenWorkspacesEngine.prototype, SyncEngine.prototype);

View file

@ -33,7 +33,7 @@ export class ZenThemeMarketplaceChild extends JSWindowActorChild {
id: meta.getAttribute('data-id'), id: meta.getAttribute('data-id'),
name: meta.getAttribute('data-name'), name: meta.getAttribute('data-name'),
author: meta.getAttribute('data-author'), author: meta.getAttribute('data-author'),
} };
} }
return null; return null;
} }
@ -94,13 +94,9 @@ export class ZenThemeMarketplaceChild extends JSWindowActorChild {
} }
injectMarkplaceAPI() { injectMarkplaceAPI() {
Cu.exportFunction( Cu.exportFunction(this.installTheme.bind(this), this.contentWindow, {
this.installTheme.bind(this), defineAs: 'ZenInstallTheme',
this.contentWindow, });
{
defineAs: "ZenInstallTheme",
}
);
} }
async addIntallButtons() { async addIntallButtons() {

View file

@ -1083,38 +1083,38 @@ Preferences.addAll([
default: false, default: false,
}, },
{ {
id: "zen.glance.activation-method", id: 'zen.glance.activation-method',
type: "string", type: 'string',
default: "ctrl", default: 'ctrl',
}, },
{ {
id: "zen.glance.enabled", id: 'zen.glance.enabled',
type: "bool", type: 'bool',
default: true, default: true,
}, },
{ {
id: "zen.theme.color-prefs.use-workspace-colors", id: 'zen.theme.color-prefs.use-workspace-colors',
type: "bool", type: 'bool',
default: false, default: false,
}, },
{ {
id: "zen.view.compact.color-toolbar", id: 'zen.view.compact.color-toolbar',
type: "bool", type: 'bool',
default: true, default: true,
}, },
{ {
id: "zen.urlbar.behavior", id: 'zen.urlbar.behavior',
type: "string", type: 'string',
default: "float", default: 'float',
}, },
{ {
id: "zen.view.compact.color-sidebar", id: 'zen.view.compact.color-sidebar',
type: "bool", type: 'bool',
default: true, default: true,
}, },
{ {
id: "zen.essentials.enabled", id: 'zen.essentials.enabled',
type: "bool", type: 'bool',
default: true, default: true,
}, },
{ {
@ -1123,18 +1123,18 @@ Preferences.addAll([
default: false, default: false,
}, },
{ {
id: "zen.tabs.show-newtab-vertical", id: 'zen.tabs.show-newtab-vertical',
type: "bool", type: 'bool',
default: true, default: true,
}, },
{ {
id: "zen.view.show-newtab-button-border-top", id: 'zen.view.show-newtab-button-border-top',
type: "bool", type: 'bool',
default: false, default: false,
}, },
{ {
id: "zen.view.show-newtab-button-top", id: 'zen.view.show-newtab-button-top',
type: "bool", type: 'bool',
default: true, default: true,
}, },
]); ]);

View file

@ -53,8 +53,8 @@ body {
& button { & button {
opacity: 0; opacity: 0;
animation: fadeIn .5s ease-in-out forwards; animation: fadeIn 0.5s ease-in-out forwards;
animation-delay: .8s; animation-delay: 0.8s;
} }
& button:nth-child(2) { & button:nth-child(2) {
@ -258,7 +258,7 @@ input[type='checkbox'] {
.delay-animation, .delay-animation,
.delay-animation-2 { .delay-animation-2 {
opacity: 0; opacity: 0;
animation: fadeIn .5s ease-in-out forwards; animation: fadeIn 0.5s ease-in-out forwards;
} }
#importBrowser { #importBrowser {
@ -345,7 +345,7 @@ input[type='checkbox'] {
#welcome { #welcome {
& h1 { & h1 {
animation-duration: .8s !important; animation-duration: 0.8s !important;
} }
} }
@ -405,7 +405,8 @@ input[type='checkbox'] {
border: 3px solid light-dark(#000, #fff); border: 3px solid light-dark(#000, #fff);
} }
#welcome, #thanks { #welcome,
#thanks {
justify-content: center; justify-content: center;
} }

View file

@ -259,7 +259,7 @@ groupbox h2 {
--zen-compact-mode-styles-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.1); --zen-compact-mode-styles-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.1);
@media not (prefers-color-scheme: dark) { @media not (prefers-color-scheme: dark) {
--zen-compact-mode-styles-shadow: 0 0 .5px .5px rgba(0, 0, 0, 0.1); --zen-compact-mode-styles-shadow: 0 0 0.5px 0.5px rgba(0, 0, 0, 0.1);
} }
box-shadow: var(--zen-compact-mode-styles-shadow); box-shadow: var(--zen-compact-mode-styles-shadow);
@ -644,5 +644,5 @@ groupbox h2 {
.sync-engine-workspaces .checkbox-icon, .sync-engine-workspaces .checkbox-icon,
.sync-engine-workspaces.sync-engine-image { .sync-engine-workspaces.sync-engine-image {
list-style-image: url("chrome://devtools/skin/images/tool-storage.svg"); list-style-image: url('chrome://devtools/skin/images/tool-storage.svg');
} }

View file

@ -577,7 +577,6 @@
fill: white !important; fill: white !important;
} }
/* reload/stop animation */ /* reload/stop animation */
#stop-reload-button[animate] #stop-reload-button[animate]
> #reload-button[displaystop] > #reload-button[displaystop]

View file

@ -47,9 +47,7 @@
} }
}, },
"license": { "license": {
"ignoredFiles": [ "ignoredFiles": [".*\\.json"],
".*\\.json"
],
"licenseType": "MPL-2.0" "licenseType": "MPL-2.0"
}, },
"updateHostname": "updates.zen-browser.app" "updateHostname": "updates.zen-browser.app"