mirror of
https://github.com/zen-browser/components.git
synced 2025-07-07 23:49:58 +02:00
Refactor gradient changer location and add support for per workspace gradients and animations
This commit is contained in:
parent
4a5809f950
commit
c0aae7a2ee
1 changed files with 121 additions and 23 deletions
|
@ -9,8 +9,14 @@
|
||||||
currentRotation = 45;
|
currentRotation = 45;
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
if (!Services.prefs.getBoolPref('zen.theme.gradient', true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ChromeUtils.defineLazyGetter(this, 'panel', () => document.getElementById('PanelUI-zen-gradient-generator'));
|
ChromeUtils.defineLazyGetter(this, 'panel', () => document.getElementById('PanelUI-zen-gradient-generator'));
|
||||||
ChromeUtils.defineLazyGetter(this, 'toolbox', () => document.getElementById('TabsToolbar'));
|
ChromeUtils.defineLazyGetter(this, 'toolbox', () => document.getElementById('TabsToolbar'));
|
||||||
|
ChromeUtils.defineLazyGetter(this, 'customColorInput', () => document.getElementById('PanelUI-zen-gradient-generator-custom-input'));
|
||||||
|
ChromeUtils.defineLazyGetter(this, 'customColorList', () => document.getElementById('PanelUI-zen-gradient-generator-custom-list'));
|
||||||
|
|
||||||
this.initRotation();
|
this.initRotation();
|
||||||
this.initCanvas();
|
this.initCanvas();
|
||||||
|
@ -92,7 +98,7 @@
|
||||||
onRotationMouseDown(event) {
|
onRotationMouseDown(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.rotationDragging = true;
|
this.rotationDragging = true;
|
||||||
this.rotationInputDot.style.zIndex = 1;
|
this.rotationInputDot.style.zIndex = 2;
|
||||||
this.rotationInputDot.classList.add('dragging');
|
this.rotationInputDot.classList.add('dragging');
|
||||||
document.addEventListener('mousemove', this.onRotationMouseMove.bind(this));
|
document.addEventListener('mousemove', this.onRotationMouseMove.bind(this));
|
||||||
document.addEventListener('mouseup', this.onRotationMouseUp.bind(this));
|
document.addEventListener('mouseup', this.onRotationMouseUp.bind(this));
|
||||||
|
@ -100,7 +106,7 @@
|
||||||
|
|
||||||
onRotationMouseUp(event) {
|
onRotationMouseUp(event) {
|
||||||
this.rotationDragging = false;
|
this.rotationDragging = false;
|
||||||
this.rotationInputDot.style.zIndex = 0;
|
this.rotationInputDot.style.zIndex = 1;
|
||||||
this.rotationInputDot.classList.remove('dragging');
|
this.rotationInputDot.classList.remove('dragging');
|
||||||
document.removeEventListener('mousemove', this.onRotationMouseMove.bind(this));
|
document.removeEventListener('mousemove', this.onRotationMouseMove.bind(this));
|
||||||
document.removeEventListener('mouseup', this.onRotationMouseUp.bind(this));
|
document.removeEventListener('mouseup', this.onRotationMouseUp.bind(this));
|
||||||
|
@ -149,7 +155,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateInitialPosition(color) {
|
calculateInitialPosition(color) {
|
||||||
const [r, g, b] = color;
|
const [r, g, b] = color.c;
|
||||||
const imageData = this.canvasCtx.getImageData(0, 0, this.canvas.width, this.canvas.height);
|
const imageData = this.canvasCtx.getImageData(0, 0, this.canvas.width, this.canvas.height);
|
||||||
const pixels = imageData.data;
|
const pixels = imageData.data;
|
||||||
let x = 0;
|
let x = 0;
|
||||||
|
@ -176,14 +182,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
createDot(color, fromWorkspace = false) {
|
createDot(color, fromWorkspace = false) {
|
||||||
const [r, g, b] = color;
|
if (color.isCustom) {
|
||||||
|
this.addColorToCustomList(color.c);
|
||||||
|
}
|
||||||
|
const [r, g, b] = color.c;
|
||||||
const dot = document.createElement('div');
|
const dot = document.createElement('div');
|
||||||
dot.classList.add('zen-theme-picker-dot');
|
dot.classList.add('zen-theme-picker-dot');
|
||||||
dot.style.setProperty('--zen-theme-picker-dot-color', `rgb(${r}, ${g}, ${b})`);
|
if (color.isCustom) {
|
||||||
const { x, y } = this.calculateInitialPosition(color);
|
if (!color.c) {
|
||||||
dot.style.left = `${x * 100}%`;
|
return;
|
||||||
dot.style.top = `${y * 100}%`;
|
}
|
||||||
dot.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
dot.classList.add('custom');
|
||||||
|
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);
|
||||||
|
dot.style.left = `${x * 100}%`;
|
||||||
|
dot.style.top = `${y * 100}%`;
|
||||||
|
dot.addEventListener('mousedown', this.onDotMouseDown.bind(this));
|
||||||
|
}
|
||||||
this.panel.querySelector('.zen-theme-picker-gradient').appendChild(dot);
|
this.panel.querySelector('.zen-theme-picker-gradient').appendChild(dot);
|
||||||
if (!fromWorkspace) {
|
if (!fromWorkspace) {
|
||||||
this.onDarkModeChange(null, true);
|
this.onDarkModeChange(null, true);
|
||||||
|
@ -231,9 +249,38 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addColorToCustomList(color) {
|
||||||
|
const listItems = window.MozXULElement.parseXULToFragment(`
|
||||||
|
<hbox class="zen-theme-picker-custom-list-item">
|
||||||
|
<html:div class="zen-theme-picker-dot-custom"></html:div>
|
||||||
|
<label class="zen-theme-picker-custom-list-item-label"></label>
|
||||||
|
<toolbarbutton class="zen-theme-picker-custom-list-item-remove toolbarbutton-1" oncommand="gZenThemePicker.removeCustomColor(event);"></toolbarbutton>
|
||||||
|
</hbox>
|
||||||
|
`);
|
||||||
|
listItems.querySelector('.zen-theme-picker-custom-list-item').setAttribute('data-color', color);
|
||||||
|
listItems.querySelector('.zen-theme-picker-dot-custom').style.setProperty('--zen-theme-picker-dot-color', color);
|
||||||
|
listItems.querySelector('.zen-theme-picker-custom-list-item-label').textContent = color;
|
||||||
|
this.customColorList.appendChild(listItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
async addCustomColor() {
|
||||||
|
const color = this.customColorInput.value;
|
||||||
|
if (!color) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// can be any color format, we just add it to the list as a dot, but hidden
|
||||||
|
const dot = document.createElement('div');
|
||||||
|
dot.classList.add('zen-theme-picker-dot', 'hidden', 'custom');
|
||||||
|
dot.style.opacity = 0;
|
||||||
|
dot.style.setProperty('--zen-theme-picker-dot-color', color);
|
||||||
|
this.panel.querySelector('.zen-theme-picker-gradient').appendChild(dot);
|
||||||
|
this.customColorInput.value = '';
|
||||||
|
await this.updateCurrentWorkspace();
|
||||||
|
}
|
||||||
|
|
||||||
onDotMouseUp(event) {
|
onDotMouseUp(event) {
|
||||||
if (event.button === 2) {
|
if (event.button === 2) {
|
||||||
if (this.numberOfDots <= 2 || !event.target.classList.contains('zen-theme-picker-dot')
|
if (this.numberOfDots < 2 || !event.target.classList.contains('zen-theme-picker-dot')
|
||||||
|| this.numberOfDots === 1) {
|
|| this.numberOfDots === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -244,14 +291,14 @@
|
||||||
if (this.dragging) {
|
if (this.dragging) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.dragging = false;
|
this.dragging = false;
|
||||||
this.draggedDot.style.zIndex = 0;
|
this.draggedDot.style.zIndex = 1;
|
||||||
this.draggedDot.classList.remove('dragging');
|
this.draggedDot.classList.remove('dragging');
|
||||||
this.draggedDot = null;
|
this.draggedDot = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length;
|
this.numberOfDots = this.panel.querySelectorAll('.zen-theme-picker-dot').length;
|
||||||
if (this.numberOfDots < ZenThemePicker.MAX_DOTS) {
|
if (this.numberOfDots < ZenThemePicker.MAX_DOTS) {
|
||||||
this.createDot([Math.random() * 255, Math.random() * 255, Math.random() * 255]);
|
this.createDot({c:[Math.random() * 255, Math.random() * 255, Math.random() * 255]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,11 +306,14 @@
|
||||||
const isDarkMode = this.isDarkMode;
|
const isDarkMode = this.isDarkMode;
|
||||||
const factor = isDarkMode ? 0.5 : 1.1;
|
const factor = isDarkMode ? 0.5 : 1.1;
|
||||||
return colors.map(color => {
|
return colors.map(color => {
|
||||||
return [
|
return {
|
||||||
Math.min(255, color[0] * factor),
|
c: color.isCustom ? color.c : [
|
||||||
Math.min(255, color[1] * factor),
|
Math.min(255, color.c[0] * factor),
|
||||||
Math.min(255, color[2] * factor),
|
Math.min(255, color.c[1] * factor),
|
||||||
]
|
Math.min(255, color.c[2] * factor),
|
||||||
|
],
|
||||||
|
isCustom: color.isCustom,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,10 +322,19 @@
|
||||||
this.updateCurrentWorkspace();
|
this.updateCurrentWorkspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
getSingleRGBColor(color) {
|
onTextureChange(event) {
|
||||||
return `color-mix(in srgb, rgb(${color[0]}, ${color[1]}, ${color[2]}) ${this.currentOpacity * 100}%, var(--zen-themed-toolbar-bg) ${(1 - this.currentOpacity) * 100}%)`;
|
this.currentTexture = event.target.value;
|
||||||
|
this.updateCurrentWorkspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getSingleRGBColor(color) {
|
||||||
|
if (color.isCustom) {
|
||||||
|
return color.c;
|
||||||
|
}
|
||||||
|
return `color-mix(in srgb, rgb(${color.c[0]}, ${color.c[1]}, ${color.c[2]}) ${this.currentOpacity * 100}%, var(--zen-themed-toolbar-bg) ${(1 - this.currentOpacity) * 100}%)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
getGradient(colors) {
|
getGradient(colors) {
|
||||||
const themedColors = this.themedColors(colors);
|
const themedColors = this.themedColors(colors);
|
||||||
if (themedColors.length === 1) {
|
if (themedColors.length === 1) {
|
||||||
|
@ -284,15 +343,21 @@
|
||||||
return `linear-gradient(${this.currentRotation}deg, ${themedColors.map(color => this.getSingleRGBColor(color)).join(', ')})`;
|
return `linear-gradient(${this.currentRotation}deg, ${themedColors.map(color => this.getSingleRGBColor(color)).join(', ')})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTheme(colors, opacity = 0.5, rotation = 45) {
|
getTheme(colors, opacity = 0.5, rotation = 45, texture = 0) {
|
||||||
return {
|
return {
|
||||||
type: 'gradient',
|
type: 'gradient',
|
||||||
gradientColors: colors,
|
gradientColors: colors.filter(color => color), // remove undefined
|
||||||
opacity,
|
opacity,
|
||||||
rotation,
|
rotation,
|
||||||
|
texture,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateNoise(texture) {
|
||||||
|
const wrapper = document.getElementById('zen-main-app-wrapper');
|
||||||
|
wrapper.style.setProperty('--zen-grainy-background-opacity', texture);
|
||||||
|
}
|
||||||
|
|
||||||
async onWorkspaceChange(workspace, skipUpdate = false) {
|
async onWorkspaceChange(workspace, skipUpdate = false) {
|
||||||
const uuid = workspace.uuid;
|
const uuid = workspace.uuid;
|
||||||
const theme = await ZenWorkspacesStorage.getWorkspaceTheme(uuid);
|
const theme = await ZenWorkspacesStorage.getWorkspaceTheme(uuid);
|
||||||
|
@ -305,21 +370,50 @@
|
||||||
appWrapepr.removeAttribute('animating');
|
appWrapepr.removeAttribute('animating');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
this.customColorList.innerHTML = '';
|
||||||
if (!theme || theme.type !== 'gradient') {
|
if (!theme || theme.type !== 'gradient') {
|
||||||
document.body.style.removeProperty('--zen-main-browser-background');
|
document.body.style.removeProperty('--zen-main-browser-background');
|
||||||
|
this.updateNoise(0);
|
||||||
|
if (!skipUpdate) {
|
||||||
|
for (const dot of this.panel.querySelectorAll('.zen-theme-picker-dot')) {
|
||||||
|
dot.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.currentOpacity = theme.opacity || 0.5;
|
this.currentOpacity = theme.opacity || 0.5;
|
||||||
this.currentRotation = theme.rotation || 45;
|
this.currentRotation = theme.rotation || 45;
|
||||||
|
this.currentTexture = theme.texture || 0;
|
||||||
document.getElementById('PanelUI-zen-gradient-generator-opacity').value = this.currentOpacity;
|
document.getElementById('PanelUI-zen-gradient-generator-opacity').value = this.currentOpacity;
|
||||||
|
document.getElementById('PanelUI-zen-gradient-generator-texture').value = this.currentTexture;
|
||||||
this.setRotationInput(this.currentRotation);
|
this.setRotationInput(this.currentRotation);
|
||||||
const gradient = this.getGradient(theme.gradientColors);
|
const gradient = this.getGradient(theme.gradientColors);
|
||||||
|
this.updateNoise(theme.texture);
|
||||||
|
for (const dot of theme.gradientColors) {
|
||||||
|
if (dot.isCustom) {
|
||||||
|
this.addColorToCustomList(dot.c);
|
||||||
|
}
|
||||||
|
}
|
||||||
document.body.style.setProperty('--zen-main-browser-background', gradient);
|
document.body.style.setProperty('--zen-main-browser-background', gradient);
|
||||||
if (!skipUpdate) {
|
if (!skipUpdate) {
|
||||||
this.recalculateDots(theme.gradientColors);
|
this.recalculateDots(theme.gradientColors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeCustomColor(event) {
|
||||||
|
const target = event.target.closest('.zen-theme-picker-custom-list-item');
|
||||||
|
const color = target.getAttribute('data-color');
|
||||||
|
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
|
||||||
|
for (const dot of dots) {
|
||||||
|
if (dot.style.getPropertyValue('--zen-theme-picker-dot-color') === color) {
|
||||||
|
dot.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
target.remove();
|
||||||
|
this.updateCurrentWorkspace();
|
||||||
|
}
|
||||||
|
|
||||||
recalculateDots(colors) {
|
recalculateDots(colors) {
|
||||||
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
|
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
|
||||||
for (let i = 0; i < colors.length; i++) {
|
for (let i = 0; i < colors.length; i++) {
|
||||||
|
@ -334,9 +428,13 @@
|
||||||
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
|
const dots = this.panel.querySelectorAll('.zen-theme-picker-dot');
|
||||||
const colors = Array.from(dots).map(dot => {
|
const colors = Array.from(dots).map(dot => {
|
||||||
const color = dot.style.getPropertyValue('--zen-theme-picker-dot-color');
|
const color = dot.style.getPropertyValue('--zen-theme-picker-dot-color');
|
||||||
return color.match(/\d+/g).map(Number);
|
if (color === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const isCustom = dot.classList.contains('custom');
|
||||||
|
return {c: isCustom ? color : color.match(/\d+/g).map(Number), isCustom};
|
||||||
});
|
});
|
||||||
const gradient = this.getTheme(colors, this.currentOpacity, this.currentRotation);
|
const gradient = this.getTheme(colors, this.currentOpacity, this.currentRotation, this.currentTexture);
|
||||||
const currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
|
const currentWorkspace = await ZenWorkspaces.getActiveWorkspace();
|
||||||
await ZenWorkspacesStorage.saveWorkspaceTheme(currentWorkspace.uuid, gradient);
|
await ZenWorkspacesStorage.saveWorkspaceTheme(currentWorkspace.uuid, gradient);
|
||||||
this.onWorkspaceChange(currentWorkspace, true);
|
this.onWorkspaceChange(currentWorkspace, true);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue