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,16 +10,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out repository - name: Check out repository
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Fetch JSON Response - name: Fetch JSON Response
run: | run: |
curl -s "https://hg.mozilla.org/releases/mozilla-release/json-tags" > rc-response.json curl -s "https://hg.mozilla.org/releases/mozilla-release/json-tags" > rc-response.json
- name: Check for any updates - name: Check for any updates
env: env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
DISCORD_PING_IDS: ${{ secrets.DISCORD_PING_IDS }} DISCORD_PING_IDS: ${{ secrets.DISCORD_PING_IDS }}
run: | run: |
python3 scripts/check-rc-response.py || true python3 scripts/check-rc-response.py || true

View file

@ -10,56 +10,55 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code
uses: actions/checkout@v2
with:
token: ${{ secrets.DEPLOY_KEY }}
- name: Checkout code - name: Get dates for last month
uses: actions/checkout@v2 shell: bash
with: run: |
token: ${{ secrets.DEPLOY_KEY }} # Get the current date
current_date=$(date +'%Y-%m-%d')
- name: Get dates for last month # Calculate the previous month
shell: bash previous_date=$(date -d "$current_date -1 month" +'%Y-%m-%d')
run: |
# Get the current date
current_date=$(date +'%Y-%m-%d')
# Calculate the previous month # Extract the year and month from the previous date
previous_date=$(date -d "$current_date -1 month" +'%Y-%m-%d') previous_year=$(date -d "$previous_date" +'%Y')
previous_month=$(date -d "$previous_date" +'%m')
# Extract the year and month from the previous date # Calculate the first day of the previous month
previous_year=$(date -d "$previous_date" +'%Y') first_day=$(date -d "$previous_year-$previous_month-01" +'%Y-%m-%d')
previous_month=$(date -d "$previous_date" +'%m')
# Calculate the first day of the previous month # Calculate the last day of the previous month
first_day=$(date -d "$previous_year-$previous_month-01" +'%Y-%m-%d') last_day=$(date -d "$first_day +1 month -1 day" +'%Y-%m-%d')
# Calculate the last day of the previous month echo "$first_day..$last_day"
last_day=$(date -d "$first_day +1 month -1 day" +'%Y-%m-%d') echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV"
echo "last_month_year=$previous_year" >> "$GITHUB_ENV"
echo "$first_day..$last_day" - name: Run issue-metrics tool
echo "last_month=$first_day..$last_day" >> "$GITHUB_ENV" uses: github/issue-metrics@v2
echo "last_month_year=$previous_year" >> "$GITHUB_ENV" env:
GH_TOKEN: ${{ secrets.DEPLOY_KEY }}
HIDE_AUTHOR: true
HIDE_TIME_TO_ANSWER: true
SEARCH_QUERY: 'repo:zen-browser/desktop is:issue created:${{ env.last_month }}'
- name: Run issue-metrics tool - name: Move metrics to docs folder
uses: github/issue-metrics@v2 run: |
env: mkdir -p docs/issue-metrics
GH_TOKEN: ${{ secrets.DEPLOY_KEY }} rm -f docs/issue-metrics/${{ env.last_month_year }}_${{ env.last_month }}.md
HIDE_AUTHOR: true mv issue_metrics.md docs/issue-metrics/${{ env.last_month_year }}_${{ env.last_month }}.md
HIDE_TIME_TO_ANSWER: true
SEARCH_QUERY: 'repo:zen-browser/desktop is:issue created:${{ env.last_month }}'
- name: Move metrics to docs folder - name: Remove metrisc JSON
run: | run: |
mkdir -p docs/issue-metrics rm -f issue_metrics.json
rm -f docs/issue-metrics/${{ env.last_month_year }}_${{ env.last_month }}.md
mv issue_metrics.md docs/issue-metrics/${{ env.last_month_year }}_${{ env.last_month }}.md
- name: Remove metrisc JSON - name: Commit changes
run: | uses: stefanzweifel/git-auto-commit-action@v5
rm -f issue_metrics.json with:
commit_message: 'Update monthly issue metrics'
- name: Commit changes commit_user_name: Zen Browser Robot
uses: stefanzweifel/git-auto-commit-action@v5 commit_user_email: zen-browser-auto@users.noreply.github.com
with:
commit_message: 'Update monthly issue metrics'
commit_user_name: Zen Browser Robot
commit_user_email: zen-browser-auto@users.noreply.github.com

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
@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban ### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community **Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals. individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within **Consequence**: A permanent ban from any sort of public interaction within

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

