Refactor gradient changer location and add support for per workspace gradients and animations

This commit is contained in:
mr. M 2024-10-26 11:56:39 +02:00
parent 4a5809f950
commit c0aae7a2ee
No known key found for this signature in database
GPG key ID: CBD57A2AEDBDA1FB

View file

@ -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);