mirror of
https://github.com/zen-browser/desktop.git
synced 2026-08-25 07:51:34 +00:00
Merge branch 'new-color-picker' of https://github.com/zen-browser/desktop into new-color-picker
This commit is contained in:
@@ -4,7 +4,7 @@ export var ZenCustomizableUI = new (class {
|
||||
constructor() {}
|
||||
|
||||
TYPE_TOOLBAR = 'toolbar';
|
||||
defaultSidebarIcons = ['zen-profile-button', 'zen-workspaces-button', 'downloads-button'];
|
||||
defaultSidebarIcons = ['preferences-button', 'zen-workspaces-button', 'downloads-button'];
|
||||
|
||||
startup(CustomizableUIInternal) {
|
||||
CustomizableUIInternal.registerArea(
|
||||
@@ -126,7 +126,7 @@ export var ZenCustomizableUI = new (class {
|
||||
window.CustomizableUI.registerToolbarNode(window.document.getElementById('zen-sidebar-top-buttons'));
|
||||
window.CustomizableUI.registerToolbarNode(window.document.getElementById('zen-sidebar-icons-wrapper'));
|
||||
window.addEventListener(
|
||||
'MozAfterPaint',
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
this._dispatchResizeEvent(window);
|
||||
},
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
var ZenStartup = {
|
||||
init() {
|
||||
this.openWatermark();
|
||||
window.SessionStore.promiseInitialized.then(() => {
|
||||
this._changeSidebarLocation();
|
||||
this._zenInitBrowserLayout();
|
||||
this._initSearchBar();
|
||||
});
|
||||
this._changeSidebarLocation();
|
||||
this._zenInitBrowserLayout();
|
||||
this._initSearchBar();
|
||||
},
|
||||
|
||||
_zenInitBrowserLayout() {
|
||||
@@ -31,11 +29,7 @@
|
||||
document.getElementById('zen-appcontent-navbar-container').appendChild(deckTemplate);
|
||||
}
|
||||
|
||||
// Disable smooth scroll
|
||||
gBrowser.tabContainer.arrowScrollbox.smoothScroll = Services.prefs.getBoolPref(
|
||||
'zen.startup.smooth-scroll-in-tabs',
|
||||
false
|
||||
);
|
||||
this._initSidebarScrolling();
|
||||
|
||||
gZenCompactModeManager.init();
|
||||
ZenWorkspaces.init();
|
||||
@@ -86,6 +80,35 @@
|
||||
}
|
||||
},
|
||||
|
||||
_initSidebarScrolling() {
|
||||
// Disable smooth scroll
|
||||
const canSmoothScroll = Services.prefs.getBoolPref('zen.startup.smooth-scroll-in-tabs', false);
|
||||
const tabsWrapper = document.getElementById('zen-tabs-wrapper');
|
||||
gBrowser.tabContainer.addEventListener('wheel', (event) => {
|
||||
if (canSmoothScroll) return;
|
||||
event.preventDefault(); // Prevent the smooth scroll behavior
|
||||
gBrowser.tabContainer.scrollTop += event.deltaY * 20; // Apply immediate scroll
|
||||
});
|
||||
// Detect overflow and underflow
|
||||
const observer = new ResizeObserver((_) => {
|
||||
const tabContainer = gBrowser.tabContainer;
|
||||
// const isVertical = tabContainer.getAttribute('orient') === 'vertical';
|
||||
// let contentSize = tabsWrapper.getBoundingClientRect()[isVertical ? 'height' : 'width'];
|
||||
// NOTE: This should be contentSize > scrollClientSize, but due
|
||||
// to how Gecko internally rounds in those cases, we allow for some
|
||||
// minor differences (the internal Gecko layout size is 1/60th of a
|
||||
// pixel, so 0.02 should cover it).
|
||||
//let overflowing = contentSize - tabContainer.arrowScrollbox.scrollClientSize > 0.02;
|
||||
let overflowing = true; // cheatign the system, because we want to always show make the element overflowing
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
tabContainer.arrowScrollbox.toggleAttribute('overflowing', overflowing);
|
||||
tabContainer.arrowScrollbox.dispatchEvent(new CustomEvent(overflowing ? 'overflow' : 'underflow'));
|
||||
});
|
||||
});
|
||||
observer.observe(tabsWrapper);
|
||||
},
|
||||
|
||||
_initSearchBar() {
|
||||
// Only focus the url bar
|
||||
gURLBar.focus();
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
var gZenUIManager = {
|
||||
_popupTrackingElements: [],
|
||||
_hoverPausedForExpand: false,
|
||||
_hasLoadedDOM: false,
|
||||
|
||||
init() {
|
||||
document.addEventListener('popupshowing', this.onPopupShowing.bind(this));
|
||||
document.addEventListener('popuphidden', this.onPopupHidden.bind(this));
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, 'sidebarHeightThrottle', 'zen.view.sidebar-height-throttle', 500);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, 'contentElementSeparation', 'zen.theme.content-element-separation', 0);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, 'urlbarWaitToClear', 'zen.urlbar.wait-to-clear', 0);
|
||||
|
||||
gURLBar._zenTrimURL = this.urlbarTrim.bind(this);
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, 'motion', () => {
|
||||
return ChromeUtils.importESModule('chrome://browser/content/zen-vendor/motion.min.mjs', { global: 'current' });
|
||||
});
|
||||
|
||||
new ResizeObserver(gZenCommonActions.throttle(this.updateTabsToolbar.bind(this), this.sidebarHeightThrottle)).observe(
|
||||
document.getElementById('tabbrowser-tabs')
|
||||
);
|
||||
ChromeUtils.defineLazyGetter(this, '_toastContainer', () => {
|
||||
return document.getElementById('zen-toast-container');
|
||||
});
|
||||
|
||||
new ResizeObserver(this.updateTabsToolbar.bind(this)).observe(document.getElementById('TabsToolbar'));
|
||||
|
||||
new ResizeObserver(
|
||||
gZenCommonActions.throttle(
|
||||
@@ -22,25 +28,60 @@ var gZenUIManager = {
|
||||
this.sidebarHeightThrottle
|
||||
)
|
||||
).observe(document.getElementById('navigator-toolbox'));
|
||||
|
||||
SessionStore.promiseAllWindowsRestored.then(() => {
|
||||
this._hasLoadedDOM = true;
|
||||
this.updateTabsToolbar();
|
||||
});
|
||||
|
||||
window.addEventListener('TabClose', this.onTabClose.bind(this));
|
||||
this.tabsWrapper.addEventListener('scroll', this.saveScrollbarState.bind(this));
|
||||
},
|
||||
|
||||
updateTabsToolbar() {
|
||||
// Set tabs max-height to the "toolbar-items" height
|
||||
const toolbarItems = document.getElementById('tabbrowser-tabs');
|
||||
const tabs = document.getElementById('tabbrowser-arrowscrollbox');
|
||||
tabs.style.maxHeight = '0px'; // reset to 0
|
||||
const toolbarRect = toolbarItems.getBoundingClientRect();
|
||||
let height = toolbarRect.height;
|
||||
// -5 for the controls padding
|
||||
let totalHeight = toolbarRect.height - this.contentElementSeparation * 2 - 5;
|
||||
// remove the height from other elements that aren't hidden
|
||||
const otherElements = document.querySelectorAll('#tabbrowser-tabs > *:not([hidden="true"])');
|
||||
for (let tab of otherElements) {
|
||||
if (tabs === tab) continue;
|
||||
totalHeight -= tab.getBoundingClientRect().height;
|
||||
const tabs = this.tabsWrapper;
|
||||
// Remove tabs so we can accurately calculate the height
|
||||
// without them affecting the height of the toolbar
|
||||
for (const tab of gBrowser.tabs) {
|
||||
if (tab.hasAttribute('zen-essential')) {
|
||||
continue;
|
||||
}
|
||||
tab.style.maxHeight = '0px';
|
||||
}
|
||||
tabs.style.maxHeight = totalHeight + 'px';
|
||||
//console.info('ZenThemeModifier: set tabs max-height to', totalHeight + 'px');
|
||||
tabs.style.flex = '1';
|
||||
tabs.style.removeProperty('max-height');
|
||||
const toolbarRect = tabs.getBoundingClientRect();
|
||||
let height = toolbarRect.height;
|
||||
for (const tab of gBrowser.tabs) {
|
||||
if (tab.hasAttribute('zen-essential')) {
|
||||
continue;
|
||||
}
|
||||
tab.style.removeProperty('max-height');
|
||||
}
|
||||
tabs.style.removeProperty('flex');
|
||||
tabs.style.maxHeight = height + 'px';
|
||||
},
|
||||
|
||||
get tabsWrapper() {
|
||||
if (this._tabsWrapper) {
|
||||
return this._tabsWrapper;
|
||||
}
|
||||
this._tabsWrapper = document.getElementById('zen-tabs-wrapper');
|
||||
return this._tabsWrapper;
|
||||
},
|
||||
|
||||
saveScrollbarState() {
|
||||
this._scrollbarState = this.tabsWrapper.scrollTop;
|
||||
},
|
||||
|
||||
restoreScrollbarState() {
|
||||
this.tabsWrapper.scrollTop = this._scrollbarState;
|
||||
},
|
||||
|
||||
onTabClose(event) {
|
||||
this.updateTabsToolbar();
|
||||
this.restoreScrollbarState();
|
||||
},
|
||||
|
||||
openAndChangeToTab(url, options) {
|
||||
@@ -55,9 +96,7 @@ var gZenUIManager = {
|
||||
},
|
||||
|
||||
generateUuidv4() {
|
||||
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>
|
||||
(+c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))).toString(16)
|
||||
);
|
||||
return Services.uuid.generateUUID().toString();
|
||||
},
|
||||
|
||||
toogleBookmarksSidebar() {
|
||||
@@ -113,6 +152,111 @@ var gZenUIManager = {
|
||||
this.__currentPopup = null;
|
||||
this.__currentPopupTrackElement = null;
|
||||
},
|
||||
|
||||
// Section: URL bar
|
||||
|
||||
get newtabButtons() {
|
||||
return document.querySelectorAll('#tabs-newtab-button');
|
||||
},
|
||||
|
||||
_prevUrlbarLabel: null,
|
||||
_lastSearch: '',
|
||||
_clearTimeout: null,
|
||||
_lastTab: null,
|
||||
|
||||
handleNewTab(werePassedURL, searchClipboard, where) {
|
||||
const shouldOpenURLBar =
|
||||
Services.prefs.getBoolPref('zen.urlbar.replace-newtab') && !werePassedURL && !searchClipboard && where === 'tab';
|
||||
if (shouldOpenURLBar) {
|
||||
if (this._clearTimeout) {
|
||||
clearTimeout(this._clearTimeout);
|
||||
}
|
||||
this._lastTab = gBrowser.selectedTab;
|
||||
this._lastTab._visuallySelected = false;
|
||||
this._prevUrlbarLabel = gURLBar._untrimmedValue;
|
||||
gURLBar._zenHandleUrlbarClose = this.handleUrlbarClose.bind(this);
|
||||
gURLBar.setAttribute('zen-newtab', true);
|
||||
for (const button of this.newtabButtons) {
|
||||
button.setAttribute('in-urlbar', true);
|
||||
}
|
||||
document.getElementById('Browser:OpenLocation').doCommand();
|
||||
gURLBar.search(this._lastSearch);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
clearUrlbarData() {
|
||||
this._prevUrlbarLabel = null;
|
||||
this._lastSearch = '';
|
||||
},
|
||||
|
||||
handleUrlbarClose(onSwitch) {
|
||||
gURLBar._zenHandleUrlbarClose = null;
|
||||
gURLBar.removeAttribute('zen-newtab');
|
||||
this._lastTab._visuallySelected = true;
|
||||
this._lastTab = null;
|
||||
for (const button of this.newtabButtons) {
|
||||
button.removeAttribute('in-urlbar');
|
||||
}
|
||||
if (onSwitch) {
|
||||
this.clearUrlbarData();
|
||||
} else {
|
||||
this._lastSearch = gURLBar._untrimmedValue;
|
||||
this._clearTimeout = setTimeout(() => {
|
||||
this.clearUrlbarData();
|
||||
}, this.urlbarWaitToClear);
|
||||
}
|
||||
gURLBar.setURI(this._prevUrlbarLabel, onSwitch, false, false, !onSwitch);
|
||||
gURLBar.handleRevert();
|
||||
if (gURLBar.focused) {
|
||||
gURLBar.view.close({ elementPicked: onSwitch });
|
||||
gURLBar.updateTextOverflow();
|
||||
if (gBrowser.selectedTab.linkedBrowser && onSwitch) {
|
||||
gURLBar.getBrowserState(gBrowser.selectedTab.linkedBrowser).urlbarFocused = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
urlbarTrim(aURL) {
|
||||
if (gZenVerticalTabsManager._hasSetSingleToolbar) {
|
||||
let url = BrowserUIUtils.removeSingleTrailingSlashFromURL(aURL);
|
||||
return url.startsWith('http://') || url.startsWith('https://') ? url.split('/')[2] : url;
|
||||
}
|
||||
return BrowserUIUtils.trimURL(aURL);
|
||||
},
|
||||
|
||||
// Section: Notification messages
|
||||
_createToastElement(messageId, options) {
|
||||
const element = document.createXULElement('vbox');
|
||||
const label = document.createXULElement('label');
|
||||
document.l10n.setAttributes(label, messageId, options);
|
||||
element.appendChild(label);
|
||||
if (options.descriptionId) {
|
||||
const description = document.createXULElement('label');
|
||||
description.classList.add('description');
|
||||
document.l10n.setAttributes(description, options.descriptionId, options);
|
||||
element.appendChild(description);
|
||||
}
|
||||
element.classList.add('zen-toast');
|
||||
return element;
|
||||
},
|
||||
|
||||
async showToast(messageId, options = {}) {
|
||||
const toast = this._createToastElement(messageId, options);
|
||||
this._toastContainer.removeAttribute('hidden');
|
||||
this._toastContainer.appendChild(toast);
|
||||
await this.motion.animate(toast, { opacity: [0, 1], scale: [0.8, 1] }, { type: 'spring', bounce: 0.4 });
|
||||
await new Promise((resolve) => setTimeout(resolve, 3000));
|
||||
await this.motion.animate(toast, { opacity: [1, 0], scale: [1, 0.9] }, { duration: 0.2, bounce: 0 });
|
||||
const toastHeight = toast.getBoundingClientRect().height;
|
||||
// 5 for the separation between toasts
|
||||
await this.motion.animate(toast, { marginBottom: [0, `-${toastHeight + 5}px`] }, { duration: 0.2 });
|
||||
toast.remove();
|
||||
if (!this._toastContainer.hasChildNodes()) {
|
||||
this._toastContainer.setAttribute('hidden', 'true');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var gZenVerticalTabsManager = {
|
||||
@@ -147,27 +291,14 @@ var gZenVerticalTabsManager = {
|
||||
window.addEventListener('customizationstarting', this._preCustomize.bind(this));
|
||||
window.addEventListener('aftercustomization', this._postCustomize.bind(this));
|
||||
|
||||
window.addEventListener('DOMContentLoaded', updateEvent, { once: true });
|
||||
|
||||
const tabs = document.getElementById('tabbrowser-tabs');
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(this, 'canOpenTabOnMiddleClick', 'zen.tabs.newtab-on-middle-click', true);
|
||||
this._updateEvent();
|
||||
|
||||
if (!this.isWindowsStyledButtons) {
|
||||
document.documentElement.setAttribute('zen-window-buttons-reversed', true);
|
||||
}
|
||||
|
||||
if (tabs) {
|
||||
tabs.addEventListener('mouseup', this.openNewTabOnTabsMiddleClick.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
openNewTabOnTabsMiddleClick(event) {
|
||||
if (event.button === 1 && event.target.id === 'tabbrowser-tabs' && this.canOpenTabOnMiddleClick) {
|
||||
document.getElementById('cmd_newNavigatorTabNoEvent').doCommand();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
this._renameTabHalt = this.renameTabHalt.bind(this);
|
||||
gBrowser.tabContainer.addEventListener('dblclick', this.renameTabStart.bind(this));
|
||||
},
|
||||
|
||||
toggleExpand() {
|
||||
@@ -204,6 +335,45 @@ var gZenVerticalTabsManager = {
|
||||
return this.__topButtonsSeparatorElement;
|
||||
},
|
||||
|
||||
animateTab(aTab) {
|
||||
if (!gZenUIManager.motion || !aTab || !gZenUIManager._hasLoadedDOM) {
|
||||
return;
|
||||
}
|
||||
// get next visible tab
|
||||
const isLastTab = () => {
|
||||
const visibleTabs = gBrowser.visibleTabs;
|
||||
return visibleTabs[visibleTabs.length - 1] === aTab;
|
||||
};
|
||||
|
||||
const tabSize = aTab.getBoundingClientRect().height;
|
||||
const transform = `-${tabSize}px`;
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
aTab,
|
||||
{
|
||||
opacity: [0, 1],
|
||||
transform: ['scale(0.95)', 'scale(1)'],
|
||||
marginBottom: isLastTab() ? [] : [transform, '0px'],
|
||||
},
|
||||
{
|
||||
duration: 0.2,
|
||||
easing: 'ease-out',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
aTab.style.removeProperty('margin-bottom');
|
||||
aTab.style.removeProperty('transform');
|
||||
aTab.style.removeProperty('opacity');
|
||||
});
|
||||
gZenUIManager.motion
|
||||
.animate(aTab.querySelector('.tab-content'), {
|
||||
filter: ['blur(1px)', 'blur(0px)'],
|
||||
})
|
||||
.then(() => {
|
||||
aTab.querySelector('.tab-stack').style.removeProperty('filter');
|
||||
});
|
||||
},
|
||||
|
||||
get actualWindowButtons() {
|
||||
// we have multiple ".titlebar-buttonbox-container" in the DOM, because of the titlebar
|
||||
if (!this.__actualWindowButtons) {
|
||||
@@ -295,6 +465,11 @@ var gZenVerticalTabsManager = {
|
||||
|
||||
gBrowser.tabContainer.setAttribute('orient', isVerticalTabs ? 'vertical' : 'horizontal');
|
||||
gBrowser.tabContainer.arrowScrollbox.setAttribute('orient', isVerticalTabs ? 'vertical' : 'horizontal');
|
||||
// on purpose, we set the orient to horizontal, because the arrowScrollbox is vertical
|
||||
gBrowser.tabContainer.arrowScrollbox.scrollbox.setAttribute(
|
||||
'orient',
|
||||
isVerticalTabs && ZenWorkspaces.workspaceEnabled ? 'horizontal' : 'vertical'
|
||||
);
|
||||
|
||||
const buttonsTarget = document.getElementById('zen-sidebar-top-buttons-customization-target');
|
||||
if (isRightSide) {
|
||||
@@ -448,6 +623,7 @@ var gZenVerticalTabsManager = {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
this._isUpdating = false;
|
||||
},
|
||||
|
||||
@@ -488,4 +664,85 @@ var gZenVerticalTabsManager = {
|
||||
}
|
||||
target.appendChild(child);
|
||||
},
|
||||
|
||||
renameTabKeydown(event) {
|
||||
if (event.key === 'Enter') {
|
||||
let label = this._tabEdited.querySelector('.tab-label-container-editing');
|
||||
let input = this._tabEdited.querySelector('#tab-label-input');
|
||||
let newName = input.value.trim();
|
||||
|
||||
// Check if name is blank, reset if so
|
||||
// Always remove, so we can always rename and if it's empty,
|
||||
// it will reset to the original name anyway
|
||||
this._tabEdited.removeAttribute('zen-has-static-label');
|
||||
if (newName) {
|
||||
gBrowser._setTabLabel(this._tabEdited, newName);
|
||||
this._tabEdited.setAttribute('zen-has-static-label', 'true');
|
||||
} else {
|
||||
gBrowser.setTabTitle(this._tabEdited);
|
||||
}
|
||||
|
||||
// Maybe add some confetti here?!?
|
||||
gZenUIManager.motion.animate(
|
||||
this._tabEdited,
|
||||
{
|
||||
scale: [1, 0.98, 1],
|
||||
},
|
||||
{
|
||||
duration: 0.25,
|
||||
}
|
||||
);
|
||||
|
||||
this._tabEdited.querySelector('.tab-editor-container').remove();
|
||||
label.classList.remove('tab-label-container-editing');
|
||||
|
||||
this._tabEdited = null;
|
||||
} else if (event.key === 'Escape') {
|
||||
event.target.blur();
|
||||
}
|
||||
},
|
||||
|
||||
renameTabStart(event) {
|
||||
if (
|
||||
this._tabEdited ||
|
||||
!Services.prefs.getBoolPref('zen.tabs.rename-tabs') ||
|
||||
Services.prefs.getBoolPref('browser.tabs.closeTabByDblclick') ||
|
||||
!gZenVerticalTabsManager._prefsSidebarExpanded
|
||||
)
|
||||
return;
|
||||
this._tabEdited = event.target.closest('.tabbrowser-tab');
|
||||
if (!this._tabEdited || !this._tabEdited.pinned || this._tabEdited.hasAttribute('zen-essential')) {
|
||||
this._tabEdited = null;
|
||||
return;
|
||||
}
|
||||
const label = this._tabEdited.querySelector('.tab-label-container');
|
||||
label.classList.add('tab-label-container-editing');
|
||||
|
||||
const container = window.MozXULElement.parseXULToFragment(`
|
||||
<vbox class="tab-label-container tab-editor-container" flex="1" align="start" pack="center"></vbox>
|
||||
`);
|
||||
label.after(container);
|
||||
const containerHtml = this._tabEdited.querySelector('.tab-editor-container');
|
||||
const input = document.createElement('input');
|
||||
input.id = 'tab-label-input';
|
||||
input.value = this._tabEdited.label;
|
||||
input.addEventListener('keydown', this.renameTabKeydown.bind(this));
|
||||
|
||||
containerHtml.appendChild(input);
|
||||
input.focus();
|
||||
input.select();
|
||||
|
||||
input.addEventListener('blur', this._renameTabHalt);
|
||||
},
|
||||
|
||||
renameTabHalt(event) {
|
||||
if (document.activeElement === event.target || !this._tabEdited) {
|
||||
return;
|
||||
}
|
||||
this._tabEdited.querySelector('.tab-editor-container').remove();
|
||||
const label = this._tabEdited.querySelector('.tab-label-container-editing');
|
||||
label.classList.remove('tab-label-container-editing');
|
||||
|
||||
this._tabEdited = null;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
diff --git a/browser/base/content/browser-commands.js b/browser/base/content/browser-commands.js
|
||||
index 352de44dda36e3f6672eb353f42978ede0cd2681..d6956a318c34bfb12b0ba957edab1166e1a4edaf 100644
|
||||
index 352de44dda36e3f6672eb353f42978ede0cd2681..66d1616da17df3430cec0994a346f0f446944f1a 100644
|
||||
--- a/browser/base/content/browser-commands.js
|
||||
+++ b/browser/base/content/browser-commands.js
|
||||
@@ -407,8 +407,8 @@ var BrowserCommands = {
|
||||
@@ -318,6 +318,10 @@ var BrowserCommands = {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (gZenUIManager.handleNewTab(werePassedURL, searchClipboard, where)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// A notification intended to be useful for modular peformance tracking
|
||||
// starting as close as is reasonably possible to the time when the user
|
||||
// expressed the intent to open a new tab. Since there are a lot of
|
||||
@@ -407,8 +411,8 @@ var BrowserCommands = {
|
||||
(event.ctrlKey || event.metaKey || event.altKey) &&
|
||||
gBrowser.selectedTab.pinned
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js
|
||||
index 9df41bb3c82919839ee1408aa4d177ea7ee40a56..e37c64fa2c2ea39762be4285a1a7055463ded537 100644
|
||||
index 63100defacf66c6b3232b9e0a783a5fd14e3a46a..22b79b021ff0baab4dac602447a124308208c828 100644
|
||||
--- a/browser/base/content/browser-init.js
|
||||
+++ b/browser/base/content/browser-init.js
|
||||
@@ -152,13 +152,15 @@ var gBrowserInit = {
|
||||
elem.setAttribute("skipintoolbarset", "true");
|
||||
}
|
||||
}
|
||||
@@ -162,13 +162,15 @@ var gBrowserInit = {
|
||||
elem.setAttribute("skipintoolbarset", "true");
|
||||
}
|
||||
}
|
||||
+ ZenCustomizableUI.init(window);
|
||||
for (let area of CustomizableUI.areas) {
|
||||
let type = CustomizableUI.getAreaType(area);
|
||||
@@ -16,10 +16,10 @@ index 9df41bb3c82919839ee1408aa4d177ea7ee40a56..e37c64fa2c2ea39762be4285a1a70554
|
||||
}
|
||||
}
|
||||
+ ZenCustomizableUI.registerToolbarNodes(window);
|
||||
if (isVerticalTabs) {
|
||||
// Show the vertical tabs toolbar
|
||||
setToolbarVisibility(
|
||||
@@ -253,6 +255,10 @@ var gBrowserInit = {
|
||||
if (isVerticalTabs) {
|
||||
// Show the vertical tabs toolbar
|
||||
setToolbarVisibility(
|
||||
@@ -287,6 +289,10 @@ var gBrowserInit = {
|
||||
gPrivateBrowsingUI.init();
|
||||
BrowserSearch.init();
|
||||
BrowserPageActions.init();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
|
||||
index 9a65dcc7ad41ab961907c95338e023b173d4f474..9477e0c115ed3c4a670f1ac63846b6de01bf8b8c 100644
|
||||
index 019b168c1aeae7e1c97a3ae58c99a48a27f54134..1f051e8a1e8a58e8bb721196deecfa36f4089dd6 100644
|
||||
--- a/browser/base/content/browser.js
|
||||
+++ b/browser/base/content/browser.js
|
||||
@@ -32,6 +32,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||
@@ -10,7 +10,7 @@ index 9a65dcc7ad41ab961907c95338e023b173d4f474..9477e0c115ed3c4a670f1ac63846b6de
|
||||
DevToolsSocketStatus:
|
||||
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
|
||||
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
|
||||
@@ -630,6 +631,15 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
@@ -632,6 +633,15 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
false
|
||||
);
|
||||
|
||||
@@ -26,19 +26,18 @@ index 9a65dcc7ad41ab961907c95338e023b173d4f474..9477e0c115ed3c4a670f1ac63846b6de
|
||||
customElements.setElementCreationCallback("screenshots-buttons", () => {
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://browser/content/screenshots/screenshots-buttons.js",
|
||||
@@ -3440,6 +3450,11 @@ var XULBrowserWindow = {
|
||||
@@ -3440,6 +3450,10 @@ var XULBrowserWindow = {
|
||||
AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser);
|
||||
TranslationsParent.onLocationChange(gBrowser.selectedBrowser);
|
||||
|
||||
+ gZenViewSplitter.onLocationChange(gBrowser.selectedBrowser);
|
||||
+ ZenWorkspaces.onLocationChange(gBrowser.selectedBrowser);
|
||||
+ gZenTabUnloader.onLocationChange(gBrowser.selectedBrowser);
|
||||
+ gZenGlanceManager.onLocationChange(gBrowser.selectedBrowser);
|
||||
+
|
||||
PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser);
|
||||
|
||||
if (!gMultiProcessBrowser) {
|
||||
@@ -4435,7 +4450,7 @@ nsBrowserAccess.prototype = {
|
||||
@@ -4435,7 +4449,7 @@ nsBrowserAccess.prototype = {
|
||||
// Passing a null-URI to only create the content window,
|
||||
// and pass true for aSkipLoad to prevent loading of
|
||||
// about:blank
|
||||
@@ -47,7 +46,7 @@ index 9a65dcc7ad41ab961907c95338e023b173d4f474..9477e0c115ed3c4a670f1ac63846b6de
|
||||
null,
|
||||
aParams,
|
||||
aWhere,
|
||||
@@ -4443,6 +4458,10 @@ nsBrowserAccess.prototype = {
|
||||
@@ -4443,6 +4457,10 @@ nsBrowserAccess.prototype = {
|
||||
aName,
|
||||
true
|
||||
);
|
||||
@@ -58,7 +57,7 @@ index 9a65dcc7ad41ab961907c95338e023b173d4f474..9477e0c115ed3c4a670f1ac63846b6de
|
||||
},
|
||||
|
||||
openURIInFrame: function browser_openURIInFrame(
|
||||
@@ -7281,6 +7300,12 @@ var gDialogBox = {
|
||||
@@ -7285,6 +7303,12 @@ var gDialogBox = {
|
||||
parentElement.showModal();
|
||||
this._didOpenHTMLDialog = true;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
diff --git a/browser/base/content/browser-sets.js b/browser/base/content/browser-sets.js
|
||||
index 3031278749317d153624c6ccfbcc9d47aaf4089f..e67a8c3b56c01334627350c494b0139638ebf19a 100644
|
||||
index 61aef2d420a78fb1910f556b71f6db75a16180ed..a3a1e70bedb760c165c338c28de6f2ee924df8de 100644
|
||||
--- a/browser/base/content/browser-sets.js
|
||||
+++ b/browser/base/content/browser-sets.js
|
||||
@@ -245,7 +245,7 @@ document.addEventListener(
|
||||
@@ -250,7 +250,7 @@ document.addEventListener(
|
||||
}
|
||||
});
|
||||
|
||||
- document.getElementById("mainKeyset").addEventListener("command", event => {
|
||||
+ document.getElementById("zenKeyset").addEventListener("command", event => {
|
||||
switch (event.target.id) {
|
||||
case "goHome":
|
||||
BrowserCommands.home();
|
||||
const SIDEBAR_REVAMP_PREF = "sidebar.revamp";
|
||||
const SIDEBAR_REVAMP_ENABLED = Services.prefs.getBoolPref(
|
||||
SIDEBAR_REVAMP_PREF,
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
diff --git a/browser/base/content/browser.xhtml b/browser/base/content/browser.xhtml
|
||||
index ca8953f3604f4f70de76576964af5f3c733f17a0..a2731ef6d4392301217cd05f6583e4814f1118e2 100644
|
||||
index 891c067d6ad718061c410c04743bed25744504b5..b7ded9691225068b23e4d6a5113242d0c0f5f842 100644
|
||||
--- a/browser/base/content/browser.xhtml
|
||||
+++ b/browser/base/content/browser.xhtml
|
||||
@@ -101,6 +101,8 @@
|
||||
@@ -99,6 +99,8 @@
|
||||
|
||||
<title data-l10n-id="browser-main-window-title"></title>
|
||||
<title data-l10n-id="browser-main-window-default-title"></title>
|
||||
|
||||
+#include zen-preloaded.inc.xhtml
|
||||
+
|
||||
# All JS files which are needed by browser.xhtml and other top level windows to
|
||||
# support MacOS specific features *must* go into the global-scripts.inc file so
|
||||
# that they can be shared with macWindow.inc.xhtml.
|
||||
@@ -145,6 +147,7 @@
|
||||
@@ -143,6 +145,7 @@
|
||||
window.addEventListener("DOMContentLoaded",
|
||||
gBrowserInit.onDOMContentLoaded.bind(gBrowserInit), { once: true });
|
||||
</script>
|
||||
@@ -19,7 +19,7 @@ index ca8953f3604f4f70de76576964af5f3c733f17a0..a2731ef6d4392301217cd05f6583e481
|
||||
</head>
|
||||
<html:body xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
# All sets except for popupsets (commands, keys, and stringbundles)
|
||||
@@ -166,9 +169,12 @@
|
||||
@@ -164,9 +167,13 @@
|
||||
</vbox>
|
||||
</html:template>
|
||||
|
||||
@@ -27,6 +27,7 @@ index ca8953f3604f4f70de76576964af5f3c733f17a0..a2731ef6d4392301217cd05f6583e481
|
||||
-
|
||||
-#include browser-box.inc.xhtml
|
||||
+ <hbox id="zen-main-app-wrapper" flex="1" persist="zen-compact-mode">
|
||||
+ <vbox id="zen-toast-container"></vbox>
|
||||
+ #include navigator-toolbox.inc.xhtml
|
||||
+ <html:span id="zen-sidebar-box-container">
|
||||
+ </html:span>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml
|
||||
index 1fb595272a184f9a40f56f87d86232e3324f7750..8dd0f0ff856be524a5fa27fb8c6180c1fe058134 100644
|
||||
index e5f3424eaeeec0ba552537f167dd99e912216d94..4bdfcdb23fe9c44ad3d4de273c64f4cc31cb4034 100644
|
||||
--- a/browser/base/content/main-popupset.inc.xhtml
|
||||
+++ b/browser/base/content/main-popupset.inc.xhtml
|
||||
@@ -144,6 +144,10 @@
|
||||
@@ -181,6 +181,10 @@
|
||||
hidden="true"
|
||||
tabspecific="true"
|
||||
aria-labelledby="editBookmarkPanelTitle">
|
||||
@@ -13,17 +13,17 @@ index 1fb595272a184f9a40f56f87d86232e3324f7750..8dd0f0ff856be524a5fa27fb8c6180c1
|
||||
<box class="panel-header">
|
||||
<html:h1>
|
||||
<html:span id="editBookmarkPanelTitle"/>
|
||||
@@ -169,6 +173,7 @@
|
||||
@@ -206,6 +210,7 @@
|
||||
class="footer-button"/>
|
||||
</html:moz-button-group>
|
||||
</vbox>
|
||||
+ </vbox>
|
||||
+ </vbox>
|
||||
</panel>
|
||||
</html:template>
|
||||
|
||||
@@ -454,6 +459,8 @@
|
||||
@@ -535,6 +540,8 @@
|
||||
|
||||
#include popup-notifications.inc
|
||||
#include popup-notifications.inc.xhtml
|
||||
|
||||
+#include zen-popupset.inc.xhtml
|
||||
+
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
index 00391af141d9015fe5839534e5e6b22a91ba65d9..17d8ac96986e698b09033b870c24fc2f61c47a05 100644
|
||||
index a0a382643a2f74b6d789f3641ef300eed202d5e9..7a2be5fe6cdecb771ce3326008085ae402a465de 100644
|
||||
--- a/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
@@ -2,7 +2,7 @@
|
||||
@@ -29,23 +29,30 @@ index 00391af141d9015fe5839534e5e6b22a91ba65d9..17d8ac96986e698b09033b870c24fc2f
|
||||
<toolbartabstop/>
|
||||
<hbox id="TabsToolbar-customization-target" flex="1">
|
||||
<toolbarbutton id="firefox-view-button"
|
||||
@@ -40,6 +40,7 @@
|
||||
@@ -40,9 +40,9 @@
|
||||
data-l10n-id="toolbar-button-firefox-view-2"
|
||||
role="button"
|
||||
aria-pressed="false"
|
||||
+ hidden="true"
|
||||
cui-areatype="toolbar"
|
||||
removable="true"/>
|
||||
|
||||
@@ -55,9 +56,14 @@
|
||||
-
|
||||
<tabs id="tabbrowser-tabs"
|
||||
is="tabbrowser-tabs"
|
||||
aria-multiselectable="true"
|
||||
@@ -50,6 +50,10 @@
|
||||
tooltip="tabbrowser-tab-tooltip"
|
||||
orient="horizontal"
|
||||
stopwatchid="FX_TAB_CLICK_MS">
|
||||
+<html:div id="zen-essentials-container" skipintoolbarset="true"></html:div>
|
||||
+<hbox id="zen-current-workspace-indicator-container"></hbox>
|
||||
+<html:div id="zen-tabs-wrapper">
|
||||
+<html:div id="zen-browser-tabs-container">
|
||||
<hbox class="tab-drop-indicator" hidden="true"/>
|
||||
# If the name (tabbrowser-arrowscrollbox) or structure of this changes
|
||||
# significantly, there is an optimization in
|
||||
# DisplayPortUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered based
|
||||
@@ -57,7 +61,7 @@
|
||||
# the current structure that we may want to revisit.
|
||||
+ <html:div id="zen-essentials-container"></html:div>
|
||||
+ <hbox id="zen-current-workspace-indicator">
|
||||
+ <hbox id="zen-current-workspace-indicator-icon"></hbox>
|
||||
+ <hbox id="zen-current-workspace-indicator-name"></hbox>
|
||||
+ </hbox>
|
||||
<html:div id="vertical-pinned-tabs-container" tabindex="-1"></html:div>
|
||||
<html:div id="vertical-pinned-tabs-container-separator"></html:div>
|
||||
- <arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" clicktoscroll="" scrolledtostart="" scrolledtoend="">
|
||||
@@ -53,6 +60,15 @@ index 00391af141d9015fe5839534e5e6b22a91ba65d9..17d8ac96986e698b09033b870c24fc2f
|
||||
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="" fadein=""/>
|
||||
<hbox id="tabbrowser-arrowscrollbox-periphery">
|
||||
<toolbartabstop/>
|
||||
@@ -75,6 +79,8 @@
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
data-l10n-id="tabs-toolbar-new-tab"/>
|
||||
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
|
||||
+</html:div>
|
||||
+</html:div>
|
||||
</tabs>
|
||||
|
||||
<toolbarbutton id="new-tab-button"
|
||||
@@ -100,11 +106,12 @@
|
||||
#include private-browsing-indicator.inc.xhtml
|
||||
<toolbarbutton id="content-analysis-indicator"
|
||||
@@ -69,7 +85,7 @@ index 00391af141d9015fe5839534e5e6b22a91ba65d9..17d8ac96986e698b09033b870c24fc2f
|
||||
<toolbar id="nav-bar"
|
||||
class="browser-toolbar chromeclass-location"
|
||||
data-l10n-id="navbar-accessible"
|
||||
@@ -487,10 +494,12 @@
|
||||
@@ -490,10 +497,12 @@
|
||||
consumeanchor="PanelUI-button"
|
||||
data-l10n-id="appmenu-menu-button-closed2"/>
|
||||
</toolbaritem>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/navigator-toolbox.js b/browser/base/content/navigator-toolbox.js
|
||||
index 64ded8fb2c08f1dbfec8fe08ab427a24b53f1169..69009d53d7242c26f777ac2e0bb1897ff27ad916 100644
|
||||
index 64ded8fb2c08f1dbfec8fe08ab427a24b53f1169..9e1e888554279b6e1df3bc1cb907afd2ccb330ca 100644
|
||||
--- a/browser/base/content/navigator-toolbox.js
|
||||
+++ b/browser/base/content/navigator-toolbox.js
|
||||
@@ -8,7 +8,7 @@
|
||||
@@ -11,3 +11,19 @@ index 64ded8fb2c08f1dbfec8fe08ab427a24b53f1169..69009d53d7242c26f777ac2e0bb1897f
|
||||
const widgetOverflow = document.getElementById("widget-overflow");
|
||||
|
||||
function onPopupShowing(event) {
|
||||
@@ -187,6 +187,7 @@ document.addEventListener(
|
||||
#reload-button ,
|
||||
#urlbar-go-button,
|
||||
#reader-mode-button,
|
||||
+ #zen-tabs-wrapper,
|
||||
#picture-in-picture-button,
|
||||
#shopping-sidebar-button,
|
||||
#urlbar-zoom-button,
|
||||
@@ -208,6 +209,7 @@ document.addEventListener(
|
||||
case "vertical-tabs-newtab-button":
|
||||
case "tabs-newtab-button":
|
||||
case "new-tab-button":
|
||||
+ case "zen-tabs-wrapper":
|
||||
gBrowser.handleNewTabMiddleClick(element, event);
|
||||
break;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
content/browser/ZenStartup.mjs (content/ZenStartup.mjs)
|
||||
content/browser/ZenUIManager.mjs (content/ZenUIManager.mjs)
|
||||
content/browser/ZenCustomizableUI.sys.mjs (content/ZenCustomizableUI.sys.mjs)
|
||||
content/browser/zen-components/ZenUIMigration.mjs (zen-components/ZenUIMigration.mjs)
|
||||
content/browser/zen-components/ZenCompactMode.mjs (zen-components/ZenCompactMode.mjs)
|
||||
content/browser/zen-components/ZenViewSplitter.mjs (zen-components/ZenViewSplitter.mjs)
|
||||
content/browser/zen-components/ZenThemesCommon.mjs (zen-components/ZenThemesCommon.mjs)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<vbox id="zen-glance-sidebar-container">
|
||||
<toolbarbutton id="zen-glance-sidebar-close" class="toolbarbutton-1" oncommand="gZenGlanceManager.closeGlance()"/>
|
||||
<vbox id="zen-glance-sidebar-container" hidden="true">
|
||||
<toolbarbutton id="zen-glance-sidebar-close" class="toolbarbutton-1" oncommand="gZenGlanceManager.closeGlance({ onTabClose: true })"/>
|
||||
<toolbarbutton id="zen-glance-sidebar-open" class="toolbarbutton-1" oncommand="gZenGlanceManager.fullyOpenGlance()"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
@@ -105,13 +105,18 @@
|
||||
<panelmultiview id="PanelUI-zen-gradient-generator-multiview" mainViewId="PanelUI-zen-gradient-generator-view">
|
||||
<panelview id="PanelUI-zen-gradient-generator-view" class="PanelUI-subView zen-theme-picker" role="document" mainview-with-header="true" has-custom-header="true">
|
||||
<hbox class="zen-theme-picker-gradient">
|
||||
<div id="PanelUI-zen-gradient-generator-color-actions">
|
||||
<button id="PanelUI-zen-gradient-generator-color-add" class="subviewbutton">
|
||||
</button>
|
||||
<button id="PanelUI-zen-gradient-generator-color-remove" class="subviewbutton">
|
||||
</button>
|
||||
<html:div class="separator"></html:div>
|
||||
<button id="PanelUI-zen-gradient-generator-color-toggle-algo" class="subviewbutton">
|
||||
</button>
|
||||
</div>
|
||||
</hbox>
|
||||
<hbox id="PanelUI-zen-gradient-generator-controls">
|
||||
<vbox id="PanelUI-zen-gradient-generator-options">
|
||||
<hbox id="PanelUI-zen-gradient-degrees">
|
||||
<box class="dot"></box>
|
||||
<box class="text"></box>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<vbox id="PanelUI-zen-gradient-colors-wrapper">
|
||||
<vbox>
|
||||
|
||||
@@ -56,21 +56,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-new-tab-appear-vertical {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-25px);
|
||||
}
|
||||
60% {
|
||||
opacity: 0.8;
|
||||
transform: translateY(4px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-main-app-wrapper-animation {
|
||||
from {
|
||||
opacity: 1;
|
||||
@@ -242,76 +227,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-glance-content-animation-out {
|
||||
0% {
|
||||
/* make the box shrink to final width/height and x/y coordinates */
|
||||
transform: translate(-50%, -50%) translateZ(0);
|
||||
width: 85%;
|
||||
height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
/* make the box appear from initial width/height and x/y coordinates */
|
||||
transform: translate(-50%, -50%) translateZ(0);
|
||||
opacity: 0;
|
||||
width: 47%;
|
||||
height: 53%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-glance-buttons-animation-full {
|
||||
from {
|
||||
width: 85%;
|
||||
height: 85%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
to {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-glance-loading-animation {
|
||||
0% {
|
||||
opacity: 1;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
90% {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-glance-buttons-animation {
|
||||
from {
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(-100%) translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-rice-form-out {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
|
||||
@@ -9,11 +9,6 @@
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
position: relative;
|
||||
|
||||
/* For glance */
|
||||
transition:
|
||||
transform 0.1s ease-in-out,
|
||||
opacity 0.1s ease-in-out;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
:root:not([zen-no-padding='true']) & {
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
:root:is([inDOMFullscreen='true'], [chromehidden~='location'], [chromehidden~='toolbar']) {
|
||||
#navigator-toolbox,
|
||||
#zen-sidebar-splitter {
|
||||
display: none;
|
||||
visibility: collapse;
|
||||
}
|
||||
}
|
||||
|
||||
#browser {
|
||||
width: 100%;
|
||||
background: var(--zen-main-browser-background);
|
||||
background: var(--zen-main-browser-background) !important;
|
||||
|
||||
will-change: background-color;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
&[animating='true']::after {
|
||||
background: var(--zen-main-browser-background-old);
|
||||
backdrop-filter: blur(5px);
|
||||
animation: zen-main-app-wrapper-animation 0.4s ease forwards;
|
||||
animation: zen-main-app-wrapper-animation 0.2s ease forwards;
|
||||
transition: 0s;
|
||||
}
|
||||
}
|
||||
@@ -152,12 +152,33 @@
|
||||
gap: var(--zen-element-separation);
|
||||
}
|
||||
|
||||
.titlebar-buttonbox-container {
|
||||
height: 100%;
|
||||
@media not (-moz-platform: macos) {
|
||||
.titlebar-buttonbox-container {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-platform: macos) {
|
||||
.titlebar-buttonbox-container {
|
||||
margin-inline-end: 8px;
|
||||
padding: 3px 0;
|
||||
|
||||
& > .titlebar-buttonbox {
|
||||
margin-inline-start: var(--zen-toolbox-padding);
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-bool-pref: 'zen.widget.mac.mono-window-controls') {
|
||||
.titlebar-buttonbox-container {
|
||||
/* Draw 3 dots as background to represent the window controls,
|
||||
all with the same cololr as the titlebar */
|
||||
background-image: radial-gradient(circle, var(--zen-toolbar-element-bg) 6px, transparent 0.5px);
|
||||
background-size: 20px 22px;
|
||||
background-position: 53% 50%;
|
||||
|
||||
&:not([zen-has-hover='true']) > .titlebar-buttonbox {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
transition:
|
||||
left 0.25s ease,
|
||||
right 0.25s ease,
|
||||
left 0.15s ease,
|
||||
right 0.15s ease,
|
||||
opacity 1.5s ease;
|
||||
top: 0;
|
||||
bottom: var(--zen-element-separation);
|
||||
opacity: 0;
|
||||
padding: 0 var(--zen-compact-float) !important;
|
||||
opacity: 0;
|
||||
|
||||
:root[zen-single-toolbar='true'] & {
|
||||
top: var(--zen-element-separation);
|
||||
@@ -59,13 +59,13 @@
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
& #urlbar[open] {
|
||||
& #urlbar[open]:not([zen-floating-urlbar='true']) {
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:not([zen-right-side='true']) #navigator-toolbox {
|
||||
left: calc(-1 * var(--zen-sidebar-width) + var(--zen-element-separation));
|
||||
left: calc(-1 * var(--zen-sidebar-width) + 1px);
|
||||
}
|
||||
|
||||
/* When we have multiple toolbars and the top-toolbar is NOT being hidden,
|
||||
@@ -82,7 +82,7 @@
|
||||
--zen-compact-float: calc(var(--zen-element-separation) + 1px);
|
||||
|
||||
&:not([animate='true']) {
|
||||
right: calc(-1 * var(--zen-sidebar-width) + var(--zen-element-separation));
|
||||
right: calc(-1 * var(--zen-sidebar-width) + 1px);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,15 @@
|
||||
background-size: 2000px !important; /* Dont ask me why */
|
||||
backdrop-filter: blur(5px) !important;
|
||||
}
|
||||
|
||||
& #urlbar[open][zen-floating-urlbar='true'] {
|
||||
--zen-urlbar-offset: var(--zen-sidebar-width);
|
||||
transition: left 0.05s ease;
|
||||
|
||||
#navigator-toolbox:has(&) {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#navigator-toolbox:hover,
|
||||
@@ -121,9 +130,9 @@
|
||||
#navigator-toolbox[movingtab],
|
||||
#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)
|
||||
*:is([panelopen='true'], [open='true'], #urlbar:not([zen-floating-urlbar='true']):focus-within):not(tab):not(.zen-compact-mode-ignore)
|
||||
) {
|
||||
&:not([animate='true']) {
|
||||
&:not([animate='true']):not(:has(#urlbar[zen-floating-urlbar='true']:hover)) {
|
||||
--zen-compact-mode-func: linear(
|
||||
0 0%,
|
||||
0.002748 1%,
|
||||
@@ -228,14 +237,20 @@
|
||||
1.003423 100%
|
||||
);
|
||||
transition:
|
||||
left 0.3125s var(--zen-compact-mode-func),
|
||||
right 0.3125s var(--zen-compact-mode-func);
|
||||
left 0.3s var(--zen-compact-mode-func),
|
||||
right 0.3s var(--zen-compact-mode-func);
|
||||
opacity: 1;
|
||||
|
||||
left: -1px;
|
||||
:root[zen-right-side='true'] & {
|
||||
right: -1px;
|
||||
left: auto;
|
||||
&:not([supress-primary-adjustment='true']) {
|
||||
left: -1px;
|
||||
:root[zen-right-side='true'] & {
|
||||
right: -1px;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
& #urlbar[open][zen-floating-urlbar='true'] {
|
||||
--zen-urlbar-offset: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,42 +9,49 @@
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
.zen-glance-background {
|
||||
transform: scale(0.98);
|
||||
backdrop-filter: blur(5px);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#zen-glance-sidebar-container {
|
||||
display: none;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
z-index: 999;
|
||||
|
||||
& toolbarbutton:hover {
|
||||
background: var(--button-background-color-hover);
|
||||
&[hidden='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
top: 10%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
padding: 5px;
|
||||
gap: 12px;
|
||||
left: 2%;
|
||||
|
||||
& toolbarbutton {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: light-dark(rgb(24, 24, 24), rgb(231, 231, 231));
|
||||
transition: background 0.2s ease;
|
||||
border-radius: 999px;
|
||||
appearance: none;
|
||||
box-shadow: 0 0 12px 1px rgba(0, 0, 0, 0.07);
|
||||
opacity: 0;
|
||||
|
||||
&:hover {
|
||||
background: light-dark(rgb(41, 41, 41), rgb(204, 204, 204));
|
||||
}
|
||||
|
||||
& label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& image {
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.browserSidebarContainer.zen-glance-overlay {
|
||||
box-shadow: none !important;
|
||||
|
||||
&[fade-out='true'] {
|
||||
background: transparent;
|
||||
opacity: 1;
|
||||
|
||||
& .browserContainer {
|
||||
opacity: 1;
|
||||
animation: zen-glance-content-animation-out 0.3s ease-in-out forwards !important;
|
||||
|
||||
& browser {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
& #zen-glance-sidebar-container {
|
||||
opacity: 0;
|
||||
transition: opacity 0.1s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .browserContainer {
|
||||
background: var(--zen-dialog-background);
|
||||
position: fixed;
|
||||
@@ -69,37 +76,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
& #zen-glance-sidebar-container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
top: 10%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
opacity: 0;
|
||||
background: var(--zen-dialog-background);
|
||||
|
||||
border: 1px solid var(--zen-colors-border);
|
||||
border-right: none;
|
||||
|
||||
border-top-left-radius: var(--zen-native-inner-radius);
|
||||
border-bottom-left-radius: var(--zen-native-inner-radius);
|
||||
|
||||
padding: 5px;
|
||||
gap: 6px;
|
||||
|
||||
animation: zen-glance-buttons-animation 0.2s ease-in-out forwards;
|
||||
animation-delay: 0.3s;
|
||||
|
||||
& toolbarbutton {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
& label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& browser {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -108,9 +84,7 @@
|
||||
}
|
||||
|
||||
&[animate-full='true'] {
|
||||
opacity: 1;
|
||||
animation: zen-glance-buttons-animation-full 0.2s ease-in-out forwards !important;
|
||||
|
||||
transform: translate(-50%, -50%);
|
||||
& #zen-glance-sidebar-container {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
@@ -118,22 +92,18 @@
|
||||
|
||||
&[animate='true'] {
|
||||
position: absolute;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
&:not([animate-end='true']) {
|
||||
pointer-events: none;
|
||||
|
||||
& browser {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
& #zen-glance-sidebar-container {
|
||||
opacity: 0;
|
||||
animation: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[fade-out='true'] {
|
||||
& browser {
|
||||
transition: opacity 0.1s ease;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& browser[animate-glance-open='true'] {
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#PanelUI-zen-gradient-generator {
|
||||
--panel-width: 300px;
|
||||
--panel-width: 350px;
|
||||
--panel-padding: 10px;
|
||||
min-width: var(--panel-width);
|
||||
}
|
||||
@@ -17,60 +17,10 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#PanelUI-zen-gradient-degrees {
|
||||
position: relative;
|
||||
border-radius: 999px;
|
||||
min-height: 50px;
|
||||
min-width: 50px;
|
||||
max-height: 50px;
|
||||
max-width: 50px;
|
||||
border: 3px solid var(--zen-primary-color);
|
||||
display: flex;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
|
||||
& .dot {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
/* +3 because of the border */
|
||||
width: 53px;
|
||||
height: 53px;
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
|
||||
&::after {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: var(--zen-colors-tertiary);
|
||||
box-shadow: 0 0 0 2px var(--zen-themed-toolbar-bg);
|
||||
cursor: grab;
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 0;
|
||||
border: 2px solid var(--zen-colors-border);
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
&[dragging='true']::after {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
& .text {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
#PanelUI-zen-gradient-generator-controls {
|
||||
padding-right: var(--panel-padding);
|
||||
align-items: center;
|
||||
gap: var(--panel-padding);
|
||||
border-bottom: 1px solid color-mix(in srgb, var(--zen-colors-border) 50%, transparent 50%);
|
||||
padding-bottom: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#zen-theme-picker-color {
|
||||
@@ -97,8 +47,8 @@
|
||||
|
||||
#PanelUI-zen-gradient-generator-color-custom-add {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -225,7 +175,7 @@
|
||||
inset: 0;
|
||||
background-image: linear-gradient(to right, var(--zen-primary-color) 1px, transparent 1px),
|
||||
linear-gradient(to bottom, var(--zen-primary-color) 1px, transparent 1px);
|
||||
background-size: 24px 24px;
|
||||
background-size: 20px 20px;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -239,13 +189,13 @@
|
||||
& .zen-theme-picker-dot {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background: var(--zen-theme-picker-dot-color);
|
||||
box-shadow: 0 0 0 2px var(--zen-themed-toolbar-bg);
|
||||
cursor: pointer;
|
||||
border: 2px solid #fff;
|
||||
border: 3px solid #fff;
|
||||
animation: zen-theme-picker-dot-animation 0.5s;
|
||||
transition: transform 0.2s;
|
||||
transform: translate(-50%, -50%);
|
||||
@@ -255,3 +205,42 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#PanelUI-zen-gradient-generator-color-actions {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
z-index: 1;
|
||||
transform: translateX(-50%);
|
||||
& .separator,
|
||||
& button {
|
||||
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1));
|
||||
}
|
||||
|
||||
& button {
|
||||
border: none !important;
|
||||
padding: 0.4rem !important;
|
||||
min-width: fit-content !important;
|
||||
transition: background 0.2s;
|
||||
& .button-text {
|
||||
display: none;
|
||||
}
|
||||
appearance: none;
|
||||
&:hover {
|
||||
background: light-dark(rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.2));
|
||||
}
|
||||
}
|
||||
|
||||
& .separator {
|
||||
width: 1px;
|
||||
margin: 0 0.5rem;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media not (-moz-bool-pref: 'zen.theme.gradient.show-custom-colors') {
|
||||
#PanelUI-zen-gradient-generator-custom-colors {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,11 @@ panel {
|
||||
--panel-border-radius: var(--zen-native-inner-radius);
|
||||
}
|
||||
|
||||
/* split-view popup */
|
||||
#confirmation-hint {
|
||||
--arrowpanel-background: var(--zen-colors-primary);
|
||||
}
|
||||
|
||||
/* app menu */
|
||||
.addon-banner-item,
|
||||
.panel-banner-item {
|
||||
@@ -344,3 +349,30 @@ menuitem {
|
||||
#editBMPanel_workspaceList input[type='checkbox'] {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* Section: Toast notifications */
|
||||
|
||||
#zen-toast-container {
|
||||
position: fixed;
|
||||
top: calc(var(--zen-element-separation) * 2);
|
||||
right: calc(var(--zen-element-separation) * 2);
|
||||
z-index: 1000;
|
||||
gap: 1rem;
|
||||
|
||||
& .zen-toast {
|
||||
padding: 0.9rem 0.8rem;
|
||||
border-radius: 12px;
|
||||
background-color: var(--button-primary-bgcolor);
|
||||
color: var(--button-primary-color);
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
width: fit-content;
|
||||
|
||||
& .description {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,14 +42,13 @@
|
||||
#zen-tabbox-wrapper {
|
||||
& #sidebar-splitter {
|
||||
opacity: 0;
|
||||
margin-inline-end: -4px;
|
||||
margin: 0 calc(-1 * var(--zen-element-separation));
|
||||
}
|
||||
|
||||
& #sidebar-box {
|
||||
border-radius: var(--zen-native-inner-radius);
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--zen-colors-border);
|
||||
|
||||
:root:not([zen-right-side='true']) &[positionend='true'] {
|
||||
margin-right: var(--zen-element-separation);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
--tab-min-height: 10px !important;
|
||||
}
|
||||
|
||||
#vertical-pinned-tabs-container-separator {
|
||||
.vertical-pinned-tabs-container-separator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
}
|
||||
|
||||
/* Other UI Elements */
|
||||
#zen-current-workspace-indicator {
|
||||
.zen-current-workspace-indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ height: var(--zen-toolbar-height);
|
||||
}
|
||||
}
|
||||
|
||||
&:not([zen-has-hover='true']):not([has-popup-menu]):not(:focus-within) {
|
||||
&:not([zen-has-hover='true']):not([has-popup-menu]):not(:focus-within):not(:has(*:is([panelopen='true'], [open='true']))) {
|
||||
transition-delay: 0.2s;
|
||||
height: var(--zen-element-separation);
|
||||
overflow: hidden;
|
||||
|
||||
@@ -19,9 +19,17 @@
|
||||
height: var(--zen-toolbar-height);
|
||||
}
|
||||
|
||||
@media (-moz-platform: macos) and (not (-moz-bool-pref: 'zen.view.mac.show-three-dot-menu')) {
|
||||
&:not([customizing]) #PanelUI-button:not([open]):not([panelopen]) {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
& #zen-sidebar-top-buttons .toolbarbutton-1 {
|
||||
& > .toolbarbutton-icon {
|
||||
padding: 5px;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +57,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
#vertical-pinned-tabs-container, #tabbrowser-arrowscrollbox {
|
||||
.tabbrowser-tab[fadein='true'][zen-initial-fadein='true'] {
|
||||
animation: zen-new-tab-appear-vertical 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
}
|
||||
#tabbrowser-arrowscrollbox {
|
||||
min-height: fit-content !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +72,14 @@
|
||||
}
|
||||
|
||||
#browser {
|
||||
--zen-toolbox-padding: max(5px, calc(var(--zen-element-separation) / 1.5));
|
||||
--zen-min-toolbox-padding: .4rem;
|
||||
@media (-moz-platform: macos) {
|
||||
--zen-min-toolbox-padding: .52rem;
|
||||
}
|
||||
@media (-moz-platform: linux) {
|
||||
--zen-min-toolbox-padding: .35rem;
|
||||
}
|
||||
--zen-toolbox-padding: max(var(--zen-min-toolbox-padding), calc(var(--zen-element-separation) / 1.5));
|
||||
}
|
||||
|
||||
:root[zen-single-toolbar='true'] {
|
||||
@@ -74,17 +87,6 @@
|
||||
width: -moz-available !important;
|
||||
}
|
||||
|
||||
.sharing-icon,
|
||||
#identity-icon,
|
||||
.urlbar-icon,
|
||||
#permissions-granted-icon,
|
||||
#tracking-protection-icon,
|
||||
#tracking-protection-icon-box,
|
||||
#blocked-permissions-container > .blocked-permission-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
#identity-icon-box,
|
||||
#identity-permission-box {
|
||||
margin-top: auto;
|
||||
@@ -99,7 +101,7 @@
|
||||
}
|
||||
|
||||
& #nav-bar {
|
||||
margin-bottom: 6px;
|
||||
margin-bottom: var(--zen-toolbox-padding);
|
||||
|
||||
& toolbarspring {
|
||||
display: none;
|
||||
@@ -115,23 +117,38 @@
|
||||
}
|
||||
}
|
||||
|
||||
#vertical-pinned-tabs-container-separator {
|
||||
.vertical-pinned-tabs-container-separator {
|
||||
background: light-dark(rgba(1, 1, 1, 0.075), rgba(255, 255, 255, 0.1));
|
||||
margin: 8px auto;
|
||||
border: none;
|
||||
height: 1px;
|
||||
max-height: 1px;
|
||||
width: 98%;
|
||||
transition: margin 0.2s ease-in-out, background 0.2s ease-in-out, max-height 0.2s ease-in-out;
|
||||
|
||||
#vertical-pinned-tabs-container:not(:has(tab:not([hidden]))) + & {
|
||||
display: none;
|
||||
#vertical-pinned-tabs-container .zen-workspace-tabs-section[hide-separator] & {
|
||||
max-height: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
#navigator-toolbox {
|
||||
--border-radius-medium: 12px;
|
||||
--tab-border-radius: 8px;
|
||||
--border-radius-medium: 10px;
|
||||
--tab-border-radius: 6px;
|
||||
--zen-toolbox-min-width: 1px;
|
||||
|
||||
@media (-moz-platform: windows) {
|
||||
/* More native look */
|
||||
--border-radius-medium: 8px;
|
||||
--tab-border-radius: 6px;
|
||||
}
|
||||
|
||||
@media (-moz-platform: macos) {
|
||||
/* More native look */
|
||||
--border-radius-medium: 12px;
|
||||
--tab-border-radius: 10px;
|
||||
}
|
||||
|
||||
--tab-hover-background-color: color-mix(in srgb, var(--toolbarbutton-hover-background) 50%, transparent 50%);
|
||||
|
||||
min-width: var(--zen-toolbox-min-width);
|
||||
@@ -221,7 +238,9 @@
|
||||
#tabbrowser-tabs {
|
||||
margin-inline-start: 0 !important;
|
||||
padding-inline-start: 0 !important;
|
||||
overflow-x: hidden;
|
||||
overflow-y: unset !important; /* DO NOT CHANGE THIS: Firefox renders badly workspace changes */
|
||||
overflow-x: clip;
|
||||
overflow-clip-margin: var(--zen-toolbox-padding);
|
||||
|
||||
--tab-inner-inline-margin: 0;
|
||||
|
||||
@@ -230,27 +249,20 @@
|
||||
|
||||
--tab-block-margin: 2px;
|
||||
--tab-selected-bgcolor: light-dark(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.12));
|
||||
--tab-selected-shadow: 0 1px 1px 1px light-dark(rgba(0, 0, 0, 0.09), rgba(0, 0, 0, 0.1)) !important;
|
||||
grid-gap: 0 !important;
|
||||
|
||||
&[overflow]::after,
|
||||
#vertical-tabs-newtab-button {
|
||||
#vertical-tabs-newtab-button,
|
||||
#vertical-pinned-tabs-container-separator { /* notice #vertical-pinned-tabs-container-separator is an ID */
|
||||
/* Hide separator they give us, eww */
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
& .tabbrowser-tab {
|
||||
transition: scale 0.07s ease;
|
||||
#tabbrowser-tabs &:not([zen-essential='true']) {
|
||||
#tabbrowser-tabs[dont-animate-tabs] & {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:is([selected], [multiselected], [visuallyselected]) .tab-background {
|
||||
box-shadow: 0 1px 1px 1px light-dark(rgba(0, 0, 0, 0.09), rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
}
|
||||
|
||||
&:not([zen-essential='true']):active {
|
||||
&:active {
|
||||
scale: 0.98;
|
||||
}
|
||||
|
||||
@@ -258,7 +270,6 @@
|
||||
padding: 0 !important;
|
||||
|
||||
position: relative;
|
||||
border-radius: var(--border-radius-medium);
|
||||
|
||||
& .tab-background {
|
||||
overflow: hidden;
|
||||
@@ -269,10 +280,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&[selected] .tab-background {
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
@media (-moz-bool-pref: 'zen.tabs.dim-pending') {
|
||||
&[pending='true'] .tab-icon-image {
|
||||
opacity: 0.5;
|
||||
@@ -282,14 +289,23 @@
|
||||
/* We have a tab inside a tab, this means, it's a glance tab */
|
||||
& .tabbrowser-tab {
|
||||
pointer-events: none;
|
||||
margin: 0;
|
||||
margin: 0 0 0 4px;
|
||||
--toolbarbutton-inner-padding: 0;
|
||||
--border-radius-medium: 8px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
--tab-min-height: 24px;
|
||||
--tab-min-width: 24px;
|
||||
|
||||
& .tab-background {
|
||||
background: transparent;
|
||||
background: var(--zen-toolbar-element-bg) !important;
|
||||
margin-block: 0 !important;
|
||||
margin-inline: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
& .tab-content {
|
||||
padding: 0 5px;
|
||||
}
|
||||
& label { display: none !important; }
|
||||
& .tab-close-button,
|
||||
& .tab-reset-button {
|
||||
@@ -298,19 +314,26 @@
|
||||
|
||||
& .tab-icon-image {
|
||||
--toolbarbutton-inner-padding: 0 !important;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* On essentials, glance tabs are floating */
|
||||
&[zen-essential='true'] .tabbrowser-tab {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
--tab-collapsed-width: 35px;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
--tab-collapsed-width: 34px;
|
||||
--tab-min-height: 16px;
|
||||
width: var(--tab-collapsed-width) !important;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
& .tab-background {
|
||||
/* Solid colors because we don't want to show the background */
|
||||
background: light-dark(rgb(249, 249, 249), rgb(63, 63, 63)) !important;
|
||||
border: 2px solid light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,6 +344,7 @@
|
||||
align-items: center;
|
||||
|
||||
padding-top: var(--zen-element-separation);
|
||||
--toolbarbutton-inner-padding: 5px;
|
||||
|
||||
& > toolbarbutton:not(#zen-workspaces-button) {
|
||||
padding: 0 !important;
|
||||
@@ -342,11 +366,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
#zen-tabs-wrapper {
|
||||
min-height: fit-content;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
#zen-browser-tabs-container {
|
||||
overflow-x: clip !important; /* might break custom css with new design, so let's force it */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#vertical-pinned-tabs-container {
|
||||
padding-inline-end: 0 !important;
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 12 * (var(--tab-min-height) + 2 * var(--tab-block-margin))) !important;
|
||||
min-height: fit-content !important;
|
||||
overflow-x: clip;
|
||||
overflow-y: visible;
|
||||
max-height: unset !important;
|
||||
|
||||
& .tabbrowser-tab:not(:hover) .tab-background:not([selected]):not([multiselected]) {
|
||||
background: transparent !important;
|
||||
@@ -403,7 +442,7 @@
|
||||
width: calc(100% - 10px) !important;
|
||||
}
|
||||
|
||||
& #zen-current-workspace-indicator-icon[no-icon='true'] {
|
||||
& .zen-current-workspace-indicator-icon[no-icon='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -454,7 +493,7 @@
|
||||
bottom: calc(-0.5 * var(--zen-toolbox-padding));
|
||||
}
|
||||
|
||||
& > *:not(tabs):not(#search-container):not(#zen-workspaces-button),
|
||||
& > :is(toolbaritem, toolbarbutton):not(#search-container):not(#zen-workspaces-button),
|
||||
& #tabbrowser-arrowscrollbox-periphery > toolbarbutton {
|
||||
width: 100% !important;
|
||||
border-radius: var(--border-radius-medium) !important;
|
||||
@@ -483,7 +522,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--toolbarbutton-hover-background) !important;
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
|
||||
& image,
|
||||
label {
|
||||
@@ -534,11 +573,11 @@
|
||||
#navigator-toolbox:not([zen-sidebar-expanded='true']) {
|
||||
max-width: var(--zen-toolbox-max-width) !important;
|
||||
min-width: var(--zen-toolbox-max-width) !important;
|
||||
& #zen-current-workspace-indicator-name,
|
||||
& .zen-current-workspace-indicator-name,
|
||||
& .toolbarbutton-text {
|
||||
display: none !important;
|
||||
}
|
||||
& #zen-current-workspace-indicator {
|
||||
& .zen-current-workspace-indicator {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
display: flex;
|
||||
@@ -687,31 +726,33 @@
|
||||
/* Mark: Move sidebar to the right */
|
||||
:root[zen-right-side='true'] {
|
||||
& #navigator-toolbox {
|
||||
order: 3 !important;
|
||||
order: 10 !important;
|
||||
}
|
||||
|
||||
& #zen-sidebar-splitter {
|
||||
order: 2 !important;
|
||||
order: 9 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark: Override the default tab close button */
|
||||
#tabbrowser-tabs {
|
||||
& .tabbrowser-tab {
|
||||
&[pinned] .tab-close-button {
|
||||
&[pinned]:not([pending='true']) .tab-close-button {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
&[pinned]:not([zen-essential]):hover .tab-reset-button,
|
||||
&[pinned][visuallyselected]:not([zen-essential]) .tab-reset-button {
|
||||
display: block;
|
||||
&[pinned]:not([pending='true']):not([zen-essential]) {
|
||||
&:hover .tab-reset-button,
|
||||
&[visuallyselected] .tab-reset-button {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&[zen-essential] .tab-reset-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:not([pinned]) .tab-reset-button {
|
||||
&:not([pinned][visuallyselected]) .tab-reset-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -727,7 +768,7 @@
|
||||
border-radius: var(--tab-border-radius);
|
||||
color: inherit;
|
||||
fill: currentColor;
|
||||
padding: 6px;
|
||||
padding: var(--tab-close-button-padding);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
outline: var(--toolbarbutton-outline);
|
||||
@@ -848,10 +889,22 @@
|
||||
@media (-moz-bool-pref: 'zen.tabs.show-newtab-vertical') {
|
||||
#tabs-newtab-button {
|
||||
display: flex !important;
|
||||
transition: scale 0.1s ease;
|
||||
& .toolbarbutton-text {
|
||||
align-items: center;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&[open] {
|
||||
scale: 0.98;
|
||||
}
|
||||
|
||||
&[in-urlbar] {
|
||||
background: var(--tab-selected-bgcolor) !important;
|
||||
opacity: 1 !important;
|
||||
box-shadow: var(--tab-selected-shadow);
|
||||
}
|
||||
}
|
||||
|
||||
#tabbrowser-arrowscrollbox-periphery {
|
||||
@@ -896,26 +949,25 @@
|
||||
transition: max-height 0.3s ease-out;
|
||||
opacity: 1;
|
||||
grid-template-columns: repeat(auto-fit, minmax(var(--tab-pinned-min-width-expanded), auto));
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
overflow: hidden;
|
||||
scrollbar-width: thin;
|
||||
display: grid;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#zen-essentials-container .tabbrowser-tab {
|
||||
#zen-essentials-container > .tabbrowser-tab {
|
||||
--toolbarbutton-inner-padding: 0;
|
||||
max-width: unset;
|
||||
width: 100% !important;
|
||||
border-radius: var(--border-radius-medium);
|
||||
|
||||
& .tab-background {
|
||||
border-radius: var(--border-radius-medium) !important;
|
||||
transition: background 0.1s ease-in-out;
|
||||
}
|
||||
|
||||
--tab-selected-bgcolor: light-dark(rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.2));
|
||||
|
||||
&[selected] .tab-background {
|
||||
box-shadow: 0 1px 1px 1px light-dark(rgba(0, 0, 0, 0.09), rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
|
||||
&:not([selected], [multiselected="true"]) .tab-background {
|
||||
&:not([visuallyselected], [multiselected="true"]) .tab-background {
|
||||
background: var(--zen-toolbar-element-bg);
|
||||
border: none;
|
||||
}
|
||||
@@ -938,8 +990,12 @@
|
||||
margin-inline-end: 0 !important;
|
||||
}
|
||||
|
||||
&:hover .tab-background {
|
||||
background: var(--tab-selected-bgcolor);
|
||||
}
|
||||
|
||||
@media (-moz-bool-pref: 'zen.theme.essentials-favicon-bg') {
|
||||
&[selected] .tab-background {
|
||||
&[visuallyselected] > .tab-stack > .tab-background {
|
||||
&::after {
|
||||
content: "";
|
||||
inset: -50%;
|
||||
@@ -956,19 +1012,19 @@
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
background: light-dark(rgba(255, 255, 255, 0.75), rgba(68, 64, 64, 0.75));
|
||||
background: light-dark(rgba(255, 255, 255, 0.85), rgba(68, 64, 64, 0.85));
|
||||
margin: 2px;
|
||||
border-radius: calc(var(--border-radius-medium) - 2px);
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
content: "";
|
||||
transition: background 0.2s ease-in-out;
|
||||
transition: background 0.1s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&[selected]:hover .tab-background::before {
|
||||
background: light-dark(rgba(255, 255, 255, 0.70), rgba(68, 64, 64, 0.70));
|
||||
&[visuallyselected]:hover .tab-background::before {
|
||||
background: light-dark(rgba(255, 255, 255, 0.80), rgba(68, 64, 64, 0.80));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1026,3 +1082,80 @@
|
||||
%include vertical-tabs-topbuttons-fix.css
|
||||
}
|
||||
}
|
||||
|
||||
/* Vertical tabs reordering indicators */
|
||||
#zen-drag-indicator {
|
||||
--zen-drag-indicator-height: 2px;
|
||||
--zen-drag-indicator-bg: color-mix(in srgb, var(--zen-primary-color) 50%, light-dark(rgba(0, 0, 0, .85), rgba(255, 255, 255, .95)) 50%);
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
background: var(--zen-drag-indicator-bg);
|
||||
pointer-events: none;
|
||||
border-radius: 5px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: calc(2 * var(--zen-drag-indicator-height));
|
||||
width: calc(2 * var(--zen-drag-indicator-height));
|
||||
border: var(--zen-drag-indicator-height) solid var(--zen-drag-indicator-bg);
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&[orientation='horizontal'] {
|
||||
left: calc(var(--indicator-left) + 2 * var(--zen-drag-indicator-height) + 4px);
|
||||
width: calc(var(--indicator-width) - 2 * var(--zen-drag-indicator-height) - 4px);
|
||||
height: var(--zen-drag-indicator-height);
|
||||
transition: top 0.1s ease-out, left 0.1s ease-out, width 0.1s ease-out;
|
||||
|
||||
&::before {
|
||||
left: calc(-2 * var(--zen-drag-indicator-height));
|
||||
top: 50%;
|
||||
transform: translate(calc(-1 * var(--zen-drag-indicator-height)), -50%);
|
||||
}
|
||||
}
|
||||
|
||||
&[orientation='vertical'] {
|
||||
top: calc(var(--indicator-top) + 2 * var(--zen-drag-indicator-height) + 4px);
|
||||
height: calc(var(--indicator-height) - 2 * var(--zen-drag-indicator-height) - 4px);
|
||||
width: var(--zen-drag-indicator-height);
|
||||
transition: top 0.1s ease-out, left 0.1s ease-out, height 0.1s ease-out;
|
||||
|
||||
&::before {
|
||||
top: calc(-2 * var(--zen-drag-indicator-height));
|
||||
left: 50%;
|
||||
transform: translate(-50%, calc(-1 * var(--zen-drag-indicator-height)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Horizontal tabs reordering indicators */
|
||||
#zen-essentials-container .tabbrowser-tab.drag-over-before {
|
||||
box-shadow: 3px 0 6px -2px var(--toolbarbutton-active-background, rgba(0, 255, 0, 0.2));
|
||||
}
|
||||
|
||||
#zen-essentials-container .tabbrowser-tab.drag-over-after {
|
||||
box-shadow: -3px 0 6px -2px var(--toolbarbutton-active-background, rgba(0, 255, 0, 0.2));
|
||||
}
|
||||
|
||||
/* Renaming tabs */
|
||||
.tab-label-container-editing {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#tab-label-input {
|
||||
white-space: nowrap;
|
||||
overflow-x: scroll;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Section: tab workspaces stylings */
|
||||
.zen-workspace-tabs-section {
|
||||
position: absolute;
|
||||
transform: translateX(-100%);
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
:root,
|
||||
.zenLooksAndFeelColorOption {
|
||||
/** We also add `.zenLooksAndFeelColorOption` so that it recalculates the colors when the theme changes
|
||||
* in the preferences page.
|
||||
*/
|
||||
* in the preferences page.
|
||||
*/
|
||||
|
||||
/* Default values */
|
||||
--zen-border-radius: 7px;
|
||||
@@ -46,21 +46,21 @@
|
||||
|
||||
--in-content-primary-button-background: color-mix(
|
||||
in srgb,
|
||||
var(--zen-primary-color) 10%,
|
||||
var(--zen-branding-bg) 90%
|
||||
var(--zen-primary-color) 30%,
|
||||
var(--zen-branding-bg-reverse) 70%
|
||||
) !important;
|
||||
--in-content-primary-button-background-hover: color-mix(
|
||||
in srgb,
|
||||
var(--zen-primary-color) 15%,
|
||||
var(--zen-branding-bg) 85%
|
||||
var(--zen-primary-color) 35%,
|
||||
var(--zen-branding-bg-reverse) 65%
|
||||
) !important;
|
||||
--in-content-primary-button-background-active: color-mix(
|
||||
in srgb,
|
||||
var(--zen-primary-color) 20%,
|
||||
var(--zen-branding-bg) 80%
|
||||
var(--zen-primary-color) 40%,
|
||||
var(--zen-branding-bg-reverse) 60%
|
||||
) !important;
|
||||
--button-text-color-primary: var(--zen-branding-bg-reverse) !important;
|
||||
--in-content-primary-button-text-color: var(--zen-colors-primary-foreground) !important;
|
||||
--button-text-color-primary: var(--zen-branding-bg) !important;
|
||||
--in-content-primary-button-text-color: var(--zen-branding-bg) !important;
|
||||
--in-content-primary-button-border-color: transparent !important;
|
||||
--in-content-primary-button-border-hover: transparent !important;
|
||||
--in-content-primary-button-border-active: var(--zen-colors-border) !important;
|
||||
@@ -72,7 +72,7 @@
|
||||
/* This is like the secondary button */
|
||||
--in-content-button-background: transparent !important;
|
||||
--in-content-button-text-color: var(--zen-secondary-btn-color) !important;
|
||||
--in-content-button-background-hover: color-mix(in srgb, var(--zen-primary-color) 5%, var(--zen-branding-bg) 60%) !important;
|
||||
--in-content-button-background-hover: color-mix(in srgb, currentColor 3%, transparent 97%) !important;
|
||||
--button-bgcolor: var(--in-content-button-background) !important;
|
||||
--button-hover-bgcolor: var(--in-content-button-background-hover) !important;
|
||||
--button-hover-color: var(--in-content-button-text-color-hover) !important;
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
--button-background-color: var(--in-content-button-background) !important;
|
||||
--button-background-color-hover: var(--in-content-button-background-hover) !important;
|
||||
--button-background-color-active: var(--in-content-primary-button-background-active) !important;
|
||||
--button-background-color-active: color-mix(in srgb, currentColor 5%, transparent 95%) !important;
|
||||
|
||||
--color-accent-primary: var(--button-primary-bgcolor) !important;
|
||||
--color-accent-primary-hover: var(--button-primary-hover-bgcolor) !important;
|
||||
@@ -104,7 +104,7 @@
|
||||
--zen-button-border-radius: 5px;
|
||||
--zen-button-padding: 0.6rem 1.2rem;
|
||||
|
||||
--zen-toolbar-element-bg: light-dark(rgba(0, 0, 0, 0.11), rgba(255, 255, 255, 0.11));
|
||||
--zen-toolbar-element-bg: light-dark(rgba(0, 0, 0, 0.07), rgba(255, 255, 255, 0.11));
|
||||
|
||||
/* Toolbar */
|
||||
--zen-toolbar-height: 38px;
|
||||
@@ -131,6 +131,8 @@
|
||||
--toolbarbutton-border-radius: 6px;
|
||||
--urlbar-margin-inline: 1px !important;
|
||||
|
||||
--tab-icon-overlay-stroke: light-dark(white, black) !important;
|
||||
|
||||
--fp-contextmenu-border-radius: 8px;
|
||||
--fp-contextmenu-padding: calc(4px - var(--fp-contextmenu-menuitem-border-width)) 0;
|
||||
--fp-contextmenu-menuitem-border-radius: calc(4px + var(--fp-contextmenu-menuitem-border-width));
|
||||
@@ -146,6 +148,8 @@
|
||||
--fp-contextmenu-bgcolor: light-dark(Menu, rgb(43 42 51 / 0.95));
|
||||
--toolbar-bgcolor: transparent;
|
||||
|
||||
--tab-close-button-padding: 5px !important;
|
||||
|
||||
--toolbarbutton-active-background: var(--zen-toolbar-element-bg);
|
||||
|
||||
--input-bgcolor: var(--zen-colors-tertiary) !important;
|
||||
@@ -153,19 +157,19 @@
|
||||
--zen-themed-toolbar-bg: light-dark(var(--zen-branding-bg), #161616);
|
||||
--zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #161616);
|
||||
|
||||
--zen-workspace-indicator-height: 45px;
|
||||
|
||||
@media (-moz-windows-mica) or (-moz-platform: macos) {
|
||||
background: transparent;
|
||||
--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: transparent;
|
||||
@media (-moz-bool-pref: 'zen.widget.windows.acrylic') {
|
||||
--zen-themed-toolbar-bg-transparent: color-mix(in srgb, var(--zen-themed-toolbar-bg) 85%, transparent 15%);
|
||||
}
|
||||
}
|
||||
|
||||
--toolbar-field-background-color: var(--zen-colors-input-bg) !important;
|
||||
--arrowpanel-background: var(--zen-dialog-background) !important;
|
||||
|
||||
--tab-selected-shadow: none !important;
|
||||
--zen-big-shadow: 0 0 9.73px 0px light-dark(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.25));
|
||||
|
||||
/* Nativity */
|
||||
@@ -176,10 +180,10 @@
|
||||
--zen-native-inner-radius: var(
|
||||
--zen-webview-border-radius,
|
||||
/* Inner radius calculation:
|
||||
* 1. If the native radius - the separation is less than 4px, use 4px.
|
||||
* 2. Otherwise, use the the calculated value (inner radius = outer radius - separation).
|
||||
*/
|
||||
max(5px, calc(var(--zen-native-content-radius) - var(--zen-element-separation)))
|
||||
* 1. If the native radius - the separation is less than 4px, use 4px.
|
||||
* 2. Otherwise, use the the calculated value (inner radius = outer radius - separation).
|
||||
*/
|
||||
max(5px, calc(var(--zen-native-content-radius) - var(--zen-element-separation) / 2))
|
||||
);
|
||||
|
||||
/** Other theme-related styles */
|
||||
@@ -209,7 +213,7 @@
|
||||
--zen-colors-primary-foreground: color-mix(in srgb, var(--zen-primary-color) 80%, white 20%);
|
||||
|
||||
--zen-colors-input-bg: color-mix(in srgb, var(--zen-primary-color) 1%, var(--zen-dark-color-mix-base) 99%);
|
||||
--zen-colors-border: color-mix(in srgb, var(--zen-colors-secondary) 20%, rgb(53, 53, 53) 80%);
|
||||
--zen-colors-border: color-mix(in srgb, var(--zen-colors-secondary) 20%, rgb(79, 79, 79) 80%);
|
||||
--zen-colors-border-contrast: color-mix(in srgb, var(--zen-colors-secondary) 10%, rgba(255, 255, 255, 0.11) 90%);
|
||||
|
||||
--zen-dialog-background: var(--zen-dark-color-mix-base);
|
||||
@@ -218,33 +222,3 @@
|
||||
--zen-browser-gradient-base: color-mix(in srgb, var(--zen-primary-color) 30%, var(--zen-dark-color-mix-base) 70%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@media (-moz-bool-pref: 'zen.theme.color-prefs.amoled') {
|
||||
:root {
|
||||
--zen-dark-color-mix-base: hsl(5 5 5);
|
||||
--zen-urlbar-background: color-mix(in srgb, var(--zen-primary-color) 4%, rgb(0, 0, 0) 96%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (-moz-bool-pref: 'zen.theme.color-prefs.colorful') {
|
||||
:root {
|
||||
--zen-in-content-dialog-background: rgb(28, 28, 32);
|
||||
|
||||
--zen-colors-primary: color-mix(in srgb, var(--zen-primary-color) 50%, black 50%);
|
||||
--zen-colors-secondary: color-mix(in srgb, var(--zen-primary-color) 40%, black 60%);
|
||||
--zen-colors-tertiary: color-mix(in srgb, var(--zen-primary-color) 15%, black 85%);
|
||||
|
||||
--zen-colors-hover-bg: color-mix(in srgb, var(--zen-primary-color) 90%, black 10%);
|
||||
--zen-colors-primary-foreground: color-mix(in srgb, var(--zen-primary-color) 80%, white 20%);
|
||||
|
||||
--zen-colors-input-bg: color-mix(in srgb, var(--zen-primary-color) 10%, black 80%);
|
||||
--zen-colors-border: color-mix(in srgb, var(--zen-colors-secondary) 80%, black 20%);
|
||||
|
||||
--zen-dialog-background: color-mix(in srgb, var(--zen-primary-color) 10%, black 90%);
|
||||
--zen-urlbar-background: color-mix(in srgb, var(--zen-primary-color) 8%, rgb(15, 15, 15) 92%);
|
||||
|
||||
--zen-browser-gradient-base: color-mix(in srgb, var(--zen-primary-color) 30%, black 70%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
}
|
||||
|
||||
#urlbar {
|
||||
--toolbarbutton-border-radius: 10px;
|
||||
--urlbarView-separator-color: var(--zen-colors-border);
|
||||
--toolbarbutton-border-radius: 8px;
|
||||
--urlbarView-separator-color: light-dark(hsl(0, 0%, 90%), hsl(0, 0%, 20%));
|
||||
--urlbarView-hover-background: var(--toolbarbutton-hover-background);
|
||||
--urlbarView-highlight-background: var(--toolbarbutton-hover-background);
|
||||
border-radius: var(--toolbarbutton-border-radius);
|
||||
@@ -32,10 +32,9 @@
|
||||
|
||||
#urlbar-background {
|
||||
background: var(--zen-toolbar-element-bg) !important;
|
||||
border-radius: var(--border-radius-medium);
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
#urlbar-background {
|
||||
border: none !important;
|
||||
margin: 1px;
|
||||
|
||||
@@ -122,26 +121,32 @@
|
||||
}
|
||||
|
||||
#urlbar[breakout-extend='true'] #urlbar-background {
|
||||
border: 1px solid var(--zen-colors-border) !important;
|
||||
box-shadow: var(--zen-big-shadow) !important;
|
||||
box-shadow:
|
||||
inset 0 0 0.5px 1px hsla(0, 0%, 100%, 0.1),
|
||||
/* 2. shadow ring 👇 */ 0 0 0 1px hsla(230, 13%, 9%, 0.075),
|
||||
/* 3. multiple soft shadows 👇 */ 0 0.3px 0.4px hsla(230, 13%, 9%, 0.02),
|
||||
0 0.9px 1.5px hsla(230, 13%, 9%, 0.045),
|
||||
0 6.5px 12px hsla(230, 13%, 9%, 0.1) !important;
|
||||
backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
:root[zen-single-toolbar='true'] {
|
||||
.urlbar-page-action:not([open]),
|
||||
.identity-box-button:not([open]),
|
||||
#tracking-protection-icon-container {
|
||||
margin-inline-end: calc(-16px - 2 * var(--urlbar-icon-padding)) !important;
|
||||
margin-inline-end: calc(-8px - 2 * var(--urlbar-icon-padding)) !important;
|
||||
opacity: 0;
|
||||
transition: all 0.2s;
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
#identity-permission-box > *:not(#permissions-granted-icon) {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#urlbar[open] :is(#tracking-protection-icon-container, .urlbar-page-action),
|
||||
#urlbar:hover :is(#tracking-protection-icon-container, .urlbar-page-action),
|
||||
#urlbar[open] :is(#tracking-protection-icon-container, .urlbar-page-action, .identity-box-button),
|
||||
#urlbar:hover :is(#tracking-protection-icon-container, .urlbar-page-action, .identity-box-button),
|
||||
.urlbar-page-action[open],
|
||||
.identity-box-button[open],
|
||||
#tracking-protection-icon-container[open] {
|
||||
opacity: 1;
|
||||
margin-inline-end: 0 !important;
|
||||
@@ -235,9 +240,23 @@ button.popup-notification-dropmarker {
|
||||
}
|
||||
|
||||
@container urlbar-container (width < 350px) {
|
||||
#userContext-icons {
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
#userContext-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#userContext-indicator {
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
|
||||
#urlbar:hover:not([breakout-extend='true']) #userContext-icons {
|
||||
margin-inline-end: calc(-16px - 2 * var(--urlbar-icon-padding)) !important;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 550px) {
|
||||
@@ -275,7 +294,7 @@ button.popup-notification-dropmarker {
|
||||
#urlbar .urlbar-page-action,
|
||||
#urlbar #tracking-protection-icon-container,
|
||||
#urlbar:not([breakout-extend='true']) #identity-box:is(:not(.chromeUI), [pageproxystate='invalid']) #identity-icon-box {
|
||||
border-radius: 10px !important;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
/* Extensions or similar */
|
||||
@@ -374,13 +393,14 @@ button.popup-notification-dropmarker {
|
||||
/* We cant have a transparent background with a backdrop-filter because on normal websites,
|
||||
the backdrop woudn't work, we would need to apply a clip-path to the site and that's not recommended
|
||||
due to performance issues */
|
||||
background-color: light-dark(rgb(247, 247, 247), var(--zen-branding-bg)) !important;
|
||||
background-color: light-dark(hsl(0, 0%, 100%), hsl(0, 0%, 14%)) !important;
|
||||
outline: 1px solid rgba(0, 0, 0, 0.3) !important;
|
||||
}
|
||||
}
|
||||
|
||||
:root[zen-single-toolbar='true'] {
|
||||
#urlbar[open] {
|
||||
min-width: 30vw;
|
||||
min-width: 35vw;
|
||||
}
|
||||
|
||||
&[zen-right-side='true'] #urlbar[open]:not([zen-floating-urlbar='true']) {
|
||||
@@ -392,20 +412,24 @@ button.popup-notification-dropmarker {
|
||||
z-index: 1000;
|
||||
max-width: 45vw;
|
||||
min-width: 45vw !important;
|
||||
font-size: 1.1em;
|
||||
--urlbar-container-height: 55px !important;
|
||||
--urlbar-margin-inline: 10px !important;
|
||||
position: absolute;
|
||||
|
||||
font-size: 1.15em !important;
|
||||
@media (-moz-platform: macos) {
|
||||
font-size: 1.5em !important;
|
||||
}
|
||||
top: calc(var(--zen-toolbar-height) * 2) !important;
|
||||
|
||||
--zen-urlbar-center: calc(var(--zen-urlbar-offset, 0px) + 28vw);
|
||||
|
||||
:root[zen-right-side='true'] & {
|
||||
right: 28vw !important;
|
||||
right: var(--zen-urlbar-center) !important;
|
||||
}
|
||||
|
||||
:root:not([zen-right-side='true']) & {
|
||||
left: 28vw !important;
|
||||
left: var(--zen-urlbar-center) !important;
|
||||
}
|
||||
|
||||
#urlbar-container:has(&) {
|
||||
@@ -476,10 +500,9 @@ button.popup-notification-dropmarker {
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: light-dark(var(--zen-colors-secondary), var(--zen-colors-primary)) !important;
|
||||
|
||||
.urlbarView-favicon {
|
||||
background-color: color-mix(in srgb, var(--zen-branding-bg-reverse) 20%, transparent 80%) !important;
|
||||
.urlbarView-favicon,
|
||||
& {
|
||||
background-color: color-mix(in srgb, var(--zen-branding-bg-reverse) 5%, transparent 95%) !important;
|
||||
}
|
||||
|
||||
.urlbarView-url,
|
||||
|
||||
@@ -61,17 +61,22 @@
|
||||
|
||||
@media not (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') {
|
||||
& {
|
||||
opacity: 0.4;
|
||||
filter: grayscale(1);
|
||||
opacity: 0.5;
|
||||
transition:
|
||||
opacity 0.2s,
|
||||
filter 0.2s;
|
||||
filter 0.2s,
|
||||
opacity 0.2s;
|
||||
}
|
||||
|
||||
&[active='true'] {
|
||||
filter: none;
|
||||
&[active='true'],
|
||||
&:hover {
|
||||
filter: grayscale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--zen-toolbar-element-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,14 +145,6 @@
|
||||
|
||||
& #zen-workspaces-button .zen-workspace-sidebar-icon {
|
||||
margin-inline-end: 5px;
|
||||
|
||||
& [no-icon='true'] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
& #zen-workspaces-button .zen-workspace-sidebar-icon[no-icon='true'] + .zen-workspace-sidebar-name {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
& #zen-workspaces-button {
|
||||
@@ -430,8 +427,8 @@
|
||||
min-height: 1px !important;
|
||||
padding: 3px;
|
||||
border-radius: 4px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
#PanelUI-zen-workspaces-create-footer,
|
||||
@@ -453,44 +450,60 @@
|
||||
}
|
||||
|
||||
/* Mark workspaces indicator */
|
||||
#zen-current-workspace-indicator {
|
||||
#zen-current-workspace-indicator-container {
|
||||
margin-bottom: var(--zen-workspace-indicator-height);
|
||||
}
|
||||
|
||||
.zen-current-workspace-indicator {
|
||||
padding: 15px calc(4px + var(--tab-inline-padding));
|
||||
font-weight: 600;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
position: absolute;
|
||||
max-height: var(--zen-workspace-indicator-height);
|
||||
min-height: var(--zen-workspace-indicator-height);
|
||||
gap: 12px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex-direction: row !important;
|
||||
|
||||
& #zen-current-workspace-indicator-icon {
|
||||
font-size: 14px;
|
||||
&::before {
|
||||
border-radius: var(--border-radius-medium);
|
||||
background: transparent;
|
||||
transition: background 0.1s;
|
||||
pointer-events: none;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 2px;
|
||||
z-index: -1;
|
||||
width: calc(100% - 4px);
|
||||
height: calc(100% - 10px);
|
||||
}
|
||||
|
||||
#zen-current-workspace-indicator-name {
|
||||
&:hover,
|
||||
&[open='true'] {
|
||||
&::before {
|
||||
background: var(--tab-hover-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
& .zen-current-workspace-indicator-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.zen-current-workspace-indicator-name {
|
||||
font-size: 13px;
|
||||
opacity: 0.5;
|
||||
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
|
||||
position: absolute;
|
||||
max-width: calc(100% - var(--zen-toolbox-padding) * 4);
|
||||
}
|
||||
|
||||
& #zen-current-workspace-indicator-icon {
|
||||
min-height: 16px;
|
||||
}
|
||||
|
||||
& #zen-current-workspace-indicator-icon:not([hidden]) + #zen-current-workspace-indicator-name {
|
||||
padding-left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@media not (-moz-bool-pref: 'zen.workspaces.show-workspace-indicator') {
|
||||
#zen-current-workspace-indicator {
|
||||
#zen-current-workspace-indicator-container {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
#zen-current-workspace-indicator[hidden='true'] {
|
||||
#zen-current-workspace-indicator-container[hidden='true'] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,22 @@ var gZenCommonActions = {
|
||||
transferable.addDataFlavor('text/plain');
|
||||
transferable.setTransferData('text/plain', str);
|
||||
Services.clipboard.setData(transferable, null, Ci.nsIClipboard.kGlobalClipboard);
|
||||
ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-copy-current-url-confirmation');
|
||||
gZenUIManager.showToast('zen-copy-current-url-confirmation');
|
||||
}
|
||||
},
|
||||
copyCurrentURLAsMarkdownToClipboard() {
|
||||
const currentUrl = gBrowser.currentURI.spec;
|
||||
const tabTitle = gBrowser.selectedTab.label;
|
||||
if (currentUrl && tabTitle) {
|
||||
const markdownLink = `[${tabTitle}](${currentUrl})`;
|
||||
let str = Cc['@mozilla.org/supports-string;1'].createInstance(Ci.nsISupportsString);
|
||||
str.data = markdownLink;
|
||||
let transferable = Cc['@mozilla.org/widget/transferable;1'].createInstance(Ci.nsITransferable);
|
||||
transferable.init(getLoadContext());
|
||||
transferable.addDataFlavor('text/plain');
|
||||
transferable.setTransferData('text/plain', str);
|
||||
Services.clipboard.setData(transferable, null, Ci.nsIClipboard.kGlobalClipboard);
|
||||
gZenUIManager.showToast('zen-copy-current-url-confirmation');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -41,9 +41,15 @@ var gZenCompactModeManager = {
|
||||
|
||||
get preference() {
|
||||
if (!document.documentElement.hasAttribute('zen-compact-mode')) {
|
||||
document.documentElement.setAttribute(
|
||||
'zen-compact-mode',
|
||||
lazyCompactMode.mainAppWrapper.getAttribute('zen-compact-mode')
|
||||
window.addEventListener(
|
||||
'MozAfterPaint',
|
||||
() => {
|
||||
document.documentElement.setAttribute(
|
||||
'zen-compact-mode',
|
||||
lazyCompactMode.mainAppWrapper.getAttribute('zen-compact-mode')
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
return lazyCompactMode.mainAppWrapper.getAttribute('zen-compact-mode') === 'true';
|
||||
@@ -100,8 +106,6 @@ var gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
updateCompactModeContext(isSingleToolbar) {
|
||||
this.getAndApplySidebarWidth(); // Ignore return value
|
||||
|
||||
const IDs = [
|
||||
'zen-context-menu-compact-mode-hide-sidebar',
|
||||
'zen-context-menu-compact-mode-hide-toolbar',
|
||||
@@ -140,6 +144,7 @@ var gZenCompactModeManager = {
|
||||
getAndApplySidebarWidth() {
|
||||
let sidebarWidth = this.sidebar.getBoundingClientRect().width;
|
||||
if (sidebarWidth > 1) {
|
||||
gZenUIManager.restoreScrollbarState();
|
||||
this.sidebar.style.setProperty('--zen-sidebar-width', `${sidebarWidth}px`);
|
||||
}
|
||||
return sidebarWidth;
|
||||
@@ -157,6 +162,9 @@ var gZenCompactModeManager = {
|
||||
if (canAnimate) {
|
||||
this.sidebar.setAttribute('animate', 'true');
|
||||
}
|
||||
this.sidebar.style.removeProperty('margin-right');
|
||||
this.sidebar.style.removeProperty('margin-left');
|
||||
this.sidebar.style.removeProperty('transform');
|
||||
window.requestAnimationFrame(() => {
|
||||
let sidebarWidth = this.getAndApplySidebarWidth();
|
||||
if (!canAnimate) {
|
||||
@@ -176,24 +184,23 @@ var gZenCompactModeManager = {
|
||||
{
|
||||
ease: 'easeIn',
|
||||
type: 'spring',
|
||||
stiffness: 3000,
|
||||
damping: 150,
|
||||
mass: 1,
|
||||
bounce: 0,
|
||||
duration: 0.2,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.sidebar.removeAttribute('animate');
|
||||
this.sidebar.style.transition = 'none';
|
||||
this.sidebar.style.removeProperty('margin-right');
|
||||
this.sidebar.style.removeProperty('margin-left');
|
||||
this.sidebar.style.removeProperty('transform');
|
||||
this._animating = false;
|
||||
this.sidebar.style.transition = 'none';
|
||||
setTimeout(() => {
|
||||
this._animating = false;
|
||||
this.sidebar.style.removeProperty('transition');
|
||||
});
|
||||
});
|
||||
} else if (canHideSidebar && !isCompactMode) {
|
||||
document.getElementById('browser').style.overflow = 'hidden';
|
||||
document.getElementById('browser').style.overflow = 'clip';
|
||||
if (this.sidebarIsOnRight) {
|
||||
this.sidebar.style.marginRight = `-${sidebarWidth}px`;
|
||||
} else {
|
||||
@@ -204,16 +211,15 @@ var gZenCompactModeManager = {
|
||||
this.sidebar,
|
||||
this.sidebarIsOnRight
|
||||
? {
|
||||
marginRight: 0,
|
||||
marginRight: [`-${sidebarWidth}px`, 0],
|
||||
transform: ['translateX(100%)', 'translateX(0)'],
|
||||
}
|
||||
: { marginLeft: 0 },
|
||||
{
|
||||
ease: 'easeOut',
|
||||
type: 'spring',
|
||||
stiffness: 3000,
|
||||
damping: 150,
|
||||
mass: 1,
|
||||
bounce: 0,
|
||||
duration: 0.2,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
@@ -286,6 +292,9 @@ var gZenCompactModeManager = {
|
||||
element: document.getElementById('zen-appcontent-navbar-container'),
|
||||
screenEdge: 'top',
|
||||
},
|
||||
{
|
||||
element: gZenVerticalTabsManager.actualWindowButtons,
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
@@ -330,9 +339,15 @@ var gZenCompactModeManager = {
|
||||
target.addEventListener('mouseleave', (event) => {
|
||||
// If on Mac, ignore mouseleave in the area of window buttons
|
||||
if (AppConstants.platform == 'macosx') {
|
||||
const MAC_WINDOW_BUTTONS_X_BORDER = 75;
|
||||
const MAC_WINDOW_BUTTONS_Y_BORDER = 40;
|
||||
if (event.clientX < MAC_WINDOW_BUTTONS_X_BORDER && event.clientY < MAC_WINDOW_BUTTONS_Y_BORDER) {
|
||||
const buttonRect = gZenVerticalTabsManager.actualWindowButtons.getBoundingClientRect();
|
||||
const MAC_WINDOW_BUTTONS_X_BORDER = buttonRect.width + buttonRect.x;
|
||||
const MAC_WINDOW_BUTTONS_Y_BORDER = buttonRect.height + buttonRect.y;
|
||||
if (
|
||||
event.clientX < MAC_WINDOW_BUTTONS_X_BORDER &&
|
||||
event.clientY < MAC_WINDOW_BUTTONS_Y_BORDER &&
|
||||
event.clientX > buttonRect.x &&
|
||||
event.clientY > buttonRect.y
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -342,7 +357,7 @@ var gZenCompactModeManager = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hoverableElements[i].keepHoverDuration) {
|
||||
if (this.hoverableElements[i].keepHoverDuration && !event.target.querySelector('#urlbar[zen-floating-urlbar]')) {
|
||||
this.flashElement(target, this.hoverableElements[i].keepHoverDuration, 'has-hover' + target.id, 'zen-has-hover');
|
||||
} else {
|
||||
this._removeHoverFrames[target.id] = window.requestAnimationFrame(() => target.removeAttribute('zen-has-hover'));
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,14 +1,15 @@
|
||||
{
|
||||
class ZenGlanceManager extends ZenDOMOperatedFeature {
|
||||
#currentBrowser = null;
|
||||
#currentTab = null;
|
||||
|
||||
_animating = false;
|
||||
_lazyPref = {};
|
||||
|
||||
#glances = new Map();
|
||||
#currentGlanceID = null;
|
||||
|
||||
init() {
|
||||
window.addEventListener('keydown', this.onKeyDown.bind(this));
|
||||
window.addEventListener('TabClose', this.onTabClose.bind(this));
|
||||
window.addEventListener('TabSelect', this.onLocationChange.bind(this));
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this._lazyPref,
|
||||
@@ -24,17 +25,29 @@
|
||||
Services.obs.addObserver(this, 'quit-application-requested');
|
||||
}
|
||||
|
||||
get #currentBrowser() {
|
||||
return this.#glances.get(this.#currentGlanceID)?.browser;
|
||||
}
|
||||
|
||||
get #currentTab() {
|
||||
return this.#glances.get(this.#currentGlanceID)?.tab;
|
||||
}
|
||||
|
||||
get #currentParentTab() {
|
||||
return this.#glances.get(this.#currentGlanceID)?.parentTab;
|
||||
}
|
||||
|
||||
onKeyDown(event) {
|
||||
if (event.key === 'Escape' && this.#currentBrowser) {
|
||||
if (event.key === 'Escape' && this.#currentGlanceID) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.closeGlance();
|
||||
this.closeGlance({ onTabClose: true });
|
||||
}
|
||||
}
|
||||
|
||||
onOverlayClick(event) {
|
||||
if (event.target === this.overlay && event.originalTarget !== this.contentWrapper) {
|
||||
this.closeGlance();
|
||||
this.closeGlance({ onTabClose: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,13 +61,13 @@
|
||||
|
||||
onUnload() {
|
||||
// clear everything
|
||||
if (this.#currentBrowser) {
|
||||
gBrowser.removeTab(this.#currentTab);
|
||||
for (let [id, glance] of this.#glances) {
|
||||
gBrowser.removeTab(glance.tab, { animate: false });
|
||||
}
|
||||
}
|
||||
|
||||
getTabPosition(tab) {
|
||||
return Math.max(gBrowser._numVisiblePinTabs, tab._tPos) + 1;
|
||||
return Math.max(gBrowser._numVisiblePinTabs, tab._tPos);
|
||||
}
|
||||
|
||||
createBrowserElement(url, currentTab, existingTab = null) {
|
||||
@@ -65,21 +78,57 @@
|
||||
skipLoad: false,
|
||||
index: this.getTabPosition(currentTab),
|
||||
};
|
||||
this.currentParentTab = currentTab;
|
||||
currentTab._selected = true;
|
||||
const newUUID = gZenUIManager.generateUuidv4();
|
||||
const newTab = existingTab ?? gBrowser.addTrustedTab(Services.io.newURI(url).spec, newTabOptions);
|
||||
|
||||
gBrowser.selectedTab = newTab;
|
||||
if (currentTab.hasAttribute('zenDefaultUserContextId')) {
|
||||
newTab.setAttribute('zenDefaultUserContextId', true);
|
||||
}
|
||||
currentTab.querySelector('.tab-content').appendChild(newTab);
|
||||
newTab.setAttribute('zen-glance-tab', true);
|
||||
this.#currentBrowser = newTab.linkedBrowser;
|
||||
this.#currentTab = newTab;
|
||||
newTab.setAttribute('glance-id', newUUID);
|
||||
currentTab.setAttribute('glance-id', newUUID);
|
||||
this.#glances.set(newUUID, {
|
||||
tab: newTab,
|
||||
parentTab: currentTab,
|
||||
browser: newTab.linkedBrowser,
|
||||
});
|
||||
this.#currentGlanceID = newUUID;
|
||||
gBrowser.selectedTab = newTab;
|
||||
return this.#currentBrowser;
|
||||
}
|
||||
|
||||
fillOverlay(browser) {
|
||||
this.overlay = browser.closest('.browserSidebarContainer');
|
||||
this.browserWrapper = browser.closest('.browserContainer');
|
||||
this.contentWrapper = browser.closest('.browserStack');
|
||||
}
|
||||
|
||||
showSidebarButtons(animate = false) {
|
||||
if (this.sidebarButtons.hasAttribute('hidden') && animate) {
|
||||
gZenUIManager.motion.animate(
|
||||
this.sidebarButtons.querySelectorAll('toolbarbutton'),
|
||||
{ x: [50, 0], opacity: [0, 1] },
|
||||
{ delay: gZenUIManager.motion.stagger(0.1) }
|
||||
);
|
||||
}
|
||||
this.sidebarButtons.removeAttribute('hidden');
|
||||
}
|
||||
|
||||
hideSidebarButtons() {
|
||||
this.sidebarButtons.setAttribute('hidden', true);
|
||||
}
|
||||
|
||||
openGlance(data, existingTab = null, ownerTab = null) {
|
||||
if (this.#currentBrowser) {
|
||||
return;
|
||||
}
|
||||
if (gBrowser.selectedTab === this.#currentParentTab) {
|
||||
gBrowser.selectedTab = this.#currentTab;
|
||||
return;
|
||||
}
|
||||
this.animatingOpen = true;
|
||||
this._animating = true;
|
||||
|
||||
const initialX = data.x;
|
||||
const initialY = data.y;
|
||||
@@ -89,36 +138,52 @@
|
||||
this.browserWrapper?.removeAttribute('animate');
|
||||
this.browserWrapper?.removeAttribute('animate-end');
|
||||
this.browserWrapper?.removeAttribute('animate-full');
|
||||
this.browserWrapper?.removeAttribute('animate-full-end');
|
||||
this.browserWrapper?.removeAttribute('has-finished-animation');
|
||||
this.overlay?.removeAttribute('post-fade-out');
|
||||
|
||||
const currentTab = ownerTab ?? gBrowser.selectedTab;
|
||||
|
||||
this.animatingOpen = true;
|
||||
this._animating = true;
|
||||
|
||||
const browserElement = this.createBrowserElement(data.url, currentTab, existingTab);
|
||||
|
||||
this.overlay = browserElement.closest('.browserSidebarContainer');
|
||||
this.browserWrapper = browserElement.closest('.browserContainer');
|
||||
this.contentWrapper = browserElement.closest('.browserStack');
|
||||
|
||||
this.browserWrapper.prepend(this.sidebarButtons);
|
||||
this.fillOverlay(browserElement);
|
||||
|
||||
this.overlay.classList.add('zen-glance-overlay');
|
||||
|
||||
this.browserWrapper.removeAttribute('animate-end');
|
||||
window.requestAnimationFrame(() => {
|
||||
this.quickOpenGlance();
|
||||
this.quickOpenGlance({ dontOpenButtons: true });
|
||||
this.showSidebarButtons(true);
|
||||
|
||||
gZenUIManager.motion.animate(
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer'),
|
||||
{
|
||||
scale: [1, 0.98],
|
||||
backdropFilter: ['blur(0px)', 'blur(5px)'],
|
||||
opacity: [1, 0.5],
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
}
|
||||
);
|
||||
this.#currentBrowser.setAttribute('animate-glance-open', true);
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.setAttribute('animate', true);
|
||||
this.browserWrapper.style.top = `${initialY + initialHeight / 2}px`;
|
||||
this.browserWrapper.style.left = `${initialX + initialWidth / 2}px`;
|
||||
const top = initialY + initialHeight / 2;
|
||||
const left = initialX + initialWidth / 2;
|
||||
this.browserWrapper.style.top = `${top}px`;
|
||||
this.browserWrapper.style.left = `${left}px`;
|
||||
this.browserWrapper.style.width = `${initialWidth}px`;
|
||||
this.browserWrapper.style.height = `${initialHeight}px`;
|
||||
this.browserWrapper.style.opacity = 0.8;
|
||||
this.#glances.get(this.#currentGlanceID).originalPosition = {
|
||||
top: this.browserWrapper.style.top,
|
||||
left: this.browserWrapper.style.left,
|
||||
width: this.browserWrapper.style.width,
|
||||
height: this.browserWrapper.style.height,
|
||||
};
|
||||
this.browserWrapper.style.transform = 'translate(-50%, -50%)';
|
||||
this.overlay.style.overflow = 'visible';
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
@@ -131,12 +196,13 @@
|
||||
opacity: 1,
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
duration: 0.3,
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.#currentBrowser.removeAttribute('animate-glance-open');
|
||||
this.overlay.style.removeProperty('overflow');
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
this.browserWrapper.setAttribute('animate-end', true);
|
||||
@@ -147,166 +213,236 @@
|
||||
});
|
||||
}
|
||||
|
||||
closeGlance({ noAnimation = false, onTabClose = false } = {}) {
|
||||
closeGlance({ noAnimation = false, onTabClose = false, setNewID = null, isDifferent = false } = {}) {
|
||||
if (this._animating || !this.#currentBrowser || this.animatingOpen || this._duringOpening) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.browserWrapper.removeAttribute('has-finished-animation');
|
||||
if (noAnimation) {
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').removeAttribute('style');
|
||||
this.quickCloseGlance({ closeCurrentTab: false });
|
||||
this.#currentBrowser = null;
|
||||
this.#currentTab = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.closingGlance = true;
|
||||
this._animating = true;
|
||||
|
||||
gBrowser._insertTabAtIndex(this.#currentTab, {
|
||||
index: this.getTabPosition(this.currentParentTab),
|
||||
index: this.getTabPosition(this.#currentParentTab),
|
||||
});
|
||||
|
||||
let quikcCloseZen = false;
|
||||
if (onTabClose) {
|
||||
// Create new tab if no more ex
|
||||
if (gBrowser.tabs.length === 1) {
|
||||
gBrowser.selectedTab = gZenUIManager.openAndChangeToTab(Services.prefs.getStringPref('browser.startup.homepage'));
|
||||
BrowserCommands.openTab();
|
||||
return;
|
||||
} else if (gBrowser.selectedTab === this.#currentTab) {
|
||||
this._duringOpening = true;
|
||||
gBrowser.tabContainer.advanceSelectedTab(1, true); // to skip the current tab
|
||||
this._duringOpening = false;
|
||||
quikcCloseZen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// do NOT touch here, I don't know what it does, but it works...
|
||||
window.requestAnimationFrame(() => {
|
||||
this.#currentTab.style.display = 'none';
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
this.browserWrapper.removeAttribute('animate-end');
|
||||
this.overlay.setAttribute('fade-out', true);
|
||||
window.requestAnimationFrame(() => {
|
||||
this.quickCloseGlance({ justAnimateParent: true });
|
||||
this.browserWrapper.setAttribute('animate', true);
|
||||
setTimeout(() => {
|
||||
if (!this.currentParentTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!onTabClose || quikcCloseZen) {
|
||||
this.quickCloseGlance();
|
||||
}
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
|
||||
this.lastCurrentTab = this.#currentTab;
|
||||
|
||||
this.overlay.classList.remove('zen-glance-overlay');
|
||||
gBrowser._getSwitcher().setTabStateNoAction(this.lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED);
|
||||
|
||||
if (!onTabClose && gBrowser.selectedTab === this.lastCurrentTab) {
|
||||
this._duringOpening = true;
|
||||
gBrowser.selectedTab = this.currentParentTab;
|
||||
}
|
||||
|
||||
// reset everything
|
||||
this.currentParentTab = null;
|
||||
this.browserWrapper = null;
|
||||
this.overlay = null;
|
||||
this.contentWrapper = null;
|
||||
|
||||
this.lastCurrentTab.removeAttribute('zen-glance-tab');
|
||||
this.lastCurrentTab._closingGlance = true;
|
||||
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
gBrowser.removeTab(this.lastCurrentTab, { animate: true });
|
||||
|
||||
this.#currentTab = null;
|
||||
this.#currentBrowser = null;
|
||||
|
||||
this.lastCurrentTab = null;
|
||||
this._duringOpening = false;
|
||||
|
||||
this._animating = false;
|
||||
}, 400);
|
||||
this.#currentTab.style.display = 'none';
|
||||
this.overlay.setAttribute('fade-out', true);
|
||||
this.overlay.style.pointerEvents = 'none';
|
||||
this.quickCloseGlance({ justAnimateParent: true, clearID: false });
|
||||
const originalPosition = this.#glances.get(this.#currentGlanceID).originalPosition;
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer'),
|
||||
{
|
||||
scale: [0.98, 1],
|
||||
backdropFilter: ['blur(5px)', 'blur(0px)'],
|
||||
opacity: [0.5, 1],
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').removeAttribute('style');
|
||||
});
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.browserWrapper,
|
||||
{
|
||||
...originalPosition,
|
||||
opacity: 0.3,
|
||||
},
|
||||
{ type: 'spring', bounce: 0, duration: 0.4, easing: 'ease' }
|
||||
)
|
||||
.then(() => {
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
this.browserWrapper.removeAttribute('animate-end');
|
||||
if (!this.#currentParentTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!onTabClose || quikcCloseZen) {
|
||||
this.quickCloseGlance({ clearID: false });
|
||||
}
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
|
||||
this.lastCurrentTab = this.#currentTab;
|
||||
|
||||
this.overlay.classList.remove('zen-glance-overlay');
|
||||
gBrowser._getSwitcher().setTabStateNoAction(this.lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED);
|
||||
|
||||
if (!onTabClose) {
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
}
|
||||
|
||||
// reset everything
|
||||
const prevOverlay = this.overlay;
|
||||
this.browserWrapper = null;
|
||||
this.overlay = null;
|
||||
this.contentWrapper = null;
|
||||
|
||||
this.lastCurrentTab.removeAttribute('zen-glance-tab');
|
||||
this.lastCurrentTab._closingGlance = true;
|
||||
|
||||
if (!isDifferent) {
|
||||
gBrowser.selectedTab = this.#currentParentTab;
|
||||
}
|
||||
this._ignoreClose = true;
|
||||
gBrowser.removeTab(this.lastCurrentTab, { animate: true });
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
|
||||
this.#currentParentTab.removeAttribute('glance-id');
|
||||
|
||||
this.#glances.delete(this.#currentGlanceID);
|
||||
this.#currentGlanceID = setNewID;
|
||||
|
||||
this.lastCurrentTab = null;
|
||||
this._duringOpening = false;
|
||||
|
||||
this._animating = false;
|
||||
this.closingGlance = false;
|
||||
|
||||
if (this.#currentGlanceID) {
|
||||
this.quickOpenGlance();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
quickOpenGlance() {
|
||||
quickOpenGlance({ dontOpenButtons = false } = {}) {
|
||||
if (!this.#currentBrowser || this._duringOpening) {
|
||||
return;
|
||||
}
|
||||
this._duringOpening = true;
|
||||
try {
|
||||
gBrowser.selectedTab = this.#currentTab;
|
||||
} catch (e) {}
|
||||
if (!dontOpenButtons) {
|
||||
this.showSidebarButtons();
|
||||
}
|
||||
|
||||
this.currentParentTab.linkedBrowser
|
||||
.closest('.browserSidebarContainer')
|
||||
.classList.add('deck-selected', 'zen-glance-background');
|
||||
this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-overlay');
|
||||
this.currentParentTab.linkedBrowser.zenModeActive = true;
|
||||
const parentBrowserContainer = this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer');
|
||||
parentBrowserContainer.classList.add('zen-glance-background');
|
||||
parentBrowserContainer.classList.remove('zen-glance-overlay');
|
||||
parentBrowserContainer.classList.add('deck-selected');
|
||||
this.#currentParentTab.linkedBrowser.zenModeActive = true;
|
||||
this.#currentParentTab.linkedBrowser.docShellIsActive = true;
|
||||
this.#currentBrowser.zenModeActive = true;
|
||||
this.currentParentTab.linkedBrowser.docShellIsActive = true;
|
||||
this.#currentBrowser.docShellIsActive = true;
|
||||
this.#currentBrowser.setAttribute('zen-glance-selected', true);
|
||||
this.fillOverlay(this.#currentBrowser);
|
||||
this.#currentParentTab._visuallySelected = true;
|
||||
|
||||
this.currentParentTab._visuallySelected = true;
|
||||
this.overlay.classList.add('deck-selected');
|
||||
this.overlay.classList.add('zen-glance-overlay');
|
||||
|
||||
this._duringOpening = false;
|
||||
}
|
||||
|
||||
quickCloseGlance({ closeCurrentTab = true, closeParentTab = true, justAnimateParent = false } = {}) {
|
||||
const parentHasBrowser = !!this.currentParentTab.linkedBrowser;
|
||||
if (!justAnimateParent) {
|
||||
quickCloseGlance({ closeCurrentTab = true, closeParentTab = true, justAnimateParent = false, clearID = true } = {}) {
|
||||
const parentHasBrowser = !!this.#currentParentTab.linkedBrowser;
|
||||
this.hideSidebarButtons();
|
||||
if (parentHasBrowser) {
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
|
||||
}
|
||||
if (!justAnimateParent && this.overlay) {
|
||||
if (parentHasBrowser) {
|
||||
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;
|
||||
}
|
||||
this.#currentBrowser.zenModeActive = false;
|
||||
if (closeParentTab && parentHasBrowser) {
|
||||
this.currentParentTab.linkedBrowser.docShellIsActive = false;
|
||||
this.#currentParentTab.linkedBrowser.docShellIsActive = false;
|
||||
}
|
||||
if (closeCurrentTab) {
|
||||
this.#currentBrowser.docShellIsActive = false;
|
||||
this.overlay.classList.remove('deck-selected');
|
||||
this.#currentTab._selected = false;
|
||||
}
|
||||
if (!this.currentParentTab._visuallySelected && closeParentTab) {
|
||||
this.currentParentTab._visuallySelected = false;
|
||||
if (!this.#currentParentTab._visuallySelected && closeParentTab) {
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
}
|
||||
this.#currentBrowser.removeAttribute('zen-glance-selected');
|
||||
this.overlay.classList.remove('zen-glance-overlay');
|
||||
}
|
||||
if (parentHasBrowser) {
|
||||
this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
|
||||
if (clearID) {
|
||||
this.#currentGlanceID = null;
|
||||
}
|
||||
}
|
||||
|
||||
onLocationChange(_) {
|
||||
if (this._duringOpening) {
|
||||
onLocationChangeOpenGlance() {
|
||||
if (!this.animatingOpen) {
|
||||
this.quickOpenGlance();
|
||||
}
|
||||
}
|
||||
|
||||
// note: must be async to avoid timing issues
|
||||
onLocationChange(event) {
|
||||
const tab = event.target;
|
||||
if (this.animatingFullOpen || this.closingGlance) {
|
||||
return;
|
||||
}
|
||||
if (gBrowser.selectedTab === this.#currentTab && !this.animatingOpen && !this._duringOpening && this.#currentBrowser) {
|
||||
this.quickOpenGlance();
|
||||
if (this._duringOpening || !tab.hasAttribute('glance-id')) {
|
||||
if (this.#currentGlanceID && !this._duringOpening) {
|
||||
this.quickCloseGlance();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (gBrowser.selectedTab === this.currentParentTab && this.#currentBrowser) {
|
||||
this.quickOpenGlance();
|
||||
} else if ((!this.animatingFullOpen || this.animatingOpen) && this.#currentBrowser) {
|
||||
this.closeGlance();
|
||||
if (this.#currentGlanceID && this.#currentGlanceID !== tab.getAttribute('glance-id')) {
|
||||
this.quickCloseGlance();
|
||||
}
|
||||
this.#currentGlanceID = tab.getAttribute('glance-id');
|
||||
if (gBrowser.selectedTab === this.#currentParentTab && this.#currentBrowser) {
|
||||
const curTab = this.#currentTab;
|
||||
setTimeout(() => {
|
||||
gBrowser.selectedTab = curTab;
|
||||
}, 0);
|
||||
} else if (gBrowser.selectedTab === this.#currentTab) {
|
||||
setTimeout(this.onLocationChangeOpenGlance.bind(this), 0);
|
||||
}
|
||||
}
|
||||
|
||||
onTabClose(event) {
|
||||
if (event.target === this.currentParentTab) {
|
||||
if (event.target === this.#currentParentTab) {
|
||||
this.closeGlance({ onTabClose: true });
|
||||
}
|
||||
}
|
||||
|
||||
manageTabClose(tab) {
|
||||
if (tab.hasAttribute('glance-id')) {
|
||||
const oldGlanceID = this.#currentGlanceID;
|
||||
const newGlanceID = tab.getAttribute('glance-id');
|
||||
this.#currentGlanceID = newGlanceID;
|
||||
const isDifferent = newGlanceID !== oldGlanceID;
|
||||
if (this._ignoreClose) {
|
||||
this._ignoreClose = false;
|
||||
return false;
|
||||
}
|
||||
this.closeGlance({ onTabClose: true, setNewID: isDifferent ? oldGlanceID : null, isDifferent });
|
||||
// only keep continueing tab close if we are not on the currently selected tab
|
||||
return !isDifferent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
tabDomainsDiffer(tab1, url2) {
|
||||
try {
|
||||
if (!tab1) {
|
||||
@@ -350,29 +486,41 @@
|
||||
}
|
||||
|
||||
fullyOpenGlance() {
|
||||
this.animatingFullOpen = true;
|
||||
gBrowser._insertTabAtIndex(this.#currentTab, {
|
||||
index: this.getTabPosition(this.#currentTab),
|
||||
});
|
||||
|
||||
this.animatingFullOpen = true;
|
||||
this.currentParentTab._visuallySelected = false;
|
||||
|
||||
this.browserWrapper.removeAttribute('style');
|
||||
this.browserWrapper.removeAttribute('has-finished-animation');
|
||||
this.browserWrapper.setAttribute('animate-full', true);
|
||||
this.#currentTab.removeAttribute('zen-glance-tab');
|
||||
this.#currentTab.removeAttribute('glance-id');
|
||||
this.#currentParentTab.removeAttribute('glance-id');
|
||||
gBrowser.selectedTab = this.#currentTab;
|
||||
this.currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
|
||||
setTimeout(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.browserWrapper.setAttribute('animate-full-end', true);
|
||||
this.#currentParentTab.linkedBrowser.closest('.browserSidebarContainer').classList.remove('zen-glance-background');
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
this.hideSidebarButtons();
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.browserWrapper,
|
||||
{
|
||||
width: ['85%', '100%'],
|
||||
height: ['100%', '100%'],
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: 'spring',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.browserWrapper.removeAttribute('animate-full');
|
||||
this.overlay.classList.remove('zen-glance-overlay');
|
||||
setTimeout(() => {
|
||||
this.animatingFullOpen = false;
|
||||
this.closeGlance({ noAnimation: true });
|
||||
}, 600);
|
||||
this.browserWrapper.removeAttribute('style');
|
||||
this.animatingFullOpen = false;
|
||||
this.closeGlance({ noAnimation: true });
|
||||
this.#glances.delete(this.#currentGlanceID);
|
||||
});
|
||||
}, 300);
|
||||
}
|
||||
|
||||
openGlanceForBookmark(event) {
|
||||
@@ -406,6 +554,10 @@
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
getFocusedTab(aDir) {
|
||||
return aDir < 0 ? this.#currentParentTab : this.#currentTab;
|
||||
}
|
||||
}
|
||||
|
||||
window.gZenGlanceManager = new ZenGlanceManager();
|
||||
@@ -422,6 +574,7 @@
|
||||
DOMContentLoaded: {},
|
||||
},
|
||||
},
|
||||
matches: ['https://*/*'],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
class ZenThemePicker extends ZenMultiWindowFeature {
|
||||
static GRADIENT_IMAGE_URL = 'chrome://browser/content/zen-images/gradient.png';
|
||||
static GRADIENT_DISPLAY_URL = 'chrome://browser/content/zen-images/gradient-display.png';
|
||||
static MAX_DOTS = 5;
|
||||
static MAX_DOTS = 3;
|
||||
|
||||
currentOpacity = 0.5;
|
||||
currentRotation = 45;
|
||||
|
||||
numberOfDots = 0;
|
||||
|
||||
dots = [];
|
||||
useAlgo = '';
|
||||
constructor() {
|
||||
super();
|
||||
if (!Services.prefs.getBoolPref('zen.theme.gradient', true) || !ZenWorkspaces.shouldHaveWorkspaces) {
|
||||
@@ -33,11 +32,9 @@
|
||||
this.onDarkModeChange.bind(this)
|
||||
);
|
||||
|
||||
this.initRotation();
|
||||
this.initCanvas();
|
||||
this.initCustomColorInput();
|
||||
|
||||
ZenWorkspaces.addChangeListeners(this.onWorkspaceChange.bind(this));
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addListener(this.onDarkModeChange.bind(this));
|
||||
}
|
||||
|
||||
@@ -80,7 +77,7 @@
|
||||
|
||||
onImageLoad() {
|
||||
// resize the image to fit the panel
|
||||
const imageSize = 300 - 20; // 20 is the padding (10px)
|
||||
const imageSize = 350 - 20; // 20 is the padding (10px)
|
||||
const scale = imageSize / Math.max(this.image.width, this.image.height);
|
||||
this.image.width *= scale;
|
||||
this.image.height *= scale;
|
||||
@@ -99,80 +96,12 @@
|
||||
this.onDarkModeChange(null);
|
||||
}
|
||||
|
||||
initRotation() {
|
||||
this.rotationInput = document.getElementById('PanelUI-zen-gradient-degrees');
|
||||
this.rotationInputDot = this.rotationInput.querySelector('.dot');
|
||||
this.rotationInputText = this.rotationInput.querySelector('.text');
|
||||
this.rotationInputDot.addEventListener('mousedown', this.onRotationMouseDown.bind(this));
|
||||
this.rotationInput.addEventListener('wheel', this.onRotationWheel.bind(this));
|
||||
}
|
||||
|
||||
onRotationWheel(event) {
|
||||
event.preventDefault();
|
||||
const delta = event.deltaY;
|
||||
const degrees = this.currentRotation + (delta > 0 ? 10 : -10);
|
||||
this.setRotationInput(degrees);
|
||||
this.updateCurrentWorkspace();
|
||||
}
|
||||
|
||||
onRotationMouseDown(event) {
|
||||
event.preventDefault();
|
||||
this.rotationDragging = true;
|
||||
this.rotationInputDot.style.zIndex = 2;
|
||||
this.rotationInputDot.classList.add('dragging');
|
||||
document.addEventListener('mousemove', this.onRotationMouseMove.bind(this));
|
||||
document.addEventListener('mouseup', this.onRotationMouseUp.bind(this));
|
||||
}
|
||||
|
||||
onRotationMouseUp(event) {
|
||||
this.rotationDragging = false;
|
||||
this.rotationInputDot.style.zIndex = 1;
|
||||
this.rotationInputDot.classList.remove('dragging');
|
||||
document.removeEventListener('mousemove', this.onRotationMouseMove.bind(this));
|
||||
document.removeEventListener('mouseup', this.onRotationMouseUp.bind(this));
|
||||
}
|
||||
|
||||
onRotationMouseMove(event) {
|
||||
if (this.rotationDragging) {
|
||||
event.preventDefault();
|
||||
const rect = this.rotationInput.getBoundingClientRect();
|
||||
// Make the dot follow the mouse in a circle, it can't go outside or inside the circle
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
const angle = Math.atan2(event.clientY - centerY, event.clientX - centerX);
|
||||
const distance = Math.sqrt((event.clientX - centerX) ** 2 + (event.clientY - centerY) ** 2);
|
||||
const radius = rect.width / 2;
|
||||
let x = centerX + Math.cos(angle) * radius;
|
||||
let y = centerY + Math.sin(angle) * radius;
|
||||
if (distance > radius) {
|
||||
x = event.clientX;
|
||||
y = event.clientY;
|
||||
}
|
||||
const degrees = Math.round((Math.atan2(y - centerY, x - centerX) * 180) / Math.PI);
|
||||
this.setRotationInput(degrees);
|
||||
this.updateCurrentWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
setRotationInput(degrees) {
|
||||
let fixedRotation = degrees;
|
||||
while (fixedRotation < 0) {
|
||||
fixedRotation += 360;
|
||||
}
|
||||
while (fixedRotation >= 360) {
|
||||
fixedRotation -= 360;
|
||||
}
|
||||
this.currentRotation = degrees;
|
||||
this.rotationInputDot.style.transform = `rotate(${degrees - 20}deg)`;
|
||||
this.rotationInputText.textContent = `${fixedRotation}°`;
|
||||
}
|
||||
|
||||
initCustomColorInput() {
|
||||
this.customColorInput.addEventListener('keydown', this.onCustomColorKeydown.bind(this));
|
||||
}
|
||||
|
||||
onCustomColorKeydown(event) {
|
||||
//checks for enter key for custom colors
|
||||
// Check for Enter key to add custom colors
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
this.addCustomColor();
|
||||
@@ -184,6 +113,7 @@
|
||||
themePicker.style.setProperty('--zen-theme-picker-gradient-image', `url(${ZenThemePicker.GRADIENT_DISPLAY_URL})`);
|
||||
themePicker.addEventListener('mousemove', this.onDotMouseMove.bind(this));
|
||||
themePicker.addEventListener('mouseup', this.onDotMouseUp.bind(this));
|
||||
themePicker.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
||||
themePicker.addEventListener('click', this.onThemePickerClick.bind(this));
|
||||
}
|
||||
|
||||
@@ -234,135 +164,31 @@
|
||||
dot.style.opacity = 0;
|
||||
dot.style.setProperty('--zen-theme-picker-dot-color', color.c);
|
||||
} else {
|
||||
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${r}, ${g}, ${b})`);
|
||||
const { x, y } = this.calculateInitialPosition(color);
|
||||
const dotPad = this.panel.querySelector('.zen-theme-picker-gradient');
|
||||
|
||||
const dot = document.createElement('div');
|
||||
dot.classList.add('zen-theme-picker-dot');
|
||||
|
||||
dot.style.left = `${x * 100}%`;
|
||||
dot.style.top = `${y * 100}%`;
|
||||
dot.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
||||
|
||||
dotPad.appendChild(dot);
|
||||
let id = this.dots.length;
|
||||
|
||||
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${r}, ${g}, ${b})`);
|
||||
|
||||
this.dots.push({
|
||||
ID: id,
|
||||
Element: dot,
|
||||
Position: { x: parseFloat(dot.style.left), y: parseFloat(dot.style.top) },
|
||||
});
|
||||
}
|
||||
if (color.isPrimary) {
|
||||
dot.classList.add('primary');
|
||||
}
|
||||
const lastDot = this.panel.querySelector('.zen-theme-picker-dot:last-child');
|
||||
let newIndex = 0;
|
||||
if (lastDot) {
|
||||
newIndex = parseInt(lastDot.getAttribute('data-index')) + 1;
|
||||
}
|
||||
dot.setAttribute('data-index', newIndex);
|
||||
this.panel.querySelector('.zen-theme-picker-gradient').appendChild(dot);
|
||||
if (!fromWorkspace) {
|
||||
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
|
||||
this.dragStartPosition = {
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
};
|
||||
}
|
||||
|
||||
onDotMouseMove(event) {
|
||||
if (this.dragging) {
|
||||
event.preventDefault();
|
||||
const rect = this.panel.querySelector('.zen-theme-picker-gradient').getBoundingClientRect();
|
||||
const padding = 90; // each side
|
||||
// do NOT let the ball be draged outside of an imaginary circle. You can drag it anywhere inside the circle
|
||||
// if the distance between the center of the circle and the dragged ball is bigger than the radius, then the ball
|
||||
// should be placed on the edge of the circle. If it's inside the circle, then the ball just follows the mouse
|
||||
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
const radius = (rect.width - padding) / 2;
|
||||
let pixelX = event.clientX;
|
||||
let pixelY = event.clientY;
|
||||
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||
if (distance > radius) {
|
||||
const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
|
||||
pixelX = centerX + Math.cos(angle) * radius;
|
||||
pixelY = centerY + Math.sin(angle) * radius;
|
||||
}
|
||||
|
||||
// set the location of the dot in pixels
|
||||
const relativeX = pixelX - rect.left;
|
||||
const relativeY = pixelY - rect.top;
|
||||
this.draggedDot.style.left = `${relativeX}px`;
|
||||
this.draggedDot.style.top = `${relativeY}px`;
|
||||
const color = this.getColorFromPosition(relativeX, relativeY);
|
||||
this.draggedDot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${color[0]}, ${color[1]}, ${color[2]})`);
|
||||
this.updateOtherColorsAndUpdateTheme(color);
|
||||
}
|
||||
}
|
||||
|
||||
updateOtherColorsAndUpdateTheme(primaryColor) {
|
||||
// Convert the other colors into the correct color by using color theory
|
||||
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
|
||||
const primaryColorRGB = primaryColor;
|
||||
const primaryColorDot = this.draggedDot;
|
||||
const primaryColorIndex = parseInt(primaryColorDot.getAttribute('data-index'));
|
||||
|
||||
for (const dot of dots) {
|
||||
if (dot.classList.contains('primary') || dot.classList.contains('custom')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const index = parseInt(dot.getAttribute('data-index'));
|
||||
if (index === primaryColorIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const [r, g, b] = this.getColorFromPosition(parseInt(dot.style.left), parseInt(dot.style.top));
|
||||
const color = [r, g, b];
|
||||
|
||||
// modify the color based on the index and color theory
|
||||
const modifiedColor = this.modifyColor(primaryColorRGB, color, index - primaryColorIndex);
|
||||
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${modifiedColor[0]}, ${modifiedColor[1]}, ${modifiedColor[2]})`);
|
||||
|
||||
// update y and x
|
||||
const rect = this.panel.querySelector('.zen-theme-picker-gradient').getBoundingClientRect();
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
const radius = (rect.width - 90) / 2;
|
||||
const angle = Math.atan2(modifiedColor[1] - primaryColorRGB[1], modifiedColor[0] - primaryColorRGB[0]);
|
||||
const distance = Math.sqrt((modifiedColor[0] - primaryColorRGB[0]) ** 2 + (modifiedColor[1] - primaryColorRGB[1]) ** 2);
|
||||
let x = centerX + Math.cos(angle) * radius;
|
||||
let y = centerY + Math.sin(angle) * radius;
|
||||
if (distance > radius) {
|
||||
x = primaryColorDot.style.left;
|
||||
y = primaryColorDot.style.top;
|
||||
}
|
||||
dot.style.left = x + 'px';
|
||||
dot.style.top = y + 'px';
|
||||
}
|
||||
this.updateCurrentWorkspace();
|
||||
}
|
||||
|
||||
modifyColor(primaryColor, color, index) {
|
||||
// index may be negative
|
||||
if (index < 0) {
|
||||
index = -(1 / index);
|
||||
}
|
||||
const [r, g, b] = primaryColor;
|
||||
const [r2, g2, b2] = color;
|
||||
const factor = 0.5;
|
||||
const modifiedColor = [
|
||||
Math.floor(Math.min(255, r + (r2 - r) * factor * index)),
|
||||
Math.floor(Math.min(255, g + (g2 - g) * factor * index)),
|
||||
Math.floor(Math.min(255, b + (b2 - b) * factor * index)),
|
||||
];
|
||||
return modifiedColor;
|
||||
}
|
||||
|
||||
addColorToCustomList(color) {
|
||||
const listItems = window.MozXULElement.parseXULToFragment(`
|
||||
<hbox class="zen-theme-picker-custom-list-item">
|
||||
@@ -400,14 +226,240 @@
|
||||
await this.updateCurrentWorkspace();
|
||||
}
|
||||
|
||||
spawnDot(relativePosition, primary = false) {
|
||||
const dotPad = this.panel.querySelector('.zen-theme-picker-gradient');
|
||||
|
||||
const dot = document.createElement('div');
|
||||
dot.classList.add('zen-theme-picker-dot');
|
||||
|
||||
dot.style.left = `${relativePosition.x}px`;
|
||||
dot.style.top = `${relativePosition.y}px`;
|
||||
|
||||
dotPad.appendChild(dot);
|
||||
|
||||
let id = this.dots.length;
|
||||
|
||||
if (primary === true) {
|
||||
id = 0;
|
||||
|
||||
const existingPrimaryDot = this.dots.find((d) => d.ID === 0);
|
||||
if (existingPrimaryDot) {
|
||||
existingPrimaryDot.ID = this.dots.length;
|
||||
}
|
||||
}
|
||||
|
||||
const colorFromPos = this.getColorFromPosition(relativePosition.x, relativePosition.y);
|
||||
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})`);
|
||||
|
||||
this.dots.push({
|
||||
ID: id,
|
||||
Element: dot,
|
||||
Position: { x: parseFloat(dot.style.left), y: parseFloat(dot.style.top) },
|
||||
});
|
||||
}
|
||||
|
||||
calculateCompliments(dots, action = 'update', useHarmony = '') {
|
||||
const colorHarmonies = [
|
||||
{ type: 'complementary', angles: [180] },
|
||||
{ type: 'splitComplementary', angles: [150, 210] },
|
||||
{ type: 'analogous', angles: [30, 330] },
|
||||
{ type: 'triadic', angles: [120, 240] },
|
||||
{ type: 'floating', angles: [] },
|
||||
];
|
||||
|
||||
function getColorHarmonyType(numDots) {
|
||||
if (useHarmony !== '') {
|
||||
const selectedHarmony = colorHarmonies.find((harmony) => harmony.type === useHarmony);
|
||||
if (selectedHarmony) {
|
||||
if (action === 'remove') {
|
||||
return colorHarmonies.find((harmony) => harmony.angles.length === selectedHarmony.angles.length - 1);
|
||||
}
|
||||
if (action === 'add') {
|
||||
return colorHarmonies.find((harmony) => harmony.angles.length === selectedHarmony.angles.length + 1);
|
||||
}
|
||||
if (action === 'update') {
|
||||
return selectedHarmony;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action === 'remove') {
|
||||
return colorHarmonies.find((harmony) => harmony.angles.length === numDots);
|
||||
}
|
||||
if (action === 'add') {
|
||||
return colorHarmonies.find((harmony) => harmony.angles.length + 1 === numDots);
|
||||
}
|
||||
if (action === 'update') {
|
||||
return colorHarmonies.find((harmony) => harmony.angles.length + 1 === numDots);
|
||||
}
|
||||
}
|
||||
|
||||
function getAngleFromPosition(position, centerPosition) {
|
||||
let deltaX = position.x - centerPosition.x;
|
||||
let deltaY = position.y - centerPosition.y;
|
||||
let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
|
||||
return (angle + 360) % 360;
|
||||
}
|
||||
|
||||
function getDistanceFromCenter(position, centerPosition) {
|
||||
const deltaX = position.x - centerPosition.x;
|
||||
const deltaY = position.y - centerPosition.y;
|
||||
return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
}
|
||||
|
||||
const dotPad = this.panel.querySelector('.zen-theme-picker-gradient');
|
||||
const rect = dotPad.getBoundingClientRect();
|
||||
const padding = 90;
|
||||
|
||||
let updatedDots = [...dots];
|
||||
const centerPosition = { x: rect.width / 2, y: rect.height / 2 };
|
||||
|
||||
const harmonyAngles = getColorHarmonyType(dots.length + (action === 'add' ? 1 : action === 'remove' ? -1 : 0));
|
||||
this.useAlgo = harmonyAngles.type;
|
||||
|
||||
if (!harmonyAngles || harmonyAngles.angles.length === 0) return [];
|
||||
|
||||
let primaryDot = dots.find((dot) => dot.ID === 0);
|
||||
if (!primaryDot) return [];
|
||||
|
||||
if (action === 'add' && this.dots.length) {
|
||||
updatedDots.push({ ID: this.dots.length, Position: centerPosition });
|
||||
}
|
||||
const baseAngle = getAngleFromPosition(primaryDot.Position, centerPosition);
|
||||
let distance = getDistanceFromCenter(primaryDot.Position, centerPosition);
|
||||
const radius = (rect.width - padding) / 2;
|
||||
if (distance > radius) distance = radius;
|
||||
|
||||
if (this.dots.length > 0) {
|
||||
updatedDots = [{ ID: 0, Position: primaryDot.Position }];
|
||||
}
|
||||
|
||||
harmonyAngles.angles.forEach((angleOffset, index) => {
|
||||
let newAngle = (baseAngle + angleOffset) % 360;
|
||||
let radian = (newAngle * Math.PI) / 180;
|
||||
|
||||
let newPosition = {
|
||||
x: centerPosition.x + distance * Math.cos(radian),
|
||||
y: centerPosition.y + distance * Math.sin(radian),
|
||||
};
|
||||
|
||||
updatedDots.push({ ID: index + 1, Position: newPosition });
|
||||
});
|
||||
|
||||
return updatedDots;
|
||||
}
|
||||
|
||||
handleColorPositions(colorPositions) {
|
||||
colorPositions.sort((a, b) => a.ID - b.ID);
|
||||
|
||||
if (this.useAlgo === 'floating') {
|
||||
this.dots.forEach((dot) => {
|
||||
dot.Element.style.zIndex = 999;
|
||||
const colorFromPos = this.getColorFromPosition(dot.Position.x, dot.Position.y);
|
||||
dot.Element.style.setProperty(
|
||||
'--zen-theme-picker-dot-color',
|
||||
`rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const existingPrimaryDot = this.dots.find((d) => d.ID === 0);
|
||||
|
||||
if (existingPrimaryDot) {
|
||||
existingPrimaryDot.Element.style.zIndex = 999;
|
||||
const colorFromPos = this.getColorFromPosition(existingPrimaryDot.Position.x, existingPrimaryDot.Position.y);
|
||||
existingPrimaryDot.Element.style.setProperty(
|
||||
'--zen-theme-picker-dot-color',
|
||||
`rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})`
|
||||
);
|
||||
}
|
||||
|
||||
colorPositions.forEach((dotPosition) => {
|
||||
const existingDot = this.dots.find((dot) => dot.ID === dotPosition.ID);
|
||||
|
||||
if (existingDot) {
|
||||
existingDot.Position = dotPosition.Position;
|
||||
existingDot.Element.style.left = `${dotPosition.Position.x}px`;
|
||||
existingDot.Element.style.top = `${dotPosition.Position.y}px`;
|
||||
const colorFromPos = this.getColorFromPosition(dotPosition.Position.x, dotPosition.Position.y);
|
||||
existingDot.Element.style.setProperty(
|
||||
'--zen-theme-picker-dot-color',
|
||||
`rgb(${colorFromPos[0]}, ${colorFromPos[1]}, ${colorFromPos[2]})`
|
||||
);
|
||||
|
||||
if (!this.dragging) {
|
||||
gZenUIManager.motion.animate(
|
||||
existingDot.Element,
|
||||
{
|
||||
left: `${dotPosition.Position.x}px`,
|
||||
top: `${dotPosition.Position.y}px`,
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: 'spring',
|
||||
bounce: 0.3,
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.spawnDot(dotPosition.Position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onThemePickerClick(event) {
|
||||
event.preventDefault();
|
||||
const target = event.target;
|
||||
if (target.id === 'PanelUI-zen-gradient-generator-color-add') {
|
||||
if (this.dots.length >= ZenThemePicker.MAX_DOTS) return;
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'add', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
this.updateCurrentWorkspace();
|
||||
return;
|
||||
} else if (target.id === 'PanelUI-zen-gradient-generator-color-remove') {
|
||||
this.dots.sort((a, b) => a.ID - b.ID);
|
||||
if (this.dots.length === 0) return;
|
||||
|
||||
if (event.button !== 0 || this.dragging) return;
|
||||
const lastDot = this.dots.pop();
|
||||
lastDot.Element.remove();
|
||||
|
||||
this.dots.forEach((dot, index) => {
|
||||
dot.ID = index;
|
||||
});
|
||||
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'remove', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
this.updateCurrentWorkspace();
|
||||
return;
|
||||
} else if (target.id === 'PanelUI-zen-gradient-generator-color-toggle-algo') {
|
||||
const colorHarmonies = [
|
||||
{ type: 'complementary', angles: [180] },
|
||||
{ type: 'splitComplementary', angles: [150, 210] },
|
||||
{ type: 'analogous', angles: [30, 330] },
|
||||
{ type: 'triadic', angles: [120, 240] },
|
||||
{ type: 'floating', angles: [] },
|
||||
];
|
||||
|
||||
const applicableHarmonies = colorHarmonies.filter(
|
||||
(harmony) => harmony.angles.length + 1 === this.dots.length || harmony.type === 'floating'
|
||||
);
|
||||
|
||||
let currentIndex = applicableHarmonies.findIndex((harmony) => harmony.type === this.useAlgo);
|
||||
|
||||
let nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % applicableHarmonies.length;
|
||||
this.useAlgo = applicableHarmonies[nextIndex].type;
|
||||
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'update', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
this.updateCurrentWorkspace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.button !== 0 || this.dragging || this.recentlyDragged) return;
|
||||
|
||||
const gradient = this.panel.querySelector('.zen-theme-picker-gradient');
|
||||
const rect = gradient.getBoundingClientRect();
|
||||
const padding = 90; // each side
|
||||
const padding = 60;
|
||||
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
@@ -415,39 +467,62 @@
|
||||
let pixelX = event.clientX;
|
||||
let pixelY = event.clientY;
|
||||
|
||||
// Check if the click is within the circle
|
||||
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||
if (distance > radius) {
|
||||
const clickedElement = event.target;
|
||||
let clickedDot = null;
|
||||
const existingPrimaryDot = this.dots.find((d) => d.ID === 0);
|
||||
|
||||
clickedDot = this.dots.find((dot) => dot.Element === clickedElement);
|
||||
if (clickedDot) {
|
||||
existingPrimaryDot.ID = clickedDot.ID;
|
||||
clickedDot.ID = 0;
|
||||
clickedDot.Element.style.zIndex = 999;
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'update', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
return;
|
||||
}
|
||||
|
||||
const clickedElement = event.target;
|
||||
const isExistingDot = clickedElement.classList.contains('zen-theme-picker-dot');
|
||||
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||
if (distance > radius) {
|
||||
const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
|
||||
pixelX = centerX + Math.cos(angle) * radius;
|
||||
pixelY = centerY + Math.sin(angle) * radius;
|
||||
}
|
||||
|
||||
if (!isExistingDot && this.numberOfDots < ZenThemePicker.MAX_DOTS) {
|
||||
const relativeX = event.clientX - rect.left;
|
||||
const relativeY = event.clientY - rect.top;
|
||||
const relativeX = pixelX - rect.left;
|
||||
const relativeY = pixelY - rect.top;
|
||||
|
||||
const color = this.getColorFromPosition(relativeX, relativeY);
|
||||
|
||||
const dot = document.createElement('div');
|
||||
dot.classList.add('zen-theme-picker-dot');
|
||||
dot.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
||||
|
||||
dot.style.left = `${relativeX}px`;
|
||||
dot.style.top = `${relativeY}px`;
|
||||
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${color[0]}, ${color[1]}, ${color[2]})`);
|
||||
|
||||
const lastDot = this.panel.querySelector('.zen-theme-picker-dot:last-child');
|
||||
let newIndex = 0;
|
||||
if (lastDot) {
|
||||
newIndex = parseInt(lastDot.getAttribute('data-index')) + 1;
|
||||
if (!clickedDot && this.dots.length < 1) {
|
||||
if (this.dots.length === 0) {
|
||||
this.spawnDot({ x: relativeX, y: relativeY }, true);
|
||||
} else {
|
||||
this.spawnDot({ x: relativeX, y: relativeY });
|
||||
}
|
||||
dot.setAttribute('data-index', newIndex);
|
||||
|
||||
gradient.appendChild(dot);
|
||||
|
||||
this.updateCurrentWorkspace(true);
|
||||
} else if (!clickedDot && existingPrimaryDot) {
|
||||
existingPrimaryDot.Element.style.left = `${relativeX}px`;
|
||||
existingPrimaryDot.Element.style.top = `${relativeY}px`;
|
||||
existingPrimaryDot.Position = {
|
||||
x: relativeX,
|
||||
y: relativeY,
|
||||
};
|
||||
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'update', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
this.updateCurrentWorkspace(true);
|
||||
|
||||
gZenUIManager.motion.animate(
|
||||
existingPrimaryDot.Element,
|
||||
{
|
||||
left: `${existingPrimaryDot.Position.x}px`,
|
||||
top: `${existingPrimaryDot.Position.y}px`,
|
||||
},
|
||||
{
|
||||
duration: 0.4,
|
||||
type: 'spring',
|
||||
bounce: 0.3,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,13 +531,12 @@
|
||||
if (event.button === 2) {
|
||||
return;
|
||||
}
|
||||
if (!event.target.classList.contains('primary')) {
|
||||
return;
|
||||
const draggedDot = this.dots.find((dot) => dot.Element === event.target);
|
||||
if (draggedDot) {
|
||||
this.dragging = true;
|
||||
this.draggedDot = event.target;
|
||||
this.draggedDot.classList.add('dragging');
|
||||
}
|
||||
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 = {
|
||||
@@ -476,9 +550,20 @@
|
||||
if (!event.target.classList.contains('zen-theme-picker-dot')) {
|
||||
return;
|
||||
}
|
||||
this.dots = this.dots.filter((dot) => dot.Element !== event.target);
|
||||
event.target.remove();
|
||||
|
||||
this.dots.sort((a, b) => a.ID - b.ID);
|
||||
|
||||
// Reassign the IDs after sorting
|
||||
this.dots.forEach((dot, index) => {
|
||||
dot.ID = index;
|
||||
});
|
||||
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'update', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
|
||||
this.updateCurrentWorkspace();
|
||||
this.numberOfDots--;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -486,14 +571,55 @@
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.dragging = false;
|
||||
this.draggedDot.style.zIndex = 1;
|
||||
this.draggedDot.classList.remove('dragging');
|
||||
this.draggedDot = null;
|
||||
this.dragStartPosition = null; // Reset the drag start position
|
||||
|
||||
this.recentlyDragged = true;
|
||||
setTimeout(() => {
|
||||
this.recentlyDragged = false;
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length;
|
||||
onDotMouseMove(event) {
|
||||
if (this.dragging) {
|
||||
event.preventDefault();
|
||||
const rect = this.panel.querySelector('.zen-theme-picker-gradient').getBoundingClientRect();
|
||||
const padding = 90; // each side
|
||||
// do NOT let the ball be draged outside of an imaginary circle. You can drag it anywhere inside the circle
|
||||
// if the distance between the center of the circle and the dragged ball is bigger than the radius, then the ball
|
||||
// should be placed on the edge of the circle. If it's inside the circle, then the ball just follows the mouse
|
||||
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
const radius = (rect.width - padding) / 2;
|
||||
let pixelX = event.clientX;
|
||||
let pixelY = event.clientY;
|
||||
const distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||
if (distance > radius) {
|
||||
const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
|
||||
pixelX = centerX + Math.cos(angle) * radius;
|
||||
pixelY = centerY + Math.sin(angle) * radius;
|
||||
}
|
||||
|
||||
// set the location of the dot in pixels
|
||||
const relativeX = pixelX - rect.left;
|
||||
const relativeY = pixelY - rect.top;
|
||||
|
||||
const draggedDot = this.dots.find((dot) => dot.Element === this.draggedDot);
|
||||
draggedDot.Element.style.left = `${relativeX}px`;
|
||||
draggedDot.Element.style.top = `${relativeY}px`;
|
||||
draggedDot.Position = {
|
||||
x: relativeX,
|
||||
y: relativeY,
|
||||
};
|
||||
let colorPositions = this.calculateCompliments(this.dots, 'update', this.useAlgo);
|
||||
this.handleColorPositions(colorPositions);
|
||||
|
||||
this.updateCurrentWorkspace();
|
||||
}
|
||||
}
|
||||
|
||||
themedColors(colors) {
|
||||
@@ -676,7 +802,7 @@
|
||||
// Reactivate the transition after the animation
|
||||
appWrapper.removeAttribute('post-animating');
|
||||
}, 100);
|
||||
}, 500);
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -695,13 +821,10 @@
|
||||
browser.gZenThemePicker.currentRotation = workspaceTheme.rotation ?? 45;
|
||||
browser.gZenThemePicker.currentTexture = workspaceTheme.texture ?? 0;
|
||||
|
||||
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-texture').value =
|
||||
browser.gZenThemePicker.currentTexture;
|
||||
browser.gZenThemePicker.setRotationInput(browser.gZenThemePicker.currentRotation);
|
||||
|
||||
const gradient = browser.gZenThemePicker.getGradient(workspaceTheme.gradientColors);
|
||||
const gradientToolbar = browser.gZenThemePicker.getGradient(workspaceTheme.gradientColors, true);
|
||||
@@ -725,6 +848,7 @@
|
||||
}
|
||||
|
||||
if (!skipUpdate) {
|
||||
this.dots = [];
|
||||
browser.gZenThemePicker.recalculateDots(workspaceTheme.gradientColors);
|
||||
}
|
||||
});
|
||||
@@ -782,7 +906,6 @@
|
||||
}
|
||||
|
||||
recalculateDots(colors) {
|
||||
//THIS IS PART OF THE ISSUE
|
||||
for (const color of colors) {
|
||||
this.createDot(color, true);
|
||||
}
|
||||
@@ -805,7 +928,7 @@
|
||||
if (!skipSave) {
|
||||
await ZenWorkspacesStorage.saveWorkspaceTheme(currentWorkspace.uuid, gradient);
|
||||
await ZenWorkspaces._propagateWorkspaceData();
|
||||
ConfirmationHint.show(document.getElementById('PanelUI-menu-button'), 'zen-panel-ui-gradient-generator-saved-message');
|
||||
gZenUIManager.showToast('zen-panel-ui-gradient-generator-saved-message');
|
||||
currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ const defaultKeyboardGroups = {
|
||||
'zen-search-find-again-shortcut-prev',
|
||||
],
|
||||
pageOperations: [
|
||||
'zen-text-action-copy-url-markdown-shortcut',
|
||||
'zen-text-action-copy-url-shortcut',
|
||||
'zen-location-open-shortcut',
|
||||
'zen-location-open-shortcut-alt',
|
||||
@@ -755,7 +756,7 @@ class ZenKeyboardShortcutsLoader {
|
||||
}
|
||||
|
||||
class ZenKeyboardShortcutsVersioner {
|
||||
static LATEST_KBS_VERSION = 7;
|
||||
static LATEST_KBS_VERSION = 8;
|
||||
|
||||
constructor() {}
|
||||
|
||||
@@ -809,6 +810,20 @@ class ZenKeyboardShortcutsVersioner {
|
||||
return this.migrateIfNeeded(data);
|
||||
}
|
||||
|
||||
fillDefaultIfNotPresent(data) {
|
||||
for (let shortcut of ZenKeyboardShortcutsLoader.zenGetDefaultShortcuts()) {
|
||||
// If it has an ID and we dont find it in the data, we add it
|
||||
if (shortcut.getID() && !data.find((s) => s.getID() == shortcut.getID())) {
|
||||
data.push(shortcut);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
fixedKeyboardShortcuts(data) {
|
||||
return this.fillDefaultIfNotPresent(this.migrateIfNeeded(data));
|
||||
}
|
||||
|
||||
migrate(data, version) {
|
||||
if (version < 1) {
|
||||
// Migrate from 0 to 1
|
||||
@@ -907,6 +922,21 @@ class ZenKeyboardShortcutsVersioner {
|
||||
gZenKeyboardShortcutsManager._hasToLoadDefaultDevtools = true;
|
||||
window.addEventListener('zen-devtools-keyset-added', listener);
|
||||
}
|
||||
if (version < 8) {
|
||||
// Migrate from 7 to 8
|
||||
// In this new version, we add the "Copy URL as Markdown" shortcut to the default shortcuts
|
||||
data.push(
|
||||
new KeyShortcut(
|
||||
'zen-copy-url-markdown',
|
||||
'C',
|
||||
'',
|
||||
ZEN_OTHER_SHORTCUTS_GROUP,
|
||||
KeyShortcutModifiers.fromObject({ accel: true, shift: true, alt: true }),
|
||||
'code:gZenCommonActions.copyCurrentURLAsMarkdownToClipboard()',
|
||||
'zen-text-action-copy-url-markdown-shortcut'
|
||||
)
|
||||
);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -934,7 +964,7 @@ var gZenKeyboardShortcutsManager = {
|
||||
if (this.inBrowserView) {
|
||||
const loadedShortcuts = await this._loadSaved();
|
||||
|
||||
this._currentShortcutList = this.versioner.migrateIfNeeded(loadedShortcuts);
|
||||
this._currentShortcutList = this.versioner.fixedKeyboardShortcuts(loadedShortcuts);
|
||||
this._applyShortcuts();
|
||||
|
||||
await this._saveShortcuts();
|
||||
|
||||
@@ -69,7 +69,9 @@
|
||||
return;
|
||||
}
|
||||
|
||||
await this._refreshPinnedTabs(newWorkspace, { init: onInit });
|
||||
if (onInit) {
|
||||
await this._refreshPinnedTabs(newWorkspace, { init: onInit });
|
||||
}
|
||||
}
|
||||
|
||||
log(message) {
|
||||
@@ -152,7 +154,7 @@
|
||||
const pinsToCreate = new Set(pins.map((p) => p.uuid));
|
||||
|
||||
// First pass: identify existing tabs and remove those without pins
|
||||
for (let tab of gBrowser.tabs) {
|
||||
for (let tab of ZenWorkspaces.allStoredTabs) {
|
||||
const pinId = tab.getAttribute('zen-pin-id');
|
||||
if (!pinId) {
|
||||
continue;
|
||||
@@ -178,10 +180,6 @@
|
||||
continue; // Skip pins that already have tabs
|
||||
}
|
||||
|
||||
if (!this._shouldShowPin(pin, currentWorkspace, workspaces)) {
|
||||
continue; // Skip pins not relevant to current workspace
|
||||
}
|
||||
|
||||
let params = {
|
||||
skipAnimation: true,
|
||||
allowInheritPrincipal: false,
|
||||
@@ -234,6 +232,13 @@
|
||||
|
||||
this.log(`Created new pinned tab for pin ${pin.uuid} (isEssential: ${pin.isEssential})`);
|
||||
gBrowser.pinTab(newTab);
|
||||
if (!pin.isEssential) {
|
||||
const contaienr = document.querySelector(
|
||||
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${pin.workspaceUuid}"]`
|
||||
);
|
||||
contaienr.insertBefore(newTab, contaienr.lastChild);
|
||||
}
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
|
||||
newTab.initialize();
|
||||
}
|
||||
@@ -244,43 +249,7 @@
|
||||
}
|
||||
|
||||
gBrowser._updateTabBarForPinnedTabs();
|
||||
}
|
||||
|
||||
_shouldShowPin(pin, currentWorkspace, workspaces) {
|
||||
const isEssential = pin.isEssential;
|
||||
const pinWorkspaceUuid = pin.workspaceUuid;
|
||||
const pinContextId = pin.containerTabId ? pin.containerTabId.toString() : '0';
|
||||
const workspaceContextId = currentWorkspace.containerTabId?.toString() || '0';
|
||||
const containerSpecificEssentials = ZenWorkspaces.containerSpecificEssentials;
|
||||
|
||||
// Handle essential pins
|
||||
if (isEssential) {
|
||||
if (!containerSpecificEssentials) {
|
||||
return true; // Show all essential pins when containerSpecificEssentials is false
|
||||
}
|
||||
|
||||
if (workspaceContextId !== '0') {
|
||||
// In workspaces with default container: Show essentials that match the container
|
||||
return pinContextId === workspaceContextId;
|
||||
} else {
|
||||
// In workspaces without a default container: Show essentials that aren't in container-specific workspaces
|
||||
// or have userContextId="0" or no userContextId
|
||||
return (
|
||||
!pinContextId ||
|
||||
pinContextId === '0' ||
|
||||
!workspaces.workspaces.some((workspace) => workspace.containerTabId === parseInt(pinContextId, 10))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// For non-essential pins
|
||||
if (!pinWorkspaceUuid) {
|
||||
// Pins without a workspace belong to all workspaces (if that's your desired behavior)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Show if pin belongs to current workspace
|
||||
return pinWorkspaceUuid === currentWorkspace.uuid;
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
}
|
||||
|
||||
_onPinnedTabEvent(action, event) {
|
||||
@@ -321,12 +290,19 @@
|
||||
for (let otherTab of gBrowser.tabs) {
|
||||
if (otherTab.pinned && otherTab._tPos > tab.position) {
|
||||
const actualPin = this._pinsCache.find((pin) => pin.uuid === otherTab.getAttribute('zen-pin-id'));
|
||||
if (!actualPin) {
|
||||
continue;
|
||||
}
|
||||
actualPin.position = otherTab._tPos;
|
||||
await ZenPinnedTabsStorage.savePin(actualPin, false);
|
||||
}
|
||||
}
|
||||
|
||||
const actualPin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
|
||||
|
||||
if (!actualPin) {
|
||||
return;
|
||||
}
|
||||
actualPin.position = tab.position;
|
||||
await ZenPinnedTabsStorage.savePin(actualPin);
|
||||
}
|
||||
@@ -446,7 +422,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
_onCloseTabShortcut(event, selectedTab = gBrowser.selectedTab) {
|
||||
_onCloseTabShortcut(event, selectedTab = gBrowser.selectedTab, behavior = lazy.zenPinnedTabCloseShortcutBehavior) {
|
||||
if (!selectedTab?.pinned) {
|
||||
return;
|
||||
}
|
||||
@@ -454,8 +430,6 @@
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
const behavior = lazy.zenPinnedTabCloseShortcutBehavior;
|
||||
|
||||
switch (behavior) {
|
||||
case 'close':
|
||||
this._removePinnedAttributes(selectedTab, true);
|
||||
@@ -470,6 +444,9 @@
|
||||
this._resetTabToStoredState(selectedTab);
|
||||
}
|
||||
if (behavior.includes('unload')) {
|
||||
if (selectedTab.hasAttribute('glance-id')) {
|
||||
break;
|
||||
}
|
||||
gBrowser.explicitUnloadTabs([selectedTab]);
|
||||
selectedTab.removeAttribute('linkedpanel');
|
||||
}
|
||||
@@ -557,8 +534,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
addToEssentials() {
|
||||
const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
|
||||
addToEssentials(tab) {
|
||||
const tabs = tab ? [tab] : TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
const tab = tabs[i];
|
||||
tab.setAttribute('zen-essential', 'true');
|
||||
@@ -572,10 +549,11 @@
|
||||
gBrowser.pinTab(tab);
|
||||
this.onTabIconChanged(tab);
|
||||
}
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
}
|
||||
|
||||
removeEssentials() {
|
||||
const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
|
||||
removeEssentials(tab) {
|
||||
const tabs = tab ? [tab] : TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
const tab = tabs[i];
|
||||
tab.removeAttribute('zen-essential');
|
||||
@@ -584,6 +562,7 @@
|
||||
}
|
||||
gBrowser.unpinTab(tab);
|
||||
}
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
}
|
||||
|
||||
_insertItemsIntoTabContextMenu() {
|
||||
@@ -638,6 +617,172 @@
|
||||
document.getElementById('context_unpinSelectedTabs').hidden || contextTab.getAttribute('zen-essential');
|
||||
document.getElementById('context_zen-pinned-tab-separator').hidden = !isVisible;
|
||||
}
|
||||
|
||||
moveToAnotherTabContainerIfNecessary(event, movingTabs) {
|
||||
const pinnedTabsTarget =
|
||||
event.target.closest('#vertical-pinned-tabs-container') || event.target.closest('.zen-current-workspace-indicator');
|
||||
const essentialTabsTarget = event.target.closest('#zen-essentials-container');
|
||||
const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox');
|
||||
|
||||
let isVertical = this.expandedSidebarMode;
|
||||
let moved = false;
|
||||
for (const draggedTab of movingTabs) {
|
||||
let isRegularTabs = false;
|
||||
// Check for pinned tabs container
|
||||
if (pinnedTabsTarget) {
|
||||
if (!draggedTab.pinned) {
|
||||
gBrowser.pinTab(draggedTab);
|
||||
moved = true;
|
||||
} else if (draggedTab.hasAttribute('zen-essential')) {
|
||||
this.removeEssentials(draggedTab);
|
||||
gBrowser.pinTab(draggedTab);
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
// Check for essentials container
|
||||
else if (essentialTabsTarget) {
|
||||
if (!draggedTab.hasAttribute('zen-essential')) {
|
||||
this.addToEssentials(draggedTab);
|
||||
moved = true;
|
||||
isVertical = false;
|
||||
}
|
||||
}
|
||||
// Check for normal tabs container
|
||||
else if (tabsTarget || event.target.id === 'zen-tabs-wrapper') {
|
||||
if (draggedTab.pinned && !draggedTab.hasAttribute('zen-essential')) {
|
||||
gBrowser.unpinTab(draggedTab);
|
||||
moved = true;
|
||||
isRegularTabs = true;
|
||||
} else if (draggedTab.hasAttribute('zen-essential')) {
|
||||
this.removeEssentials(draggedTab);
|
||||
moved = true;
|
||||
isRegularTabs = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the tab was moved, adjust its position relative to the target tab
|
||||
if (moved) {
|
||||
const targetTab = event.target.closest('.tabbrowser-tab');
|
||||
if (targetTab) {
|
||||
const rect = targetTab.getBoundingClientRect();
|
||||
let newIndex = targetTab._tPos;
|
||||
|
||||
if (isVertical) {
|
||||
const middleY = targetTab.screenY + rect.height / 2;
|
||||
if (!isRegularTabs && event.screenY > middleY) {
|
||||
newIndex++;
|
||||
} else if (isRegularTabs && event.screenY < middleY) {
|
||||
newIndex--;
|
||||
}
|
||||
} else {
|
||||
const middleX = targetTab.screenX + rect.width / 2;
|
||||
if (event.screenX > middleX) {
|
||||
newIndex++;
|
||||
}
|
||||
}
|
||||
gBrowser.moveTabTo(draggedTab, newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
removeTabContainersDragoverClass() {
|
||||
this.dragIndicator.remove();
|
||||
this._dragIndicator = null;
|
||||
ZenWorkspaces.activeWorkspaceIndicator.removeAttribute('open');
|
||||
}
|
||||
|
||||
get dragIndicator() {
|
||||
if (!this._dragIndicator) {
|
||||
this._dragIndicator = document.createElement('div');
|
||||
this._dragIndicator.id = 'zen-drag-indicator';
|
||||
document.body.appendChild(this._dragIndicator);
|
||||
}
|
||||
return this._dragIndicator;
|
||||
}
|
||||
|
||||
get expandedSidebarMode() {
|
||||
return document.documentElement.getAttribute('zen-sidebar-expanded') === 'true';
|
||||
}
|
||||
|
||||
applyDragoverClass(event, draggedTab) {
|
||||
const pinnedTabsTarget = event.target.closest('#vertical-pinned-tabs-container');
|
||||
const essentialTabsTarget = event.target.closest('#zen-essentials-container');
|
||||
const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox');
|
||||
const targetTab = event.target.closest('.tabbrowser-tab');
|
||||
if (event.target.closest('.zen-current-workspace-indicator')) {
|
||||
this.removeTabContainersDragoverClass();
|
||||
ZenWorkspaces.activeWorkspaceIndicator.setAttribute('open', true);
|
||||
} else {
|
||||
ZenWorkspaces.activeWorkspaceIndicator.removeAttribute('open');
|
||||
}
|
||||
|
||||
// If there's no valid target tab, nothing to do
|
||||
if (!targetTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
let shouldAddDragOverElement = false;
|
||||
let isVertical = this.expandedSidebarMode;
|
||||
|
||||
// Decide whether we should show a dragover class for the given target
|
||||
if (pinnedTabsTarget) {
|
||||
if (!draggedTab.pinned || draggedTab.hasAttribute('zen-essential')) {
|
||||
shouldAddDragOverElement = true;
|
||||
}
|
||||
} else if (essentialTabsTarget) {
|
||||
if (!draggedTab.hasAttribute('zen-essential')) {
|
||||
shouldAddDragOverElement = true;
|
||||
isVertical = false;
|
||||
}
|
||||
} else if (tabsTarget) {
|
||||
if (draggedTab.pinned || draggedTab.hasAttribute('zen-essential')) {
|
||||
shouldAddDragOverElement = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldAddDragOverElement) {
|
||||
this.removeTabContainersDragoverClass();
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate middle to decide 'before' or 'after'
|
||||
const rect = targetTab.getBoundingClientRect();
|
||||
|
||||
if (isVertical) {
|
||||
const separation = 8;
|
||||
const middleY = targetTab.screenY + rect.height / 2;
|
||||
const indicator = this.dragIndicator;
|
||||
let top = 0;
|
||||
if (event.screenY > middleY) {
|
||||
top = rect.top + rect.height + 'px';
|
||||
} else {
|
||||
top = rect.top + 'px';
|
||||
}
|
||||
indicator.setAttribute('orientation', 'horizontal');
|
||||
indicator.style.setProperty('--indicator-left', rect.left + separation / 2 + 'px');
|
||||
indicator.style.setProperty('--indicator-width', rect.width - separation + 'px');
|
||||
indicator.style.top = top;
|
||||
indicator.style.removeProperty('left');
|
||||
} else {
|
||||
const separation = 8;
|
||||
const middleX = targetTab.screenX + rect.width / 2;
|
||||
const indicator = this.dragIndicator;
|
||||
let left = 0;
|
||||
if (event.screenX > middleX) {
|
||||
left = rect.left + rect.width + 1 + 'px';
|
||||
} else {
|
||||
left = rect.left - 2 + 'px';
|
||||
}
|
||||
indicator.setAttribute('orientation', 'vertical');
|
||||
indicator.style.setProperty('--indicator-top', rect.top + separation / 2 + 'px');
|
||||
indicator.style.setProperty('--indicator-height', rect.height - separation + 'px');
|
||||
indicator.style.left = left;
|
||||
indicator.style.removeProperty('top');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.gZenPinnedTabManager = new ZenPinnedTabManager();
|
||||
|
||||
@@ -46,7 +46,6 @@ var ZenPinnedTabsStorage = {
|
||||
CREATE INDEX IF NOT EXISTS idx_zen_pins_changes_uuid ON zen_pins_changes(uuid)
|
||||
`);
|
||||
|
||||
await SessionStore.promiseInitialized;
|
||||
this._resolveInitialized();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
}
|
||||
|
||||
handleTabClose(tab) {
|
||||
// Nothing yet
|
||||
tab.lastActivity = null;
|
||||
}
|
||||
|
||||
handleTabOpen(tab) {
|
||||
@@ -226,7 +226,7 @@
|
||||
unloadTab() {
|
||||
const tabs = TabContextMenu.contextTab.multiselected ? gBrowser.selectedTabs : [TabContextMenu.contextTab];
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
if (this.canUnloadTab(tabs[i], Date.now(), [], true)) {
|
||||
if (this.canUnloadTab(tabs[i], Date.now(), this.intervalUnloader.excludedUrls, true)) {
|
||||
this.unload(tabs[i]);
|
||||
}
|
||||
}
|
||||
@@ -258,6 +258,7 @@
|
||||
!tab.linkedPanel ||
|
||||
tab.splitView ||
|
||||
tab.attention ||
|
||||
tab.hasAttribute('glance-id') ||
|
||||
tab.linkedBrowser?.zenModeActive ||
|
||||
(tab.pictureinpicture && !ignoreTimestamp) ||
|
||||
(tab.soundPlaying && !ignoreTimestamp) ||
|
||||
|
||||
63
src/browser/base/zen-components/ZenUIMigration.mjs
Normal file
63
src/browser/base/zen-components/ZenUIMigration.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
BrowserWindowTracker: 'resource:///modules/BrowserWindowTracker.sys.mjs',
|
||||
});
|
||||
|
||||
class ZenUIMigration {
|
||||
PREF_NAME = 'zen.migration.version';
|
||||
MIGRATION_VERSION = 1;
|
||||
|
||||
init(isNewProfile, win) {
|
||||
if (!isNewProfile) {
|
||||
this._migrate(win);
|
||||
}
|
||||
this.clearVariables();
|
||||
}
|
||||
|
||||
get _migrationVersion() {
|
||||
return Services.prefs.getIntPref(this.PREF_NAME, 0);
|
||||
}
|
||||
|
||||
set _migrationVersion(value) {
|
||||
Services.prefs.setIntPref(this.PREF_NAME, value);
|
||||
}
|
||||
|
||||
_migrate(win) {
|
||||
if (this._migrationVersion < 1) {
|
||||
this._migrateV1(win);
|
||||
}
|
||||
}
|
||||
|
||||
clearVariables() {
|
||||
this._migrationVersion = this.MIGRATION_VERSION;
|
||||
}
|
||||
|
||||
async _migrateV1(win) {
|
||||
// Introduction of the new URL bar, show a message to the user
|
||||
const notification = win.gNotificationBox.appendNotification(
|
||||
'zen-new-urlbar-notification',
|
||||
{
|
||||
label: { 'l10n-id': 'zen-new-urlbar-notification' },
|
||||
image: 'chrome://browser/skin/notification-icons/persistent-storage-blocked.svg',
|
||||
priority: win.gNotificationBox.PRIORITY_WARNING_HIGH,
|
||||
},
|
||||
[
|
||||
{
|
||||
'l10n-id': 'zen-disable',
|
||||
accessKey: 'D',
|
||||
callback: () => {
|
||||
Services.prefs.setBoolPref('zen.urlbar.replace-newtab', false);
|
||||
},
|
||||
},
|
||||
{
|
||||
link: 'https://docs.zen-browser.app/user-manual/urlbar/',
|
||||
'l10n-id': 'zen-learn-more-text',
|
||||
},
|
||||
]
|
||||
);
|
||||
notification.persistence = -1;
|
||||
}
|
||||
}
|
||||
|
||||
export var gZenUIMigration = new ZenUIMigration();
|
||||
@@ -192,14 +192,13 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
|
||||
|
||||
afterRearangeAction() {
|
||||
document.getElementById('zenSplitViewModifier').hidePopup();
|
||||
ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-enabled-toast', {
|
||||
gZenUIManager.showToast('zen-split-view-modifier-enabled-toast', {
|
||||
descriptionId: 'zen-split-view-modifier-enabled-toast-description',
|
||||
showDescription: true,
|
||||
});
|
||||
}
|
||||
|
||||
afterRearangeRemove() {
|
||||
ConfirmationHint.show(document.getElementById('zen-split-views-box'), 'zen-split-view-modifier-disabled-toast');
|
||||
gZenUIManager.showToast('zen-split-view-modifier-disabled-toast');
|
||||
}
|
||||
|
||||
toggleWrapperDisplay(value) {
|
||||
|
||||
@@ -8,7 +8,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
|
||||
_swipeState = {
|
||||
isGestureActive: true,
|
||||
cumulativeDelta: 0,
|
||||
lastDelta: 0,
|
||||
direction: null,
|
||||
};
|
||||
_lastScrollTime = 0;
|
||||
@@ -28,13 +28,22 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
this._resolvePinnedInitialized = resolve;
|
||||
});
|
||||
|
||||
promiseSectionsInitialized = new Promise((resolve) => {
|
||||
this._resolveSectionsInitialized = resolve;
|
||||
});
|
||||
|
||||
workspaceIndicatorXUL = `
|
||||
<hbox class="zen-current-workspace-indicator-icon"></hbox>
|
||||
<hbox class="zen-current-workspace-indicator-name"></hbox>
|
||||
`;
|
||||
|
||||
async waitForPromises() {
|
||||
await Promise.all([this.promiseDBInitialized, this.promisePinnedInitialized, SessionStore.promiseAllWindowsRestored]);
|
||||
await Promise.all([this.promiseDBInitialized, this.promisePinnedInitialized]);
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (!this.shouldHaveWorkspaces) {
|
||||
document.getElementById('zen-current-workspace-indicator').setAttribute('hidden', 'true');
|
||||
document.getElementById('zen-current-workspace-indicator-container').setAttribute('hidden', 'true');
|
||||
console.warn('ZenWorkspaces: !!! ZenWorkspaces is disabled in hidden windows !!!');
|
||||
return; // We are in a hidden window, don't initialize ZenWorkspaces
|
||||
}
|
||||
@@ -70,17 +79,25 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
);
|
||||
ChromeUtils.defineLazyGetter(this, 'tabContainer', () => document.getElementById('tabbrowser-tabs'));
|
||||
this._activeWorkspace = Services.prefs.getStringPref('zen.workspaces.active', '');
|
||||
this._delayedStartup();
|
||||
await SessionStore.promiseInitialized;
|
||||
if (!this._hasInitializedTabsStrip) {
|
||||
await this.delayedStartup();
|
||||
}
|
||||
await this.promiseSectionsInitialized;
|
||||
window.addEventListener(
|
||||
'MozAfterPaint',
|
||||
async () => {
|
||||
await SessionStore.promiseAllWindowsRestored;
|
||||
await this.afterLoadInit();
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
async _delayedStartup() {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
await this.waitForPromises();
|
||||
await this.initializeWorkspaces();
|
||||
async afterLoadInit() {
|
||||
console.info('ZenWorkspaces: ZenWorkspaces initialized');
|
||||
|
||||
await this.initializeWorkspaces();
|
||||
if (Services.prefs.getBoolPref('zen.workspaces.swipe-actions', false) && this.workspaceEnabled) {
|
||||
this.initializeGestureHandlers();
|
||||
this.initializeWorkspaceNavigation();
|
||||
@@ -97,6 +114,137 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
);
|
||||
}
|
||||
|
||||
async delayedStartup() {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
this._pinnedTabsResizeObserver = new ResizeObserver(this.onPinnedTabsResize.bind(this));
|
||||
await this.waitForPromises();
|
||||
await this.initializeTabsStripSections();
|
||||
this._resolveSectionsInitialized();
|
||||
}
|
||||
|
||||
registerPinnedResizeObserver() {
|
||||
if (!this._hasInitializedTabsStrip) {
|
||||
return;
|
||||
}
|
||||
this._pinnedTabsResizeObserver.disconnect();
|
||||
for (let element of document.getElementById('vertical-pinned-tabs-container').children) {
|
||||
if (element.classList.contains('tabbrowser-tab')) {
|
||||
continue;
|
||||
}
|
||||
this._pinnedTabsResizeObserver.observe(element);
|
||||
}
|
||||
}
|
||||
|
||||
get activeWorkspaceStrip() {
|
||||
if (!this._hasInitializedTabsStrip) {
|
||||
return gBrowser.tabContainer.arrowScrollbox;
|
||||
}
|
||||
const activeWorkspace = this.activeWorkspace;
|
||||
return document.querySelector(
|
||||
`#tabbrowser-arrowscrollbox .zen-workspace-tabs-section[zen-workspace-id="${activeWorkspace}"]`
|
||||
);
|
||||
}
|
||||
|
||||
get activeWorkspaceIndicator() {
|
||||
return document.querySelector(
|
||||
`#zen-current-workspace-indicator-container .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
|
||||
);
|
||||
}
|
||||
|
||||
get tabboxChildren() {
|
||||
return this.activeWorkspaceStrip.children;
|
||||
}
|
||||
|
||||
get pinnedTabsContainer() {
|
||||
if (!this.workspaceEnabled || !this._hasInitializedTabsStrip) {
|
||||
return document.getElementById('vertical-pinned-tabs-container');
|
||||
}
|
||||
return document.querySelector(
|
||||
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
|
||||
);
|
||||
}
|
||||
|
||||
async initializeTabsStripSections() {
|
||||
const perifery = document.getElementById('tabbrowser-arrowscrollbox-periphery');
|
||||
const tabs = gBrowser.tabContainer.allTabs;
|
||||
const workspaces = await this._workspaces();
|
||||
for (const workspace of workspaces.workspaces) {
|
||||
this._createWorkspaceTabsSection(workspace, tabs, perifery);
|
||||
}
|
||||
if (tabs.length) {
|
||||
const defaultSelectedContainer = document.querySelector(
|
||||
`#tabbrowser-arrowscrollbox .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
|
||||
);
|
||||
// New profile with no workspaces does not have a default selected container
|
||||
if (defaultSelectedContainer) {
|
||||
const pinnedContainer = document.querySelector(
|
||||
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
|
||||
);
|
||||
for (const tab of tabs) {
|
||||
if (tab.pinned) {
|
||||
pinnedContainer.insertBefore(tab, pinnedContainer.lastChild);
|
||||
continue;
|
||||
}
|
||||
// before to the last child (perifery)
|
||||
defaultSelectedContainer.insertBefore(tab, defaultSelectedContainer.lastChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
perifery.setAttribute('hidden', 'true');
|
||||
this._hasInitializedTabsStrip = true;
|
||||
this.registerPinnedResizeObserver();
|
||||
this._fixIndicatorsNames(workspaces);
|
||||
}
|
||||
|
||||
_createWorkspaceSection(workspace) {
|
||||
const section = document.createXULElement('vbox');
|
||||
section.className = 'zen-workspace-tabs-section';
|
||||
section.setAttribute('flex', '1');
|
||||
section.setAttribute('zen-workspace-id', workspace.uuid);
|
||||
return section;
|
||||
}
|
||||
|
||||
async _createWorkspaceTabsSection(workspace, tabs, perifery) {
|
||||
const container = gBrowser.tabContainer.arrowScrollbox;
|
||||
const section = this._createWorkspaceSection(workspace);
|
||||
container.appendChild(section);
|
||||
|
||||
const pinnedContainer = document.getElementById('vertical-pinned-tabs-container');
|
||||
const pinnedSection = this._createWorkspaceSection(workspace);
|
||||
this._organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs);
|
||||
section.appendChild(perifery.cloneNode(true));
|
||||
pinnedSection.appendChild(
|
||||
window.MozXULElement.parseXULToFragment(`
|
||||
<html:div class="vertical-pinned-tabs-container-separator"></html:div>
|
||||
`)
|
||||
);
|
||||
pinnedContainer.appendChild(pinnedSection);
|
||||
|
||||
const workspaceIndicator = this._createWorkspaceSection(workspace);
|
||||
workspaceIndicator.classList.add('zen-current-workspace-indicator');
|
||||
workspaceIndicator.appendChild(window.MozXULElement.parseXULToFragment(this.workspaceIndicatorXUL));
|
||||
document.getElementById('zen-current-workspace-indicator-container').appendChild(workspaceIndicator);
|
||||
this.initIndicatorContextMenu(workspaceIndicator);
|
||||
}
|
||||
|
||||
_organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs) {
|
||||
const workspaceTabs = Array.from(tabs).filter((tab) => tab.getAttribute('zen-workspace-id') === workspace.uuid);
|
||||
for (const tab of workspaceTabs) {
|
||||
if (tab.hasAttribute('zen-essential')) {
|
||||
continue; // Ignore essentials as they need to be in their own section
|
||||
}
|
||||
// remove tab from list
|
||||
tabs.splice(tabs.indexOf(tab), 1);
|
||||
if (tab.pinned) {
|
||||
pinnedSection.appendChild(tab);
|
||||
} else {
|
||||
section.appendChild(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initializeWorkspaceNavigation() {
|
||||
this._setupAppCommandHandlers();
|
||||
this._setupSidebarHandlers();
|
||||
@@ -207,7 +355,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
element.addEventListener('MozSwipeGestureMayStart', this._handleSwipeMayStart.bind(this), true);
|
||||
element.addEventListener('MozSwipeGestureStart', this._handleSwipeStart.bind(this), true);
|
||||
element.addEventListener('MozSwipeGestureUpdate', this._handleSwipeUpdate.bind(this), true);
|
||||
element.addEventListener('MozSwipeGestureEnd', this._handleSwipeEnd.bind(this), true);
|
||||
|
||||
// Use MozSwipeGesture instead of MozSwipeGestureEnd because MozSwipeGestureEnd is fired after animation ends,
|
||||
// while MozSwipeGesture is fired immediately after swipe ends.
|
||||
element.addEventListener('MozSwipeGesture', this._handleSwipeEnd.bind(this), true);
|
||||
}
|
||||
|
||||
_handleSwipeMayStart(event) {
|
||||
@@ -231,7 +382,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
|
||||
this._swipeState = {
|
||||
isGestureActive: true,
|
||||
cumulativeDelta: 0,
|
||||
lastDelta: 0,
|
||||
direction: null,
|
||||
};
|
||||
}
|
||||
@@ -242,13 +393,19 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Update cumulative delta
|
||||
this._swipeState.cumulativeDelta += event.delta;
|
||||
const delta = event.delta * 300;
|
||||
this._swipeState.lastDelta = delta;
|
||||
|
||||
// Determine swipe direction based on cumulative delta
|
||||
if (Math.abs(this._swipeState.cumulativeDelta) > 0.25) {
|
||||
this._swipeState.direction = this._swipeState.cumulativeDelta > 0 ? 'left' : 'right';
|
||||
if (Math.abs(delta) > 1) {
|
||||
this._swipeState.direction = delta > 0 ? 'left' : 'right';
|
||||
}
|
||||
|
||||
// Apply a translateX to the tab strip to give the user feedback on the swipe
|
||||
const stripWidth = document.getElementById('tabbrowser-tabs').scrollWidth;
|
||||
const translateX = Math.max(-stripWidth, Math.min(delta, stripWidth));
|
||||
|
||||
const currentWorkspace = this.activeWorkspace;
|
||||
this._organizeWorkspaceStripLocations({ uuid: currentWorkspace }, true, translateX);
|
||||
}
|
||||
|
||||
async _handleSwipeEnd(event) {
|
||||
@@ -261,13 +418,15 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
let rawDirection = moveForward ? 1 : -1;
|
||||
if (this._swipeState.direction) {
|
||||
let direction = this.naturalScroll ? -1 : 1;
|
||||
this.changeWorkspaceShortcut(rawDirection * direction);
|
||||
this.changeWorkspaceShortcut(rawDirection * direction, true);
|
||||
} else {
|
||||
this._cancelSwipeAnimation();
|
||||
}
|
||||
|
||||
// Reset swipe state
|
||||
this._swipeState = {
|
||||
isGestureActive: false,
|
||||
cumulativeDelta: 0,
|
||||
lastDelta: 0,
|
||||
direction: null,
|
||||
};
|
||||
}
|
||||
@@ -384,35 +543,28 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
this._initializeWorkspaceTabContextMenus();
|
||||
await this.workspaceBookmarks();
|
||||
window.addEventListener('TabBrowserInserted', this.onTabBrowserInserted.bind(this));
|
||||
window.addEventListener('TabOpen', this.updateTabsContainers.bind(this));
|
||||
let workspaces = await this._workspaces();
|
||||
let activeWorkspace = null;
|
||||
if (workspaces.workspaces.length === 0) {
|
||||
activeWorkspace = await this.createAndSaveWorkspace('Default Workspace', true, '🏠');
|
||||
} else {
|
||||
activeWorkspace = await this.getActiveWorkspace();
|
||||
if (!activeWorkspace) {
|
||||
activeWorkspace = workspaces.workspaces.find((workspace) => workspace.default);
|
||||
this.activeWorkspace = activeWorkspace?.uuid;
|
||||
}
|
||||
if (!activeWorkspace) {
|
||||
activeWorkspace = workspaces.workspaces[0];
|
||||
this.activeWorkspace = activeWorkspace?.uuid;
|
||||
}
|
||||
this.activeWorkspace = activeWorkspace?.uuid;
|
||||
}
|
||||
try {
|
||||
if (activeWorkspace) {
|
||||
window.gZenThemePicker = new ZenThemePicker();
|
||||
await this.changeWorkspace(activeWorkspace, { onInit: true });
|
||||
gBrowser.tabContainer._positionPinnedTabs();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('ZenWorkspaces: Error initializing theme picker', e);
|
||||
}
|
||||
}
|
||||
this.initIndicatorContextMenu();
|
||||
}
|
||||
|
||||
initIndicatorContextMenu() {
|
||||
const indicator = document.getElementById('zen-current-workspace-indicator');
|
||||
initIndicatorContextMenu(indicator) {
|
||||
const th = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -624,7 +776,11 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
|
||||
async getActiveWorkspace() {
|
||||
const workspaces = await this._workspaces();
|
||||
return workspaces.workspaces.find((workspace) => workspace.uuid === this.activeWorkspace) ?? workspaces.workspaces[0];
|
||||
return (
|
||||
workspaces.workspaces.find((workspace) => workspace.uuid === this.activeWorkspace) ??
|
||||
workspaces.workspaces.find((workspace) => workspace.default) ??
|
||||
workspaces.workspaces[0]
|
||||
);
|
||||
}
|
||||
// Workspaces dialog UI management
|
||||
|
||||
@@ -726,7 +882,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (!browser.ZenWorkspaces.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
await browser.ZenWorkspaces.updateWorkspaceIndicator();
|
||||
let workspaceList = browser.document.getElementById('PanelUI-zen-workspaces-list');
|
||||
const createWorkspaceElement = (workspace) => {
|
||||
let element = browser.document.createXULElement('toolbarbutton');
|
||||
@@ -1020,7 +1175,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (!this.workspaceEnabled) {
|
||||
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');
|
||||
await this._propagateWorkspaceData({
|
||||
ignoreStrip: true,
|
||||
@@ -1177,13 +1332,25 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
}
|
||||
|
||||
moveTabToWorkspace(tab, workspaceID) {
|
||||
if (tab.getAttribute('zen-workspace-id') === workspaceID) {
|
||||
return;
|
||||
}
|
||||
tab.setAttribute('zen-workspace-id', workspaceID);
|
||||
const parent = tab.pinned ? '#zen-browser-tabs-pinned ' : '#zen-browser-tabs ';
|
||||
const container = document.querySelector(parent + '.zen-workspace-tabs-section');
|
||||
if (container) {
|
||||
container.insertBefore(tab, container.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
_prepareNewWorkspace(window) {
|
||||
document.documentElement.setAttribute('zen-workspace-id', window.uuid);
|
||||
let tabCount = 0;
|
||||
for (let tab of gBrowser.tabs) {
|
||||
const isEssential = tab.getAttribute('zen-essential') === 'true';
|
||||
if (!tab.hasAttribute('zen-workspace-id') && !tab.pinned && !isEssential) {
|
||||
tab.setAttribute('zen-workspace-id', window.uuid);
|
||||
this.moveTabToWorkspace(tab, window.uuid);
|
||||
tabCount++;
|
||||
}
|
||||
}
|
||||
@@ -1198,6 +1365,8 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (window.uuid) {
|
||||
tab.setAttribute('zen-workspace-id', window.uuid);
|
||||
}
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
async saveWorkspaceFromCreate() {
|
||||
@@ -1262,21 +1431,25 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (!this.workspaceEnabled || this._inChangingWorkspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
await SessionStore.promiseInitialized;
|
||||
this._inChangingWorkspace = true;
|
||||
try {
|
||||
await this._performWorkspaceChange(window, ...args);
|
||||
} finally {
|
||||
this._inChangingWorkspace = false;
|
||||
this.tabContainer.removeAttribute('dont-animate-tabs');
|
||||
}
|
||||
}
|
||||
|
||||
async _performWorkspaceChange(window, { onInit = false, explicitAnimationDirection = undefined } = {}) {
|
||||
const previousWorkspace = await this.getActiveWorkspace();
|
||||
_cancelSwipeAnimation() {
|
||||
const currentWorkspace = this.activeWorkspace;
|
||||
this._animateTabs({ uuid: currentWorkspace }, true);
|
||||
}
|
||||
|
||||
if (previousWorkspace && previousWorkspace.uuid === window.uuid && !onInit) {
|
||||
async _performWorkspaceChange(window, { onInit = false, alwaysChange = false, whileScrolling = false } = {}) {
|
||||
const previousWorkspace = await this.getActiveWorkspace();
|
||||
alwaysChange = alwaysChange || onInit;
|
||||
|
||||
if (previousWorkspace && previousWorkspace.uuid === window.uuid && !alwaysChange) {
|
||||
this._cancelSwipeAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1285,107 +1458,130 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
const workspaces = await this._workspaces();
|
||||
|
||||
// Refresh tab cache
|
||||
gBrowser.verticalPinnedTabsContainer = this.pinnedTabsContainer;
|
||||
gBrowser.tabContainer.verticalPinnedTabsContainer = this.pinnedTabsContainer;
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
|
||||
let animationDirection;
|
||||
if (previousWorkspace && !onInit && !this._animatingChange) {
|
||||
animationDirection =
|
||||
explicitAnimationDirection ??
|
||||
(workspaces.workspaces.findIndex((w) => w.uuid === previousWorkspace.uuid) <
|
||||
workspaces.workspaces.findIndex((w) => w.uuid === window.uuid)
|
||||
? 'right'
|
||||
: 'left');
|
||||
}
|
||||
if (animationDirection) {
|
||||
// Animate tabs out of view before changing workspace, therefor we
|
||||
// need to animate in the opposite direction
|
||||
await this._animateTabs(animationDirection === 'left' ? 'right' : 'left', true);
|
||||
if (!whileScrolling) {
|
||||
await this._organizeWorkspaceStripLocations(previousWorkspace);
|
||||
}
|
||||
|
||||
// First pass: Handle tab visibility and workspace ID assignment
|
||||
const visibleTabs = this._processTabVisibility(window.uuid, containerId, workspaces);
|
||||
this._processTabVisibility(window.uuid, containerId, workspaces);
|
||||
|
||||
// Second pass: Handle tab selection
|
||||
await this._handleTabSelection(window, onInit, visibleTabs, containerId, workspaces);
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
const tabToSelect = await this._handleTabSelection(window, onInit, containerId, workspaces, previousWorkspace.uuid);
|
||||
|
||||
// Update UI and state
|
||||
await this._updateWorkspaceState(window, onInit);
|
||||
await this._updateWorkspaceState(window, onInit, tabToSelect);
|
||||
}
|
||||
|
||||
if (animationDirection) {
|
||||
await this._animateTabs(animationDirection);
|
||||
_updateMarginTopPinnedTabs(arrowscrollbox, pinnedContainer) {
|
||||
if (arrowscrollbox) {
|
||||
arrowscrollbox.style.marginTop = pinnedContainer.getBoundingClientRect().height + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
async _animateTabs(direction, out = false) {
|
||||
const selector = `#tabbrowser-tabs *:is(#zen-current-workspace-indicator, #vertical-pinned-tabs-container-separator, .tabbrowser-tab:not([zen-essential], [hidden]))`;
|
||||
const extraSelector = `#tabbrowser-arrowscrollbox-periphery > toolbarbutton`;
|
||||
this.tabContainer.removeAttribute('dont-animate-tabs');
|
||||
// order by actual position in the children list to animate
|
||||
const elements = Array.from([
|
||||
...this.tabContainer.querySelectorAll(selector),
|
||||
...this.tabContainer.querySelectorAll(extraSelector),
|
||||
])
|
||||
.sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING)
|
||||
.reverse();
|
||||
if (out) {
|
||||
return gZenUIManager.motion.animate(
|
||||
elements,
|
||||
{
|
||||
transform: `translateX(${direction === 'left' ? '-' : ''}100%)`,
|
||||
opacity: 0,
|
||||
},
|
||||
{
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
duration: 0.12,
|
||||
// delay: gZenUIManager.motion.stagger(0.01),
|
||||
}
|
||||
);
|
||||
async _organizeWorkspaceStripLocations(workspace, justMove = false, offsetPixels = 0) {
|
||||
const workspaces = await this._workspaces();
|
||||
let workspaceIndex = workspaces.workspaces.findIndex((w) => w.uuid === workspace.uuid);
|
||||
if (!justMove) {
|
||||
this._fixIndicatorsNames(workspaces);
|
||||
}
|
||||
return gZenUIManager.motion.animate(
|
||||
elements,
|
||||
{
|
||||
transform: [`translateX(${direction === 'left' ? '-' : ''}100%)`, 'translateX(0%)'],
|
||||
opacity: 1,
|
||||
},
|
||||
{
|
||||
duration: 0.15,
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
// delay: gZenUIManager.motion.stagger(0.02),
|
||||
for (const otherWorkspace of workspaces.workspaces) {
|
||||
const selector = `.zen-workspace-tabs-section[zen-workspace-id="${otherWorkspace.uuid}"]`;
|
||||
const newTransform = -(workspaceIndex - workspaces.workspaces.indexOf(otherWorkspace)) * 100;
|
||||
for (const container of document.querySelectorAll(selector)) {
|
||||
container.style.transform = `translateX(${newTransform + offsetPixels / 2}%)`;
|
||||
container.style.opacity = offsetPixels ? 1 : !newTransform;
|
||||
if (!offsetPixels && !container.hasAttribute('active')) {
|
||||
container.setAttribute('hidden', 'true');
|
||||
} else {
|
||||
container.removeAttribute('hidden');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
updateWorkspaceIndicator(currentWorkspace, workspaceIndicator) {
|
||||
if (!workspaceIndicator) {
|
||||
return;
|
||||
}
|
||||
const indicatorName = workspaceIndicator.querySelector('.zen-current-workspace-indicator-name');
|
||||
const indicatorIcon = workspaceIndicator.querySelector('.zen-current-workspace-indicator-icon');
|
||||
|
||||
if (this.workspaceHasIcon(currentWorkspace)) {
|
||||
indicatorIcon.removeAttribute('no-icon');
|
||||
} else {
|
||||
indicatorIcon.setAttribute('no-icon', 'true');
|
||||
}
|
||||
indicatorIcon.textContent = this.getWorkspaceIcon(currentWorkspace);
|
||||
indicatorName.textContent = currentWorkspace.name;
|
||||
}
|
||||
|
||||
_fixIndicatorsNames(workspaces) {
|
||||
for (const workspace of workspaces.workspaces) {
|
||||
const workspaceIndicator = document.querySelector(
|
||||
`#zen-current-workspace-indicator-container .zen-workspace-tabs-section[zen-workspace-id="${workspace.uuid}"]`
|
||||
);
|
||||
this.updateWorkspaceIndicator(workspace, workspaceIndicator);
|
||||
}
|
||||
}
|
||||
|
||||
async _animateTabs(newWorkspace, shouldAnimate, tabToSelect = null) {
|
||||
this._animatingChange = true;
|
||||
const animations = [];
|
||||
const workspaces = await this._workspaces();
|
||||
const newWorkspaceIndex = workspaces.workspaces.findIndex((w) => w.uuid === newWorkspace.uuid);
|
||||
for (const element of document.querySelectorAll('.zen-workspace-tabs-section')) {
|
||||
const existingTransform = element.style.transform;
|
||||
const elementWorkspaceId = element.getAttribute('zen-workspace-id');
|
||||
const elementWorkspaceIndex = workspaces.workspaces.findIndex((w) => w.uuid === elementWorkspaceId);
|
||||
const offset = -(newWorkspaceIndex - elementWorkspaceIndex) * 100;
|
||||
const newTransform = `translateX(${offset}%)`;
|
||||
const isCurrent = offset === 0;
|
||||
if (shouldAnimate) {
|
||||
element.removeAttribute('hidden');
|
||||
if (isCurrent) {
|
||||
element.style.opacity = 1;
|
||||
}
|
||||
animations.push(
|
||||
gZenUIManager.motion.animate(
|
||||
element,
|
||||
{
|
||||
transform: existingTransform ? [existingTransform, newTransform] : newTransform,
|
||||
// -0 to convert to number
|
||||
opacity: !isCurrent ? [!!offset - 0, !offset - 0] : [1, 1],
|
||||
},
|
||||
{
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
duration: 0.3,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
if (offset === 0) {
|
||||
element.setAttribute('active', 'true');
|
||||
if (tabToSelect != gBrowser.selectedTab) {
|
||||
gBrowser.selectedTab = tabToSelect;
|
||||
}
|
||||
} else {
|
||||
element.removeAttribute('active');
|
||||
}
|
||||
}
|
||||
await Promise.all(animations);
|
||||
this._animatingChange = false;
|
||||
}
|
||||
|
||||
_processTabVisibility(workspaceUuid, containerId, workspaces) {
|
||||
const visibleTabs = new Set();
|
||||
const lastSelectedTab = this._lastSelectedWorkspaceTabs[workspaceUuid];
|
||||
|
||||
this.tabContainer.setAttribute('dont-animate-tabs', 'true');
|
||||
for (const tab of gBrowser.tabs) {
|
||||
const tabWorkspaceId = tab.getAttribute('zen-workspace-id');
|
||||
const isEssential = tab.getAttribute('zen-essential') === 'true';
|
||||
|
||||
// Always hide last selected tabs from other workspaces
|
||||
if (lastSelectedTab === tab && tabWorkspaceId !== workspaceUuid && !isEssential) {
|
||||
gBrowser.hideTab(tab, undefined, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this._shouldShowTab(tab, workspaceUuid, containerId, workspaces)) {
|
||||
gBrowser.showTab(tab);
|
||||
visibleTabs.add(tab);
|
||||
|
||||
// Assign workspace ID if needed
|
||||
if (!tabWorkspaceId && !isEssential) {
|
||||
tab.setAttribute('zen-workspace-id', workspaceUuid);
|
||||
}
|
||||
} else {
|
||||
if (!this._shouldShowTab(tab, workspaceUuid, containerId, workspaces)) {
|
||||
gBrowser.hideTab(tab, undefined, true);
|
||||
} else if (tab.hasAttribute('zen-essential')) {
|
||||
gBrowser.showTab(tab, undefined, true);
|
||||
}
|
||||
}
|
||||
|
||||
return visibleTabs;
|
||||
}
|
||||
|
||||
_shouldShowTab(tab, workspaceUuid, containerId, workspaces) {
|
||||
@@ -1416,7 +1612,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
// For non-essential tabs (both normal and pinned)
|
||||
if (!tabWorkspaceId) {
|
||||
// Assign workspace ID to tabs without one
|
||||
tab.setAttribute('zen-workspace-id', workspaceUuid);
|
||||
this.moveTabToWorkspace(tab, workspaceUuid);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1424,9 +1620,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
return tabWorkspaceId === workspaceUuid;
|
||||
}
|
||||
|
||||
async _handleTabSelection(window, onInit, visibleTabs, containerId, workspaces) {
|
||||
async _handleTabSelection(window, onInit, containerId, workspaces, previousWorkspaceId) {
|
||||
const currentSelectedTab = gBrowser.selectedTab;
|
||||
const oldWorkspaceId = currentSelectedTab.getAttribute('zen-workspace-id');
|
||||
const oldWorkspaceId = previousWorkspaceId;
|
||||
const lastSelectedTab = this._lastSelectedWorkspaceTabs[window.uuid];
|
||||
|
||||
// Save current tab as last selected for old workspace if it shouldn't be visible in new workspace
|
||||
@@ -1435,53 +1631,54 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
let tabToSelect = null;
|
||||
|
||||
// If current tab is visible in new workspace, keep it
|
||||
if (this._shouldShowTab(currentSelectedTab, window.uuid, containerId, workspaces) && visibleTabs.has(currentSelectedTab)) {
|
||||
tabToSelect = currentSelectedTab;
|
||||
}
|
||||
// Try last selected tab if it is visible
|
||||
else if (
|
||||
lastSelectedTab &&
|
||||
this._shouldShowTab(lastSelectedTab, window.uuid, containerId, workspaces) &&
|
||||
visibleTabs.has(lastSelectedTab)
|
||||
) {
|
||||
if (lastSelectedTab && this._shouldShowTab(lastSelectedTab, window.uuid, containerId, workspaces)) {
|
||||
tabToSelect = lastSelectedTab;
|
||||
}
|
||||
// Find first suitable tab
|
||||
else {
|
||||
tabToSelect = Array.from(visibleTabs).find((tab) => !tab.pinned);
|
||||
tabToSelect = gBrowser.visibleTabs.find((tab) => !tab.pinned);
|
||||
if (!tabToSelect && gBrowser.visibleTabs.length) {
|
||||
tabToSelect = gBrowser.visibleTabs[gBrowser.visibleTabs.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
const previousSelectedTab = gBrowser.selectedTab;
|
||||
|
||||
// If we found a tab to select, select it
|
||||
if (tabToSelect) {
|
||||
gBrowser.selectedTab = tabToSelect;
|
||||
this._lastSelectedWorkspaceTabs[window.uuid] = tabToSelect;
|
||||
} else if (!onInit) {
|
||||
if (!onInit && !tabToSelect) {
|
||||
// Create new tab if needed and no suitable tab was found
|
||||
const newTab = this._createNewTabForWorkspace(window);
|
||||
gBrowser.selectedTab = newTab;
|
||||
this._lastSelectedWorkspaceTabs[window.uuid] = newTab;
|
||||
tabToSelect = newTab;
|
||||
}
|
||||
if (tabToSelect) {
|
||||
tabToSelect._visuallySelected = true;
|
||||
}
|
||||
|
||||
// After selecting the new tab, hide the previous selected tab if it shouldn't be visible in the new workspace
|
||||
if (!this._shouldShowTab(previousSelectedTab, window.uuid, containerId, workspaces)) {
|
||||
gBrowser.hideTab(previousSelectedTab, undefined, true);
|
||||
// Always make sure we always unselect the tab from the old workspace
|
||||
if (currentSelectedTab && currentSelectedTab !== tabToSelect) {
|
||||
currentSelectedTab._selected = false;
|
||||
}
|
||||
return tabToSelect;
|
||||
}
|
||||
|
||||
async _updateWorkspaceState(window, onInit) {
|
||||
async _updateWorkspaceState(window, onInit, tabToSelect) {
|
||||
// Update document state
|
||||
document.documentElement.setAttribute('zen-workspace-id', window.uuid);
|
||||
|
||||
// Recalculate new tab observers
|
||||
gBrowser.tabContainer.observe(null, 'nsPref:changed', 'privacy.userContext.enabled');
|
||||
|
||||
// Update workspace UI
|
||||
await this._updateWorkspacesChangeContextMenu();
|
||||
document.getElementById('tabbrowser-tabs')._positionPinnedTabs();
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
await this._propagateWorkspaceData({ clearCache: false });
|
||||
|
||||
gZenThemePicker.onWorkspaceChange(window);
|
||||
|
||||
document.getElementById('zen-tabs-wrapper').style.scrollbarWidth = 'none';
|
||||
await this._animateTabs(window, !onInit && !this._animatingChange, tabToSelect);
|
||||
await this._organizeWorkspaceStripLocations(window, true);
|
||||
document.getElementById('zen-tabs-wrapper').style.scrollbarWidth = '';
|
||||
|
||||
// Notify listeners
|
||||
if (this._changeListeners?.length) {
|
||||
for (const listener of this._changeListeners) {
|
||||
@@ -1493,7 +1690,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
this._invalidateBookmarkContainers();
|
||||
|
||||
// Update workspace indicator
|
||||
await this.updateWorkspaceIndicator();
|
||||
await this.updateWorkspaceIndicator(window, this.workspaceIndicator);
|
||||
}
|
||||
|
||||
_invalidateBookmarkContainers() {
|
||||
@@ -1506,22 +1703,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
}
|
||||
|
||||
async updateWorkspaceIndicator() {
|
||||
// Update current workspace indicator
|
||||
const currentWorkspace = await this.getActiveWorkspace();
|
||||
if (!currentWorkspace) return;
|
||||
const indicatorName = document.getElementById('zen-current-workspace-indicator-name');
|
||||
const indicatorIcon = document.getElementById('zen-current-workspace-indicator-icon');
|
||||
|
||||
if (this.workspaceHasIcon(currentWorkspace)) {
|
||||
indicatorIcon.removeAttribute('no-icon');
|
||||
} else {
|
||||
indicatorIcon.setAttribute('no-icon', 'true');
|
||||
}
|
||||
indicatorIcon.textContent = this.getWorkspaceIcon(currentWorkspace);
|
||||
indicatorName.textContent = currentWorkspace.name;
|
||||
}
|
||||
|
||||
async _updateWorkspacesChangeContextMenu() {
|
||||
const workspaces = await this._workspaces();
|
||||
|
||||
@@ -1546,7 +1727,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
}
|
||||
|
||||
_createWorkspaceData(name, isDefault, icon) {
|
||||
_createWorkspaceData(name, isDefault, icon, tabs) {
|
||||
let window = {
|
||||
uuid: gZenUIManager.generateUuidv4(),
|
||||
default: isDefault,
|
||||
@@ -1555,6 +1736,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
theme: ZenThemePicker.getTheme([]),
|
||||
};
|
||||
this._prepareNewWorkspace(window);
|
||||
const perifery = document.querySelector('#tabbrowser-arrowscrollbox-periphery[hidden]');
|
||||
perifery?.removeAttribute('hidden');
|
||||
this._createWorkspaceTabsSection(window, tabs, perifery);
|
||||
perifery.setAttribute('hidden', 'true');
|
||||
return window;
|
||||
}
|
||||
|
||||
@@ -1562,12 +1747,49 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
let workspaceData = this._createWorkspaceData(name, isDefault, icon);
|
||||
// get extra tabs remaning (e.g. on new profiles) and just move them to the new workspace
|
||||
const extraTabs = Array.from(gBrowser.tabContainer.arrowScrollbox.children).filter(
|
||||
(child) => child.tagName === 'tab' && !child.hasAttribute('zen-workspace-id')
|
||||
);
|
||||
let workspaceData = this._createWorkspaceData(name, isDefault, icon, extraTabs);
|
||||
await this.saveWorkspace(workspaceData);
|
||||
this.registerPinnedResizeObserver();
|
||||
let changed = extraTabs.length > 0;
|
||||
if (changed) {
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
gBrowser.selectedTab = extraTabs[0];
|
||||
}
|
||||
await this.changeWorkspace(workspaceData);
|
||||
return workspaceData;
|
||||
}
|
||||
|
||||
updateTabsContainers() {
|
||||
this.onPinnedTabsResize([{ target: this.pinnedTabsContainer }]);
|
||||
}
|
||||
|
||||
updateShouldHideSeparator(arrowScrollbox, pinnedContainer) {
|
||||
const shouldHideSeparator = pinnedContainer.children.length === 1 || arrowScrollbox.children.length === 1;
|
||||
if (shouldHideSeparator) {
|
||||
pinnedContainer.setAttribute('hide-separator', 'true');
|
||||
} else {
|
||||
pinnedContainer.removeAttribute('hide-separator');
|
||||
}
|
||||
}
|
||||
|
||||
onPinnedTabsResize(entries) {
|
||||
if (!this._hasInitializedTabsStrip) {
|
||||
return;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const workspaceId = entry.target.getAttribute('zen-workspace-id');
|
||||
const arrowScrollbox = document.querySelector(
|
||||
`#tabbrowser-arrowscrollbox .zen-workspace-tabs-section[zen-workspace-id="${workspaceId}"]`
|
||||
);
|
||||
this._updateMarginTopPinnedTabs(arrowScrollbox, entry.target);
|
||||
this.updateShouldHideSeparator(arrowScrollbox, entry.target);
|
||||
}
|
||||
}
|
||||
|
||||
async onTabBrowserInserted(event) {
|
||||
let tab = event.originalTarget;
|
||||
const isEssential = tab.getAttribute('zen-essential') === 'true';
|
||||
@@ -1603,12 +1825,48 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
// Switch workspace if needed
|
||||
if (workspaceID && workspaceID !== activeWorkspace.uuid) {
|
||||
if (workspaceID && workspaceID !== activeWorkspace.uuid && parent.ZenWorkspaces._hasInitializedTabsStrip) {
|
||||
await parent.ZenWorkspaces.changeWorkspace({ uuid: workspaceID });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
makeSurePinTabIsInCorrectPosition() {
|
||||
if (!this.pinnedTabsContainer) {
|
||||
return 0; // until we initialize the pinned tabs container
|
||||
}
|
||||
const tabsInsidePinTab = Array.from(this.pinnedTabsContainer.parentElement.children).filter(
|
||||
(child) => child.tagName === 'tab'
|
||||
);
|
||||
let changed = false;
|
||||
for (const tab of tabsInsidePinTab) {
|
||||
if (tab.getAttribute('zen-glance-tab') === 'true') {
|
||||
continue;
|
||||
}
|
||||
if (tab.getAttribute('zen-essential') === 'true') {
|
||||
const container = document.getElementById('zen-essentials-container');
|
||||
container.appendChild(tab);
|
||||
changed = true;
|
||||
continue;
|
||||
}
|
||||
const workspaceId = tab.getAttribute('zen-workspace-id');
|
||||
if (!workspaceId) {
|
||||
continue;
|
||||
}
|
||||
const contaienr = document.querySelector(
|
||||
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${workspaceId}"]`
|
||||
);
|
||||
contaienr.insertBefore(tab, contaienr.firstChild);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
}
|
||||
// Return the number of essentials INSIDE the pinned tabs container so we can correctly change their parent
|
||||
return Array.from(this.pinnedTabsContainer.children).filter((child) => child.getAttribute('zen-essential') === 'true')
|
||||
.length;
|
||||
}
|
||||
|
||||
// Context menu management
|
||||
|
||||
_contextMenuId = null;
|
||||
@@ -1705,7 +1963,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
this._emojis = null;
|
||||
}
|
||||
|
||||
async changeWorkspaceShortcut(offset = 1) {
|
||||
async changeWorkspaceShortcut(offset = 1, whileScrolling = false) {
|
||||
// Cycle through workspaces
|
||||
let workspaces = await this._workspaces();
|
||||
let activeWorkspace = await this.getActiveWorkspace();
|
||||
@@ -1722,7 +1980,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
let nextWorkspace = workspaces.workspaces[targetIndex];
|
||||
await this.changeWorkspace(nextWorkspace, { explicitAnimationDirection: offset > 0 ? 'right' : 'left' });
|
||||
await this.changeWorkspace(nextWorkspace, { whileScrolling });
|
||||
}
|
||||
|
||||
_initializeWorkspaceTabContextMenus() {
|
||||
@@ -1744,7 +2002,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
document.getElementById('tabContextMenu').hidePopup();
|
||||
const previousWorkspaceID = document.documentElement.getAttribute('zen-workspace-id');
|
||||
for (let tab of tabs) {
|
||||
tab.setAttribute('zen-workspace-id', workspaceID);
|
||||
this.moveTabToWorkspace(tab, workspaceID);
|
||||
if (this._lastSelectedWorkspaceTabs[previousWorkspaceID] === tab) {
|
||||
// This tab is no longer the last selected tab in the previous workspace because it's being moved to
|
||||
// the current workspace
|
||||
@@ -1782,7 +2040,13 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (matchingWorkspaces.length === 1) {
|
||||
const workspace = matchingWorkspaces[0];
|
||||
if (workspace.uuid !== this.getActiveWorkspaceFromCache().uuid) {
|
||||
this.changeWorkspace(workspace);
|
||||
window.addEventListener(
|
||||
'TabSelected',
|
||||
(event) => {
|
||||
this.changeWorkspace(workspace, { alwaysChange: true });
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
return [userContextId, true, workspace.uuid];
|
||||
}
|
||||
}
|
||||
@@ -1831,4 +2095,43 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
// Return true only if the bookmark is in another workspace and not in the active one
|
||||
return isInOtherWorkspace && !isInActiveWorkspace;
|
||||
}
|
||||
|
||||
// Session restore functions
|
||||
get allStoredTabs() {
|
||||
if (!this._hasInitializedTabsStrip) {
|
||||
const children = Array.from(this.tabboxChildren);
|
||||
children.pop(); // Remove the last child which is the new tab button
|
||||
return children;
|
||||
}
|
||||
|
||||
const tabs = [];
|
||||
// we need to go through each tab in each container
|
||||
const essentialsContainer = document.getElementById('zen-essentials-container');
|
||||
const pinnedContainers = document.querySelectorAll('#vertical-pinned-tabs-container .zen-workspace-tabs-section');
|
||||
const normalContainers = document.querySelectorAll('#tabbrowser-arrowscrollbox .zen-workspace-tabs-section');
|
||||
const containers = [essentialsContainer, ...pinnedContainers, ...normalContainers];
|
||||
for (const container of containers) {
|
||||
for (const tab of container.children) {
|
||||
if (tab.tagName === 'tab' || tab.tagName == 'tab-group') {
|
||||
tabs.push(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tabs;
|
||||
}
|
||||
|
||||
get pinnedTabCount() {
|
||||
return this.pinnedTabsContainer.children.length - 1;
|
||||
}
|
||||
|
||||
get normalTabCount() {
|
||||
return this.tabboxChildren.length - 1;
|
||||
}
|
||||
|
||||
get allWorkspaceTabs() {
|
||||
const currentWorkspace = this.activeWorkspace;
|
||||
return this.allStoredTabs.filter(
|
||||
(tab) => tab.hasAttribute('zen-essential') || tab.getAttribute('zen-workspace-id') === currentWorkspace
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -96,7 +96,7 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
}
|
||||
|
||||
handleClick(event) {
|
||||
if (this.ensureOnlyKeyModifiers(event)) {
|
||||
if (this.ensureOnlyKeyModifiers(event) || event.button !== 0 || event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
const activationMethod = this._activationMethod;
|
||||
|
||||
@@ -122,10 +122,10 @@ export class ZenThemeMarketplaceParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
getStyleSheetFullContent(style = '') {
|
||||
let stylesheet = '@-moz-document url-prefix("chrome:") {';
|
||||
let stylesheet = '@-moz-document url-prefix("chrome:") {\n';
|
||||
|
||||
for (const line of style.split('\n')) {
|
||||
stylesheet += ` ${line}`;
|
||||
stylesheet += ` ${line}\n`;
|
||||
}
|
||||
|
||||
stylesheet += '}';
|
||||
|
||||
Reference in New Issue
Block a user