@ -71,7 +71,7 @@ export var ZenCustomizableUI = new (class {
_moveWindowButtons(window) { _moveWindowButtons(window) {
const windowControls = window.document.getElementsByClassName('titlebar-buttonbox-container'); const windowControls = window.document.getElementsByClassName('titlebar-buttonbox-container');
const toolboxIcons = window.document.getElementById('zen-sidebar-top-buttons-customization-target'); const toolboxIcons = window.document.getElementById('zen-sidebar-top-buttons-customization-target');
if (window.AppConstants.platform === 'macosx'|| window.matchMedia('(-moz-gtk-csd-reversed-placement)').matches) { if (window.AppConstants.platform === 'macosx' || window.matchMedia('(-moz-gtk-csd-reversed-placement)').matches) {
for (let i = 0; i < windowControls.length; i++) { for (let i = 0; i < windowControls.length; i++) {
if (i === 0) { if (i === 0) {
toolboxIcons.prepend(windowControls[i]); toolboxIcons.prepend(windowControls[i]);

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

@ -51,7 +51,7 @@
transform: translateY(-25px); transform: translateY(-25px);
} }
60% { 60% {
opacity: 0.8 ; opacity: 0.8;
transform: translateY(4px); transform: translateY(4px);
} }
100% { 100% {

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;
@ -51,7 +52,7 @@
#tabbrowser-tabbox:has(#tabbrowser-tabpanels[zen-split-view='true']) { #tabbrowser-tabbox:has(#tabbrowser-tabpanels[zen-split-view='true']) {
--zen-split-row-gap: calc(var(--zen-element-separation) + 1px); --zen-split-row-gap: calc(var(--zen-element-separation) + 1px);
--zen-split-column-gap: calc(var(--zen-element-separation)*3 + 1px); --zen-split-column-gap: calc(var(--zen-element-separation) * 3 + 1px);
margin-right: calc(-1 * var(--zen-split-column-gap)); margin-right: calc(-1 * var(--zen-split-column-gap));
:root[zen-right-side='true'] & { :root[zen-right-side='true'] & {
@ -60,12 +61,13 @@
} }
} }
#tabbrowser-tabpanels:has(> [zen-split='true']), #zen-splitview-overlay { #tabbrowser-tabpanels:has(> [zen-split='true']),
margin-right: calc(var(--zen-element-separation) - var(--zen-split-row-gap)/2); #zen-splitview-overlay {
margin-bottom: calc(var(--zen-element-separation) - var(--zen-split-column-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-left: calc(var(--zen-split-row-gap)/-2); margin-left: calc(var(--zen-split-row-gap) / -2);
margin-top: calc(var(--zen-split-column-gap)/-2); margin-top: calc(var(--zen-split-column-gap) / -2);
@media (-moz-bool-pref: 'zen.view.compact') { @media (-moz-bool-pref: 'zen.view.compact') {
:root:not([customizing]) & { :root:not([customizing]) & {
@ -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

@ -9,126 +9,124 @@
flex-direction: column !important; flex-direction: column !important;
} }
& #navigator-toolbox { & #navigator-toolbox {
display: flex !important; display: flex !important;
flex-direction: row !important; flex-direction: row !important;
max-width: unset !important; max-width: unset !important;
min-width: unset !important; min-width: unset !important;
width: 100% !important; width: 100% !important;
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;
-webkit-box-pack: start; -webkit-box-pack: start;
max-width: 10000px !important; max-width: 10000px !important;
--tabstrip-min-height: calc(var(--tab-min-height) - 4 * var(--tab-block-margin)); --tabstrip-min-height: calc(var(--tab-min-height) - 4 * var(--tab-block-margin));
--tab-min-height: 10px !important; --tab-min-height: 10px !important;
} }
#vertical-pinned-tabs-container-separator { #vertical-pinned-tabs-container-separator {
display: none !important; display: none !important;
} }
#zen-essentials-container, #zen-essentials-container,
#vertical-pinned-tabs-container, #vertical-pinned-tabs-container,
#tabbrowser-arrowscrollbox { #tabbrowser-arrowscrollbox {
-webkit-box-flex: 1; -webkit-box-flex: 1;
} }
#vertical-pinned-tabs-container:empty { #vertical-pinned-tabs-container:empty {
-webkit-box-flex: 0 !important; -webkit-box-flex: 0 !important;
width: 0 !important; width: 0 !important;
padding: 0 !important; padding: 0 !important;
margin: 0 !important; margin: 0 !important;
border: none !important; border: none !important;
visibility: collapse !important; visibility: collapse !important;
} }
#navigator-toolbox { #navigator-toolbox {
flex-direction: row !important; flex-direction: row !important;
align-items: center; align-items: center;
} }
#titlebar { #titlebar {
flex-direction: row !important; flex-direction: row !important;
width: 100%; width: 100%;
height: 36px !important; height: 36px !important;
} }
#zen-essentials-container { #zen-essentials-container {
--tab-min-height: 36px !important; --tab-min-height: 36px !important;
display: flex !important; display: flex !important;
flex-direction: row !important; flex-direction: row !important;
padding-inline-end: 0 !important; padding-inline-end: 0 !important;
} }
#vertical-pinned-tabs-container { #vertical-pinned-tabs-container {
display: flex !important; display: flex !important;
flex-direction: row !important; flex-direction: row !important;
padding-inline-end: 0 !important; padding-inline-end: 0 !important;
} }
#zen-essentials-container .tabbrowser-tab { #zen-essentials-container .tabbrowser-tab {
width: 0% !important; width: 0% !important;
} }
#vertical-pinned-tabs-container .tabbrowser-tab { #vertical-pinned-tabs-container .tabbrowser-tab {
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; max-width: 0px !important;
max-width: 0px !important; }
}
} }
#tabbrowser-arrowscrollbox { #tabbrowser-arrowscrollbox {
display: flex !important; display: flex !important;
max-width: -moz-available; max-width: -moz-available;
overflow: hidden !important; overflow: hidden !important;
} }
#TabsToolbar { #TabsToolbar {
flex-direction: row !important; flex-direction: row !important;
gap: 8px; gap: 8px;
overflow: hidden !important; overflow: hidden !important;
display: flex !important; display: flex !important;
} }
#TabsToolbar-customization-target { #TabsToolbar-customization-target {
flex-direction: row !important; flex-direction: row !important;
} }
#tabbrowser-tabs[orient="vertical"] { #tabbrowser-tabs[orient='vertical'] {
flex-direction: row !important; flex-direction: row !important;
} }
tabs { tabs {
flex-direction: row !important; flex-direction: row !important;
} }
#zen-essentials-container { #zen-essentials-container {
container-name: tab-container; container-name: tab-container;
container-type: normal; container-type: normal;
max-width: 36px !important; max-width: 36px !important;
flex: 1 1 36px !important; flex: 1 1 36px !important;
} }
#vertical-pinned-tabs-container { #vertical-pinned-tabs-container {
container-name: tab-container; container-name: tab-container;
container-type: normal; container-type: normal;
max-width: 36px !important; max-width: 36px !important;
min-width: 36px !important; min-width: 36px !important;
flex: 1 1 36px !important; flex: 1 1 36px !important;
} }
#vertical-pinned-tabs-container .tab-close-button { #vertical-pinned-tabs-container .tab-close-button {
display: none !important; display: none !important;
} }
#vertical-pinned-tabs-container .tab-reset-button { #vertical-pinned-tabs-container .tab-reset-button {
@ -136,11 +134,11 @@
} }
#vertical-pinned-tabs-container .tab-label-container { #vertical-pinned-tabs-container .tab-label-container {
display: none !important; display: none !important;
} }
#vertical-pinned-tabs-container .tab-icon-image { #vertical-pinned-tabs-container .tab-icon-image {
margin: 0 !important; margin: 0 !important;
} }
.tabbrowser-tab { .tabbrowser-tab {
@ -162,131 +160,131 @@
} }
@container tab-container (max-width: 80px) { @container tab-container (max-width: 80px) {
.tab-close-button { .tab-close-button {
margin-right: 0px !important; margin-right: 0px !important;
} }
.tab-icon-image { .tab-icon-image {
padding: 0 !important; padding: 0 !important;
margin-left: min(2.5px, 5%) !important; margin-left: min(2.5px, 5%) !important;
margin-right: min(10px, 5%) !important; margin-right: min(10px, 5%) !important;
} }
.tab-label-container, .tab-label-container,
.tab-content { .tab-content {
margin: 0 !important; margin: 0 !important;
padding-left: min(8px, 5%) !important; padding-left: min(8px, 5%) !important;
padding-right: min(8px, 5%) !important; padding-right: min(8px, 5%) !important;
} }
} }
@container tab-container (max-width: 44px) { @container tab-container (max-width: 44px) {
.tab-label-container { .tab-label-container {
display: none !important; display: none !important;
}
.tab-content {
justify-content: space-around !important;
}
.tab-close-button {
display: none !important;
}
.tabbrowser-tab[selected] {
& .tab-icon-image,
.tab-icon-stack {
display: none !important;
} }
.tab-content { & .tab-content {
justify-content: space-around !important; justify-content: space-around !important;
padding: 0 !important;
} }
.tab-close-button { .tab-close-button {
display: none !important; display: block !important;
}
.tabbrowser-tab[selected] {
& .tab-icon-image,
.tab-icon-stack {
display: none !important;
}
& .tab-content {
justify-content: space-around !important;
padding: 0 !important;
}
.tab-close-button {
display: block !important;
}
} }
}
} }
#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;
height: 45%; height: 45%;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
background: hsl(255, 10%, 100%); background: hsl(255, 10%, 100%);
} }
/* Other UI Elements */ /* Other UI Elements */
#zen-current-workspace-indicator { #zen-current-workspace-indicator {
display: none !important; display: none !important;
} }
#zen-sidebar-splitter { #zen-sidebar-splitter {
display: none !important; display: none !important;
} }
#tabbrowser-tabpanels { #tabbrowser-tabpanels {
padding-left: var(--zen-element-separation) !important; padding-left: var(--zen-element-separation) !important;
} }
#appcontent * { #appcontent * {
overflow: visible !important; overflow: visible !important;
} }
#TabsToolbar-customization-target::after { #TabsToolbar-customization-target::after {
display: none !important; display: none !important;
} }
#zen-sidebar-icons-wrapper { #zen-sidebar-icons-wrapper {
width: auto !important; width: auto !important;
padding: 0 !important; padding: 0 !important;
} }
/* Height Adjustments */ /* Height Adjustments */
#vertical-pinned-tabs-container, #vertical-pinned-tabs-container,
#zen-essentials-container, #zen-essentials-container,
#tabbrowser-arrowscrollbox { #tabbrowser-arrowscrollbox {
max-height: none !important; max-height: none !important;
} }
#PanelUI-zen-gradient-generator { #PanelUI-zen-gradient-generator {
min-width: 390px !important; min-width: 390px !important;
} }
#zen-essentials-container:not(:empty), #zen-essentials-container:not(:empty),
#vertical-pinned-tabs-container:not(:empty), #vertical-pinned-tabs-container:not(:empty),
#tabbrowser-arrowscrollbox { #tabbrowser-arrowscrollbox {
-webkit-box-flex: 1; -webkit-box-flex: 1;
min-width: min-content; min-width: min-content;
width: auto !important; width: auto !important;
} }
#vertical-pinned-tabs-container:not(:empty) { #vertical-pinned-tabs-container:not(:empty) {
display: -webkit-box !important; display: -webkit-box !important;
-webkit-box-orient: horizontal; -webkit-box-orient: horizontal;
min-width: fit-content !important; min-width: fit-content !important;
width: fit-content !important; width: fit-content !important;
position: relative; position: relative;
margin-right: -1px !important; margin-right: -1px !important;
} }
#vertical-pinned-tabs-container:not(:empty) .tabbrowser-tab { #vertical-pinned-tabs-container:not(:empty) .tabbrowser-tab {
position: relative; position: relative;
display: -webkit-box !important; display: -webkit-box !important;
} }
#tabbrowser-arrowscrollbox { #tabbrowser-arrowscrollbox {
margin-left: 0 !important; margin-left: 0 !important;
} }
#vertical-pinned-tabs-container:empty, #vertical-pinned-tabs-container:empty,
#zen-essentials-container:empty { #zen-essentials-container:empty {
-webkit-box-flex: 0 !important; -webkit-box-flex: 0 !important;
width: 0 !important; width: 0 !important;
min-width: 0 !important; min-width: 0 !important;
padding: 0 !important; padding: 0 !important;
margin: 0 !important; margin: 0 !important;
border: none !important; border: none !important;
visibility: collapse !important; visibility: collapse !important;
} }
#nav-bar { #nav-bar {
@ -299,39 +297,39 @@
} }
hbox#nav-bar-customization-target toolbarbutton.chromeclass-toolbar-additional:nth-of-type(1) { hbox#nav-bar-customization-target toolbarbutton.chromeclass-toolbar-additional:nth-of-type(1) {
padding-inline-start: var(--toolbar-start-end-padding) !important; padding-inline-start: var(--toolbar-start-end-padding) !important;
} }
toolbar#PersonalToolbar { toolbar#PersonalToolbar {
padding-left: 6px !important; padding-left: 6px !important;
} }
.tab-context-line { .tab-context-line {
width: 100% !important; width: 100% !important;
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;
} }
#TabsToolbar-customization-target toolbarbutton, #TabsToolbar-customization-target toolbarbutton,
#TabsToolbar-customization-target toolbarpaletteitem { #TabsToolbar-customization-target toolbarpaletteitem {
-webkit-box-flex: 0 !important; -webkit-box-flex: 0 !important;
min-width: min-content; min-width: min-content;
width: auto !important; width: auto !important;
.toolbarbutton-text { .toolbarbutton-text {
display: none !important; display: none !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

@ -3,7 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
/* Here, we contain all the theme related variables, for example theme /* Here, we contain all the theme related variables, for example theme
* colors, border radius, etc. * colors, border radius, etc.
* We have `--zen-border-radius` and `--zen-primary-color` as variables. * We have `--zen-border-radius` and `--zen-primary-color` as variables.
*/ */
@ -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;
} }
@ -476,7 +474,7 @@
max-width: calc(100% - var(--zen-toolbox-padding) * 4); max-width: calc(100% - var(--zen-toolbox-padding) * 4);
} }
& #zen-current-workspace-indicator-icon:not([hidden]) + #zen-current-workspace-indicator-name { & #zen-current-workspace-indicator-icon:not([hidden]) + #zen-current-workspace-indicator-name {
padding-left: 24px; padding-left: 24px;
} }
} }

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 });
@ -313,7 +309,7 @@
return; return;
} else if (activationMethod === 'meta' && !event.metaKey) { } else if (activationMethod === 'meta' && !event.metaKey) {
return; return;
}else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') { } else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') {
return; return;
} }
@ -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,17 +203,17 @@
// 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 };
} }
} }
// 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 };
} }
getColorFromPosition(x, y) { getColorFromPosition(x, y) {
@ -245,7 +248,7 @@
onThemePickerClick(event) { onThemePickerClick(event) {
event.preventDefault(); event.preventDefault();
if (event.button !== 0 || this.dragging ) return; if (event.button !== 0 || this.dragging) return;
const gradient = this.panel.querySelector('.zen-theme-picker-gradient'); const gradient = this.panel.querySelector('.zen-theme-picker-gradient');
const rect = gradient.getBoundingClientRect(); const rect = gradient.getBoundingClientRect();
const padding = 90; // each side const padding = 90; // each side
@ -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,28 +289,24 @@
this.updateCurrentWorkspace(true); this.updateCurrentWorkspace(true);
} }
}
onDotMouseDown(event) {
event.preventDefault();
if (event.button === 2) {
return;
} }
this.dragging = true;
this.draggedDot = event.target;
this.draggedDot.style.zIndex = 1;
this.draggedDot.classList.add('dragging');
// Store the starting position of the drag onDotMouseDown(event) {
this.dragStartPosition = { event.preventDefault();
x: event.clientX, if (event.button === 2) {
y: event.clientY return;
}; }
} this.dragging = true;
this.draggedDot = event.target;
this.draggedDot.style.zIndex = 1;
this.draggedDot.classList.add('dragging');
// Store the starting position of the drag
this.dragStartPosition = {
x: event.clientX,
y: event.clientY,
};
}
onDotMouseMove(event) { onDotMouseMove(event) {
if (this.dragging) { if (this.dragging) {
@ -324,7 +322,7 @@
const radius = (rect.width - padding) / 2; const radius = (rect.width - padding) / 2;
let pixelX = event.clientX; let pixelX = event.clientX;
let pixelY = event.clientY; let pixelY = event.clientY;
const distance = Math.sqrt((pixelX - centerX) **2 + (pixelY - centerY) **2); const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
if (distance > radius) { if (distance > radius) {
const angle = Math.atan2(pixelY - centerY, pixelX - centerX); const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
pixelX = centerX + Math.cos(angle) * radius; pixelX = centerX + Math.cos(angle) * radius;
@ -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,9 +487,9 @@
} }
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%)';
} }
getSingleRGBColor(color, forToolbar = false) { getSingleRGBColor(color, forToolbar = false) {
@ -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,
if(n>9){ f,
[r,g,b,a]=d=d.split(","),n=d.length; t,
if(n<3||n>4)return null; h,
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 i = parseInt,
}else{ m = Math.round,
if(n==8||n==6||n<4)return null; a = typeof c1 == 'string';
if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:""); if (typeof p != 'number' || p < -1 || p > 1 || typeof c0 != 'string' || (c0[0] != 'r' && c0[0] != '#') || (c1 && !a))
d=i(d.slice(1),16); return null;
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 (!this.pSBCr)
else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1 this.pSBCr = (d) => {
}return x}; let n = d.length,
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; x = {};
if(!f||!t)return null; if (n > 9) {
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); ([r, g, b, a] = d = d.split(',')), (n = d.length);
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); if (n < 3 || n > 4) return null;
a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0; (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);
if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")"; } else {
else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2) 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] : '');
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);
else (x.r = d >> 16), (x.g = (d >> 8) & 255), (x.b = d & 255), (x.a = -1);
}
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,24 +755,23 @@
} }
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;
} }
const isCustom = dot.classList.contains('custom'); const isCustom = dot.classList.contains('custom');
return {c: isCustom ? color : color.match(/\d+/g).map(Number), isCustom}; return { c: isCustom ? color : color.match(/\d+/g).map(Number), isCustom };
}); });
const gradient = ZenThemePicker.getTheme(colors, this.currentOpacity, this.currentRotation, this.currentTexture); const gradient = ZenThemePicker.getTheme(colors, this.currentOpacity, this.currentRotation, this.currentTexture);
let currentWorkspace = await ZenWorkspaces.getActiveWorkspace(); let currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
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();
} }
@ -751,10 +779,9 @@
} }
async handlePanelClose() { async handlePanelClose() {
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(
if (Services.prefs.getBoolPref('zen.keyboard.shortcuts.enabled', false)) { 'MozBeforeInitialXULLayout',
gZenKeyboardShortcutsManager.beforeInit(); () => {
} if (Services.prefs.getBoolPref('zen.keyboard.shortcuts.enabled', false)) {
}, { once: true }); gZenKeyboardShortcutsManager.beforeInit();
}
},
{ 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;
@ -56,7 +65,7 @@
return; return;
} }
await this._refreshPinnedTabs(newWorkspace,{ init: onInit }); await this._refreshPinnedTabs(newWorkspace, { init: onInit });
} }
get enabled() { get enabled() {
@ -70,9 +79,9 @@
return this._enabled; return this._enabled;
} }
async _refreshPinnedTabs(currentWorkspace,{ init = false } = {}) { async _refreshPinnedTabs(currentWorkspace, { init = false } = {}) {
await this._initializePinsCache(); await this._initializePinsCache();
await this._initializePinnedTabs(init,currentWorkspace); await this._initializePinnedTabs(init, currentWorkspace);
} }
async _initializePinsCache() { async _initializePinsCache() {
@ -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(
try { pins.map(async (pin) => {
const image = await this.getFaviconAsBase64(Services.io.newURI(pin.url).spec); try {
return { const image = await this.getFaviconAsBase64(Services.io.newURI(pin.url).spec);
...pin, return {
iconUrl: image || null ...pin,
}; iconUrl: image || null,
} catch(ex) { };
// If favicon fetch fails, continue without icon } catch (ex) {
return { // If favicon fetch fails, continue without icon
...pin, return {
iconUrl: null ...pin,
}; 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, {
title: pin.title, url: pin.url,
triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL title: pin.title,
}], 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;
} }
@ -448,19 +457,19 @@
} }
_handleTabSwitch(selectedTab) { _handleTabSwitch(selectedTab) {
if(selectedTab !== gBrowser.selectedTab) { if (selectedTab !== gBrowser.selectedTab) {
return; return;
} }
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);
if (!nextTab) { if (!nextTab) {
ZenWorkspaces._createNewTabForWorkspace({ uuid: ZenWorkspaces.activeWorkspace }); ZenWorkspaces._createNewTabForWorkspace({ uuid: ZenWorkspaces.activeWorkspace });
nextTab = findNextTab(1) || findNextTab(-1); 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, {
title: pin.title, url: pin.url,
triggeringPrincipal_base64: lazy.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL title: pin.title,
}]; triggeringPrincipal_base64: lazy.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL,
},
];
state.image = pin.iconUrl || null; state.image = pin.iconUrl || null;
state.index = 0; state.index = 0;
@ -507,15 +518,15 @@
// 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('')
); );
// Return as a proper data URL // Return as a proper data URL
return `data:${faviconData.mimeType};base64,${base64String}`; return `data:${faviconData.mimeType};base64,${base64String}`;
} catch (ex) { } catch (ex) {
// console.error("Failed to get favicon:", ex); // console.error("Failed to get favicon:", ex);
return `page-icon:${pageUrl}`; // Use this as a fallback return `page-icon:${pageUrl}`; // Use this as a fallback
} }
} }
@ -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);
} }
@ -589,14 +600,16 @@
if (!this.enabled) { if (!this.enabled) {
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,26 +98,31 @@ 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, {
title: pin.title, uuid: pin.uuid,
url: pin.isGroup ? null : pin.url, title: pin.title,
container_id: pin.containerTabId || null, url: pin.isGroup ? null : pin.url,
workspace_uuid: pin.workspaceUuid || null, container_id: pin.containerTabId || null,
position: newPosition, workspace_uuid: pin.workspaceUuid || null,
is_essential: pin.isEssential || false, position: newPosition,
is_group: pin.isGroup || false, is_essential: pin.isEssential || false,
parent_uuid: pin.parentUuid || null, is_group: pin.isGroup || false,
now parent_uuid: pin.parentUuid || null,
}); 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, {
timestamp: Math.floor(now / 1000) uuid: pin.uuid,
}); 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, {
timestamp: now uuid: changedUuid,
}); 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, {
timestamp: Math.floor(now / 1000) uuid,
}); 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, {
timestamp: Math.floor(now / 1000) uuid: pin.uuid,
}); 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

@ -303,7 +303,7 @@ class ZenBrowserManagerSidebar extends ZenDOMOperatedFeature {
// Don't reload content if at least one of the panel tabs was loaded // Don't reload content if at least one of the panel tabs was loaded
if (this._lastOpenedPanel) { if (this._lastOpenedPanel) {
return; return;
} }
let data = this.sidebarData; let data = this.sidebarData;

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;
@ -187,27 +179,27 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
* @param {boolean} recursive * @param {boolean} recursive
* @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();
@ -364,30 +347,29 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
} }
const splitNode = this.getSplitNodeFromTab(tab); const splitNode = this.getSplitNodeFromTab(tab);
const posToRoot = {...splitNode.positionToRoot}; const posToRoot = { ...splitNode.positionToRoot };
const browserRect = browser.getBoundingClientRect(); const browserRect = browser.getBoundingClientRect();
const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect); const hoverSide = this.calculateHoverSide(event.clientX, event.clientY, browserRect);
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);
@ -484,9 +464,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
} }
_swapField(fieldName, obj1, obj2) { _swapField(fieldName, obj1, obj2) {
const swap = obj1[fieldName]; const swap = obj1[fieldName];
obj1[fieldName] = obj2[fieldName]; obj1[fieldName] = obj2[fieldName];
obj2[fieldName] = swap; obj2[fieldName] = swap;
} }
/** /**
@ -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,16 +741,16 @@ 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);
for (let i = 0; i < tabs.length - 1; i += 2) { for (let i = 0; i < tabs.length - 1; i += 2) {
const columnNode = new SplitNode('column', rowWidth, 100); const columnNode = new SplitNode('column', rowWidth, 100);
columnNode.children = [new SplitLeafNode(tabs[i], 50), new SplitLeafNode(tabs[i + 1], 50)]; columnNode.children = [new SplitLeafNode(tabs[i], 50), new SplitLeafNode(tabs[i + 1], 50)];
rootNode.addChild(columnNode); rootNode.addChild(columnNode);
} }
if (tabs.length % 2 !== 0) { if (tabs.length % 2 !== 0) {
@ -798,7 +782,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
*/ */
applyGridLayout(splitNode) { applyGridLayout(splitNode) {
if (!splitNode.positionToRoot) { if (!splitNode.positionToRoot) {
splitNode.positionToRoot = {top: 0, bottom: 0, left: 0, right: 0}; splitNode.positionToRoot = { top: 0, bottom: 0, left: 0, right: 0 };
} }
const nodeRootPosition = splitNode.positionToRoot; const nodeRootPosition = splitNode.positionToRoot;
if (!splitNode.children) { if (!splitNode.children) {
@ -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;
@ -946,21 +937,25 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
reducingMovement -= amountReduced; reducingMovement -= amountReduced;
if (reducingMovement <= 0) break; if (reducingMovement <= 0) break;
} }
const increasingMovement = Math.max(movementPercent, - movementPercent) - reducingMovement; const increasingMovement = Math.max(movementPercent, -movementPercent) - reducingMovement;
const increaseIndex = gridIdx + (movementPercent < 0 ? 1 : 0); const increaseIndex = gridIdx + (movementPercent < 0 ? 1 : 0);
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(
document.removeEventListener('mousemove', dragFunc); 'mouseup',
setCursor('auto'); () => {
this.tabBrowserPanel.removeAttribute('zen-split-resizing'); document.removeEventListener('mousemove', dragFunc);
}, {once: true}); setCursor('auto');
} this.tabBrowserPanel.removeAttribute('zen-split-resizing');
},
{ 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',
@ -61,16 +46,16 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
true true
); );
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
this, this,
'shouldOpenNewTabIfLastUnpinnedTabIsClosed', 'shouldOpenNewTabIfLastUnpinnedTabIsClosed',
'zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', 'zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed',
false false
); );
XPCOMUtils.defineLazyPreferenceGetter( XPCOMUtils.defineLazyPreferenceGetter(
this, this,
'containerSpecificEssentials', 'containerSpecificEssentials',
'zen.workspaces.container-specific-essentials-enabled', 'zen.workspaces.container-specific-essentials-enabled',
false false
); );
ChromeUtils.defineLazyGetter(this, 'tabContainer', () => document.getElementById('tabbrowser-tabs')); ChromeUtils.defineLazyGetter(this, 'tabContainer', () => document.getElementById('tabbrowser-tabs'));
this._activeWorkspace = Services.prefs.getStringPref('zen.workspaces.active', ''); this._activeWorkspace = Services.prefs.getStringPref('zen.workspaces.active', '');
@ -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(
this._workspaceBookmarksCache = null; async function observe(subject) {
await this.workspaceBookmarks(); this._workspaceBookmarksCache = null;
this._invalidateBookmarkContainers(); await this.workspaceBookmarks();
}.bind(this), "workspace-bookmarks-updated"); this._invalidateBookmarkContainers();
}.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();
@ -146,54 +134,57 @@ 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(
if (!this.workspaceEnabled) return; 'wheel',
async (event) => {
if (!this.workspaceEnabled) return;
// Only process non-gesture scrolls // Only process non-gesture scrolls
if (event.deltaMode !== 1) return; if (event.deltaMode !== 1) return;
const isVerticalScroll = event.deltaY && !event.deltaX; const isVerticalScroll = event.deltaY && !event.deltaX;
const isHorizontalScroll = event.deltaX && !event.deltaY; const isHorizontalScroll = event.deltaX && !event.deltaY;
//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 = {
ctrl: event.ctrlKey,
alt: event.altKey,
shift: event.shiftKey,
meta: event.metaKey,
};
const activationKeyMap = { if (this.activationMethod in activationKeyMap && !activationKeyMap[this.activationMethod]) {
ctrl: event.ctrlKey, return;
alt: event.altKey, }
shift: event.shiftKey,
meta: event.metaKey,
};
if (this.activationMethod in activationKeyMap && !activationKeyMap[this.activationMethod]) {
return;
} }
}
const currentTime = Date.now(); const currentTime = Date.now();
if (currentTime - this._lastScrollTime < scrollCooldown) return; if (currentTime - this._lastScrollTime < scrollCooldown) return;
//this decides which delta to use //this decides which delta to use
const delta = isVerticalScroll ? event.deltaY : event.deltaX; const delta = isVerticalScroll ? event.deltaY : event.deltaX;
if (Math.abs(delta) < scrollThreshold) return; if (Math.abs(delta) < scrollThreshold) return;
// Determine scroll direction // Determine scroll direction
let rawDirection = delta > 0 ? 1 : -1; let rawDirection = delta > 0 ? 1 : -1;
let direction = this.naturalScroll ? -1 : 1; let direction = this.naturalScroll ? -1 : 1;
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) {
@ -466,7 +457,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
_createNewTabForWorkspace(window) { _createNewTabForWorkspace(window) {
let tab = gZenUIManager.openAndChangeToTab(Services.prefs.getStringPref('browser.startup.homepage')); let tab = gZenUIManager.openAndChangeToTab(Services.prefs.getStringPref('browser.startup.homepage'));
if(window.uuid){ if (window.uuid) {
tab.setAttribute('zen-workspace-id', window.uuid); tab.setAttribute('zen-workspace-id', window.uuid);
} }
return tab; return 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,10 +525,10 @@ 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() {
let container = document.getElementById('PanelUI-zen-workspaces-icon-picker-wrapper'); let container = document.getElementById('PanelUI-zen-workspaces-icon-picker-wrapper');
let searchInput = document.getElementById('PanelUI-zen-workspaces-icon-search-input'); let searchInput = document.getElementById('PanelUI-zen-workspaces-icon-search-input');
@ -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);
@ -884,53 +873,53 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
element.className = 'zen-workspace-last-place-drop-target'; element.className = 'zen-workspace-last-place-drop-target';
element.addEventListener( element.addEventListener(
'dragover', 'dragover',
function (event) { function (event) {
if (this.isReorderModeOn(browser) && this.draggedElement) { if (this.isReorderModeOn(browser) && this.draggedElement) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}
}.bind(browser.ZenWorkspaces)
);
element.addEventListener(
'dragenter',
function (event) {
if (this.isReorderModeOn(browser) && this.draggedElement) {
element.classList.add('dragover');
}
}.bind(browser.ZenWorkspaces)
);
element.addEventListener(
'dragleave',
function (event) {
element.classList.remove('dragover');
}.bind(browser.ZenWorkspaces)
);
element.addEventListener(
'drop',
async function (event) {
event.preventDefault(); event.preventDefault();
element.classList.remove('dragover'); event.dataTransfer.dropEffect = 'move';
}
}.bind(browser.ZenWorkspaces)
);
if (this.isReorderModeOn(browser)) { element.addEventListener(
const draggedWorkspaceId = event.dataTransfer.getData('text/plain'); 'dragenter',
await this.moveWorkspaceToEnd(draggedWorkspaceId); function (event) {
if (this.isReorderModeOn(browser) && this.draggedElement) {
element.classList.add('dragover');
}
}.bind(browser.ZenWorkspaces)
);
if (this.draggedElement) { element.addEventListener(
this.draggedElement.classList.remove('dragging'); 'dragleave',
this.draggedElement = null; function (event) {
} element.classList.remove('dragover');
}.bind(browser.ZenWorkspaces)
);
element.addEventListener(
'drop',
async function (event) {
event.preventDefault();
element.classList.remove('dragover');
if (this.isReorderModeOn(browser)) {
const draggedWorkspaceId = event.dataTransfer.getData('text/plain');
await this.moveWorkspaceToEnd(draggedWorkspaceId);
if (this.draggedElement) {
this.draggedElement.classList.remove('dragging');
this.draggedElement = null;
} }
}.bind(browser.ZenWorkspaces) }
}.bind(browser.ZenWorkspaces)
); );
return element; return element;
}; };
if(clearCache) { if (clearCache) {
browser.ZenWorkspaces._workspaceCache = null; browser.ZenWorkspaces._workspaceCache = null;
browser.ZenWorkspaces._workspaceBookmarksCache = null; browser.ZenWorkspaces._workspaceBookmarksCache = null;
} }
@ -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++;
@ -1211,7 +1200,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
_createNewTabForWorkspace(window) { _createNewTabForWorkspace(window) {
let tab = gZenUIManager.openAndChangeToTab(BROWSER_NEW_TAB_URL); let tab = gZenUIManager.openAndChangeToTab(BROWSER_NEW_TAB_URL);
if(window.uuid){ if (window.uuid) {
tab.setAttribute('zen-workspace-id', window.uuid); tab.setAttribute('zen-workspace-id', window.uuid);
} }
} }
@ -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;
} }
@ -1670,7 +1663,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._emojis = null; this._emojis = null;
} }
async changeWorkspaceShortcut(offset = 1){ async changeWorkspaceShortcut(offset = 1) {
// Cycle through workspaces // Cycle through workspaces
let workspaces = await this._workspaces(); let workspaces = await this._workspaces();
let activeWorkspace = await this.getActiveWorkspace(); let activeWorkspace = await this.getActiveWorkspace();
@ -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,29 +142,34 @@ 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, {
name: workspace.name, uuid: workspace.uuid,
icon: workspace.icon || null, name: workspace.name,
is_default: workspace.default ? 1 : 0, icon: workspace.icon || null,
container_id: workspace.containerTabId || null, is_default: workspace.default ? 1 : 0,
now, container_id: workspace.containerTabId || null,
position: newPosition, now,
theme_type: workspace.theme?.type || null, position: newPosition,
theme_colors: workspace.theme ? JSON.stringify(workspace.theme.gradientColors) : null, theme_type: workspace.theme?.type || null,
theme_opacity: workspace.theme?.opacity || null, theme_colors: workspace.theme ? JSON.stringify(workspace.theme.gradientColors) : null,
theme_rotation: workspace.theme?.rotation || null, theme_opacity: workspace.theme?.opacity || null,
theme_texture: workspace.theme?.texture || null theme_rotation: workspace.theme?.rotation || 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, {
timestamp: Math.floor(now / 1000) uuid: workspace.uuid,
}); 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'), ? {
gradientColors: JSON.parse(row.getResultByName('theme_colors')), type: row.getResultByName('theme_type'),
opacity: row.getResultByName('theme_opacity'), gradientColors: JSON.parse(row.getResultByName('theme_colors')),
rotation: row.getResultByName('theme_rotation'), opacity: row.getResultByName('theme_opacity'),
texture: row.getResultByName('theme_texture') rotation: row.getResultByName('theme_rotation'),
} : null texture: row.getResultByName('theme_texture'),
}
: null,
})); }));
}, },
@ -201,27 +211,30 @@ var ZenWorkspacesStorage = {
await this.lazy.PlacesUtils.withConnectionWrapper('ZenWorkspacesStorage.removeWorkspace', async (db) => { await this.lazy.PlacesUtils.withConnectionWrapper('ZenWorkspacesStorage.removeWorkspace', async (db) => {
await db.execute( await db.execute(
` `
DELETE FROM zen_workspaces WHERE uuid = :uuid DELETE FROM zen_workspaces WHERE uuid = :uuid
`, `,
{ uuid } { uuid }
); );
// 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, {
timestamp: Math.floor(now / 1000) uuid,
}); 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, {
timestamp: Math.floor(now / 1000) uuid,
}); 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, {
timestamp: Math.floor(now / 1000) uuid,
}); 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, {
colors: JSON.stringify(theme.gradientColors), type: theme.type,
opacity: theme.opacity, colors: JSON.stringify(theme.gradientColors),
rotation: theme.rotation, opacity: theme.opacity,
texture: theme.texture, rotation: theme.rotation,
now: Date.now(), texture: theme.texture,
uuid now: Date.now(),
}); 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, {
timestamp: Math.floor(now / 1000) uuid: workspace.uuid,
}); 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(
await db.execute(`DELETE FROM zen_bookmarks_workspaces_changes`); 'ZenWorkspaceBookmarksStorage.clearChangedIDs',
}); async (db) => {
await db.execute(`DELETE FROM zen_bookmarks_workspaces_changes`);
}
);
}, },
}; };
ZenWorkspacesStorage.init(); ZenWorkspacesStorage.init();

View file

@ -1,36 +1,34 @@
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) {
CryptoWrapper.call(this, collection, id); CryptoWrapper.call(this, 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
function ZenWorkspacesStore(name, engine) { function ZenWorkspacesStore(name, engine) {
Store.call(this, name, engine); Store.call(this, name, engine);
} }
ZenWorkspacesStore.prototype = Object.create(Store.prototype); ZenWorkspacesStore.prototype = Object.create(Store.prototype);
@ -40,8 +38,8 @@ ZenWorkspacesStore.prototype.constructor = ZenWorkspacesStore;
* Initializes the store by loading the current changeset. * Initializes the store by loading the current changeset.
*/ */
ZenWorkspacesStore.prototype.initialize = async function () { ZenWorkspacesStore.prototype.initialize = async function () {
await Store.prototype.initialize.call(this); await Store.prototype.initialize.call(this);
// Additional initialization if needed // Additional initialization if needed
}; };
/** /**
@ -49,17 +47,17 @@ ZenWorkspacesStore.prototype.initialize = async function () {
* @returns {Object} An object mapping workspace UUIDs to true. * @returns {Object} An object mapping workspace UUIDs to true.
*/ */
ZenWorkspacesStore.prototype.getAllIDs = async function () { ZenWorkspacesStore.prototype.getAllIDs = async function () {
try { try {
const workspaces = await ZenWorkspacesStorage.getWorkspaces(); const workspaces = await ZenWorkspacesStorage.getWorkspaces();
const ids = {}; const ids = {};
for (const workspace of workspaces) { for (const workspace of workspaces) {
ids[workspace.uuid] = true; ids[workspace.uuid] = true;
}
return ids;
} catch (error) {
this._log.error("Error fetching all workspace IDs", error);
throw error;
} }
return ids;
} catch (error) {
this._log.error('Error fetching all workspace IDs', error);
throw error;
}
}; };
/** /**
@ -68,19 +66,19 @@ ZenWorkspacesStore.prototype.getAllIDs = async function () {
* @param {String} newID - The new UUID. * @param {String} newID - The new UUID.
*/ */
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);
// Mark the new ID as changed for sync // Mark the new ID as changed for sync
await ZenWorkspacesStorage.markChanged(newID); await ZenWorkspacesStorage.markChanged(newID);
}
} catch (error) {
this._log.error(`Error changing workspace ID from ${oldID} to ${newID}`, error);
throw error;
} }
} catch (error) {
this._log.error(`Error changing workspace ID from ${oldID} to ${newID}`, error);
throw error;
}
}; };
/** /**
@ -89,13 +87,13 @@ ZenWorkspacesStore.prototype.changeItemID = async function (oldID, newID) {
* @returns {Boolean} True if the workspace exists, false otherwise. * @returns {Boolean} True if the workspace exists, false otherwise.
*/ */
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;
} }
}; };
/** /**
@ -105,34 +103,34 @@ ZenWorkspacesStore.prototype.itemExists = async function (id) {
* @returns {ZenWorkspaceRecord} The workspace record. * @returns {ZenWorkspaceRecord} The workspace record.
*/ */
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) {
record.name = workspace.name; record.name = workspace.name;
record.icon = workspace.icon; record.icon = workspace.icon;
record.default = workspace.default; record.default = workspace.default;
record.containerTabId = workspace.containerTabId; record.containerTabId = workspace.containerTabId;
record.position = workspace.position; record.position = workspace.position;
if (workspace.theme) { if (workspace.theme) {
record.theme_type = workspace.theme.type; record.theme_type = workspace.theme.type;
record.theme_colors = JSON.stringify(workspace.theme.gradientColors); record.theme_colors = JSON.stringify(workspace.theme.gradientColors);
record.theme_opacity = workspace.theme.opacity; record.theme_opacity = workspace.theme.opacity;
record.theme_rotation = workspace.theme.rotation; record.theme_rotation = workspace.theme.rotation;
record.theme_texture = workspace.theme.texture; record.theme_texture = workspace.theme.texture;
} }
record.deleted = false; record.deleted = false;
} else { } else {
record.deleted = true; record.deleted = true;
}
return record;
} catch (error) {
this._log.error(`Error creating record for workspace ID ${id}`, error);
throw error;
} }
return record;
} catch (error) {
this._log.error(`Error creating record for workspace ID ${id}`, error);
throw error;
}
}; };
/** /**
@ -140,28 +138,30 @@ ZenWorkspacesStore.prototype.createRecord = async function (id, collection) {
* @param {ZenWorkspaceRecord} record - The workspace record to create. * @param {ZenWorkspaceRecord} record - The workspace record to create.
*/ */
ZenWorkspacesStore.prototype.create = async function (record) { ZenWorkspacesStore.prototype.create = async function (record) {
try { try {
this._validateRecord(record); this._validateRecord(record);
const workspace = { const workspace = {
uuid: record.id, uuid: record.id,
name: record.name, name: record.name,
icon: record.icon, icon: record.icon,
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, ? {
gradientColors: JSON.parse(record.theme_colors), type: record.theme_type,
opacity: record.theme_opacity, gradientColors: JSON.parse(record.theme_colors),
rotation: record.theme_rotation, opacity: record.theme_opacity,
texture: record.theme_texture rotation: record.theme_rotation,
} : null texture: record.theme_texture,
}; }
await ZenWorkspacesStorage.saveWorkspace(workspace,false); : null,
} catch (error) { };
this._log.error(`Error creating workspace with ID ${record.id}`, error); await ZenWorkspacesStorage.saveWorkspace(workspace, false);
throw error; } catch (error) {
} this._log.error(`Error creating workspace with ID ${record.id}`, error);
throw error;
}
}; };
/** /**
@ -169,13 +169,13 @@ ZenWorkspacesStore.prototype.create = async function (record) {
* @param {ZenWorkspaceRecord} record - The workspace record to update. * @param {ZenWorkspaceRecord} record - The workspace record to update.
*/ */
ZenWorkspacesStore.prototype.update = async function (record) { ZenWorkspacesStore.prototype.update = async function (record) {
try { try {
this._validateRecord(record); this._validateRecord(record);
await this.create(record); // Reuse create for update await this.create(record); // Reuse create for update
} catch (error) { } catch (error) {
this._log.error(`Error updating workspace with ID ${record.id}`, error); this._log.error(`Error updating workspace with ID ${record.id}`, error);
throw error; throw error;
} }
}; };
/** /**
@ -183,24 +183,24 @@ ZenWorkspacesStore.prototype.update = async function (record) {
* @param {ZenWorkspaceRecord} record - The workspace record to remove. * @param {ZenWorkspaceRecord} record - The workspace record to remove.
*/ */
ZenWorkspacesStore.prototype.remove = async function (record) { ZenWorkspacesStore.prototype.remove = async function (record) {
try { try {
await ZenWorkspacesStorage.removeWorkspace(record.id, false); await ZenWorkspacesStorage.removeWorkspace(record.id, false);
} catch (error) { } catch (error) {
this._log.error(`Error removing workspace with ID ${record.id}`, error); this._log.error(`Error removing workspace with ID ${record.id}`, error);
throw error; throw error;
} }
}; };
/** /**
* Wipes all workspaces from the storage. * Wipes all workspaces from the storage.
*/ */
ZenWorkspacesStore.prototype.wipe = async function () { 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,48 +208,48 @@ 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") {
throw new Error(`Invalid theme_colors for workspace ID ${record.id}`);
}
try {
JSON.parse(record.theme_colors);
} catch (e) {
throw new Error(`Invalid theme_colors JSON for workspace ID ${record.id}`);
}
if (record.theme_opacity != null && typeof record.theme_opacity !== "number") {
throw new Error(`Invalid theme_opacity for workspace ID ${record.id}`);
}
if (record.theme_rotation != null && typeof record.theme_rotation !== "number") {
throw new Error(`Invalid theme_rotation for workspace ID ${record.id}`);
}
if (record.theme_texture != null && typeof record.theme_texture !== "number") {
throw new Error(`Invalid theme_texture for workspace ID ${record.id}`);
}
} }
if (!record.theme_colors || typeof record.theme_colors !== 'string') {
throw new Error(`Invalid theme_colors for workspace ID ${record.id}`);
}
try {
JSON.parse(record.theme_colors);
} catch (e) {
throw new Error(`Invalid theme_colors JSON for workspace ID ${record.id}`);
}
if (record.theme_opacity != null && typeof record.theme_opacity !== 'number') {
throw new Error(`Invalid theme_opacity for workspace ID ${record.id}`);
}
if (record.theme_rotation != null && typeof record.theme_rotation !== 'number') {
throw new Error(`Invalid theme_rotation for workspace ID ${record.id}`);
}
if (record.theme_texture != null && typeof record.theme_texture !== 'number') {
throw new Error(`Invalid theme_texture for workspace ID ${record.id}`);
}
}
}; };
/** /**
@ -257,24 +257,24 @@ ZenWorkspacesStore.prototype._validateRecord = function (record) {
* @returns {Object} An object mapping workspace UUIDs to their change timestamps. * @returns {Object} An object mapping workspace UUIDs to their change timestamps.
*/ */
ZenWorkspacesStore.prototype.getChangedIDs = async function () { 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;
} }
}; };
/** /**
* Clears all recorded changes after a successful sync. * Clears all recorded changes after a successful sync.
*/ */
ZenWorkspacesStore.prototype.clearChangedIDs = async function () { 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;
} }
}; };
/** /**
@ -282,29 +282,28 @@ ZenWorkspacesStore.prototype.clearChangedIDs = async function () {
* @param {String} uuid - The UUID of the workspace that changed. * @param {String} uuid - The UUID of the workspace that changed.
*/ */
ZenWorkspacesStore.prototype.markChanged = async function (uuid) { ZenWorkspacesStore.prototype.markChanged = async function (uuid) {
try { try {
await ZenWorkspacesStorage.markChanged(uuid); await ZenWorkspacesStorage.markChanged(uuid);
} catch (error) { } catch (error) {
this._log.error(`Error marking workspace ${uuid} as changed`, error); this._log.error(`Error marking workspace ${uuid} as changed`, error);
throw error; throw error;
} }
}; };
/** /**
* Finalizes the store by ensuring all pending operations are completed. * Finalizes the store by ensuring all pending operations are completed.
*/ */
ZenWorkspacesStore.prototype.finalize = async function () { 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);
@ -315,54 +314,54 @@ ZenWorkspacesTracker.prototype.constructor = ZenWorkspacesTracker;
* @returns {Object} An object mapping workspace UUIDs to their change timestamps. * @returns {Object} An object mapping workspace UUIDs to their change timestamps.
*/ */
ZenWorkspacesTracker.prototype.getChangedIDs = async function () { 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;
} }
}; };
/** /**
* Clears all recorded changes after a successful sync. * Clears all recorded changes after a successful sync.
*/ */
ZenWorkspacesTracker.prototype.clearChangedIDs = async function () { 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;
} }
}; };
/** /**
* Called when the tracker starts. Registers observers to listen for workspace changes. * Called when the tracker starts. Registers observers to listen for workspace changes.
*/ */
ZenWorkspacesTracker.prototype.onStart = function () { 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;
}; };
/** /**
* Called when the tracker stops. Unregisters observers. * Called when the tracker stops. Unregisters observers.
*/ */
ZenWorkspacesTracker.prototype.onStop = function () { 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;
}; };
/** /**
@ -372,68 +371,67 @@ ZenWorkspacesTracker.prototype.onStop = function () {
* @param {String} data - Additional data (JSON stringified array of UUIDs). * @param {String} data - Additional data (JSON stringified array of UUIDs).
*/ */
ZenWorkspacesTracker.prototype.observe = async function (subject, topic, data) { ZenWorkspacesTracker.prototype.observe = async function (subject, topic, data) {
if (this.ignoreAll) { if (this.ignoreAll) {
return; return;
} }
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);
return; return;
} }
} else { } else {
this._log.error(`No data received for event ${topic}`); this._log.error(`No data received for event ${topic}`);
return; return;
}
this._log.trace(`Observed ${topic} for UUIDs: ${workspaceIDs.join(", ")}`);
// Process each UUID
for (const workspaceID of workspaceIDs) {
if (typeof workspaceID === "string") {
// Inform the store about the change
await this.engine._store.markChanged(workspaceID);
} else {
this._log.warn(`Invalid workspace ID encountered: ${workspaceID}`);
}
}
// Bump the score once after processing all changes
if (workspaceIDs.length > 0) {
this.score += SCORE_INCREMENT_XLARGE;
}
break;
} }
} catch (error) {
this._log.error(`Error handling ${topic} in observe method`, error); this._log.trace(`Observed ${topic} for UUIDs: ${workspaceIDs.join(', ')}`);
// Process each UUID
for (const workspaceID of workspaceIDs) {
if (typeof workspaceID === 'string') {
// Inform the store about the change
await this.engine._store.markChanged(workspaceID);
} else {
this._log.warn(`Invalid workspace ID encountered: ${workspaceID}`);
}
}
// Bump the score once after processing all changes
if (workspaceIDs.length > 0) {
this.score += SCORE_INCREMENT_XLARGE;
}
break;
} }
} catch (error) {
this._log.error(`Error handling ${topic} in observe method`, error);
}
}; };
/** /**
* Finalizes the tracker by ensuring all pending operations are completed. * Finalizes the tracker by ensuring all pending operations are completed.
*/ */
ZenWorkspacesTracker.prototype.finalize = async function () { 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

@ -108,7 +108,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
return; return;
} else if (activationMethod === 'meta' && !event.metaKey) { } else if (activationMethod === 'meta' && !event.metaKey) {
return; return;
}else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') { } else if (activationMethod === 'mantain' || typeof activationMethod === 'undefined') {
return; return;
} }
// get closest A element // get closest A element

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"