1
0
Fork 1
mirror of https://github.com/zen-browser/desktop.git synced 2025-07-07 21:49:58 +02:00

feat: Improve contrast slider, b=no-bug, c=mods, workspaces

This commit is contained in:
mr. m 2025-06-24 04:03:25 +02:00
parent f27df1a5bd
commit 7c57254da7
No known key found for this signature in database
GPG key ID: 928E01ED4C97749F
6 changed files with 220 additions and 60 deletions

View file

@ -5,20 +5,6 @@
<panel flip="side" type="arrow" popupalign="center" orient="vertical" id="PanelUI-zen-gradient-generator" position="bottomright topright" mainview="true" side="left"> <panel flip="side" type="arrow" popupalign="center" orient="vertical" id="PanelUI-zen-gradient-generator" position="bottomright topright" mainview="true" side="left">
<panelmultiview id="PanelUI-zen-gradient-generator-multiview" mainViewId="PanelUI-zen-gradient-generator-view"> <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"> <panelview id="PanelUI-zen-gradient-generator-view" class="PanelUI-subView zen-theme-picker" role="document" mainview-with-header="true" has-custom-header="true">
<hbox>
<hbox id="PanelUI-zen-gradient-generator-predefined">
<box data-lightness="00" data-algo="analogous" data-num-dots="3" data-position="219,99" style="background: linear-gradient(135deg, rgb(117, 255, 136), rgb(60, 66, 58));"></box>
<box data-lightness="10" data-algo="analogous" data-num-dots="3" data-position="167,201" style="background: linear-gradient(135deg, #a03fe0, #382b5c);"></box>
<box data-lightness="20" data-algo="analogous" data-num-dots="3" data-position="90,170" style="background: linear-gradient(135deg, #c57aa3, #af824f);"></box>
<box data-lightness="30" data-algo="splitComplementary" data-num-dots="3" data-position="83,103" style="background: linear-gradient(135deg, #1e90ff, #968a4a);"></box>
<box data-lightness="40" data-algo="analogous" data-num-dots="3" data-position="186,186" style="background: linear-gradient(135deg, #a07a48, #ab80e4);"></box>
<box data-lightness="50" data-algo="float" data-num-dots="1" data-position="196,176" style="background: #7bcbda;"></box>
<box data-lightness="60" data-algo="float" data-num-dots="1" data-position="116,167" style="background: #be9ac9;"></box>
<box data-lightness="70" data-algo="float" data-num-dots="1" data-position="122,110" style="background: #cdcea1;"></box>
<box data-lightness="80" data-algo="float" data-num-dots="1" data-position="181,83" style="background: #6ac593;"></box>
<box data-lightness="150" data-algo="complementary" data-num-dots="2" data-position="82,112" style="background: linear-gradient(135deg, #1e90ff, #cfb179);"></box>
</hbox>
</hbox>
<hbox class="zen-theme-picker-gradient"> <hbox class="zen-theme-picker-gradient">
<hbox id="PanelUI-zen-gradient-generator-scheme"> <hbox id="PanelUI-zen-gradient-generator-scheme">
<button id="PanelUI-zen-gradient-generator-scheme-auto" class="subviewbutton"/> <button id="PanelUI-zen-gradient-generator-scheme-auto" class="subviewbutton"/>
@ -36,10 +22,40 @@
</hbox> </hbox>
<label data-l10n-id="zen-panel-ui-gradient-click-to-add" id="PanelUI-zen-gradient-generator-color-click-to-add"></label> <label data-l10n-id="zen-panel-ui-gradient-click-to-add" id="PanelUI-zen-gradient-generator-color-click-to-add"></label>
</hbox> </hbox>
<hbox>
<hbox id="PanelUI-zen-gradient-generator-predefined">
<box data-lightness="90" data-algo="float" data-num-dots="1" data-position="196,176" style="background: #7bcbda;"></box>
<box data-lightness="80" data-algo="float" data-num-dots="1" data-position="116,167" style="background: #be9ac9;"></box>
<box data-lightness="70" data-algo="float" data-num-dots="1" data-position="122,110" style="background: #cdcea1;"></box>
<box data-lightness="60" data-algo="float" data-num-dots="1" data-position="181,83" style="background: #6ac593;"></box>
<box data-lightness="50" data-algo="analogous" data-num-dots="3" data-position="219,99" style="background: linear-gradient(135deg, rgb(117, 255, 136), rgb(60, 66, 58));"></box>
<box data-lightness="40" data-algo="analogous" data-num-dots="3" data-position="167,201" style="background: linear-gradient(135deg, #a03fe0, #382b5c);"></box>
<box data-lightness="30" data-algo="analogous" data-num-dots="3" data-position="90,170" style="background: linear-gradient(135deg, #c57aa3, #af824f);"></box>
<box data-lightness="20" data-algo="splitComplementary" data-num-dots="3" data-position="83,103" style="background: linear-gradient(135deg, #1e90ff, #968a4a);"></box>
<box data-lightness="10" data-algo="analogous" data-num-dots="3" data-position="186,186" style="background: linear-gradient(135deg, #a07a48, #ab80e4);"></box>
<box data-lightness="150" data-algo="complementary" data-num-dots="2" data-position="82,112" style="background: linear-gradient(135deg, #1e90ff, #cfb179);"></box>
</hbox>
</hbox>
<hbox id="PanelUI-zen-gradient-generator-controls"> <hbox id="PanelUI-zen-gradient-generator-controls">
<hbox id="PanelUI-zen-gradient-colors-wrapper"> <hbox id="PanelUI-zen-gradient-colors-wrapper">
<vbox flex="1"> <vbox flex="1" id="PanelUI-zen-gradient-opacity-wrapper">
<html:input type="range" min="0.15" max="0.85" value="0.5" step="0.05" id="PanelUI-zen-gradient-generator-opacity" /> <box id="PanelUI-zen-gradient-slider-wave">
<svg viewBox="0 -2.5 455 70" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMid meet">
<path d="M 51.373 27.395 L 419.634 27.395"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
style="stroke-width: 11px;"/>
<defs>
<linearGradient id="PanelUI-zen-gradient-generator-slider-wave-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="light-dark(rgb(77, 77, 77), rgb(161, 161, 161))"/>
<stop offset="0%" stop-color="light-dark(rgba(77, 77, 77), rgba(161, 161, 161))"/>
<stop offset="100%" stop-color="light-dark(rgba(77, 77, 77, 0.5), rgba(161, 161, 161, 0.5))"/>
</linearGradient>
</defs>
</svg>
</box>
<html:input type="range" min="0.15" max="0.85" value="0.5" step="0.01" id="PanelUI-zen-gradient-generator-opacity" />
</vbox> </vbox>
<vbox id="PanelUI-zen-gradient-generator-texture-wrapper"> <vbox id="PanelUI-zen-gradient-generator-texture-wrapper">
</vbox> </vbox>

View file

@ -775,7 +775,10 @@
@media -moz-pref('zen.theme.window.scheme', 'auto') { @media -moz-pref('zen.theme.window.scheme', 'auto') {
#PanelUI-zen-gradient-generator-scheme-auto { #PanelUI-zen-gradient-generator-scheme-auto {
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.2)); /** Can't use rgba here because of the background image, provide a solid, gray
* background for the auto scheme in dark mode.
*/
background: light-dark(#edebeb, rgb(106, 106, 106));
} }
} }
@ -785,7 +788,7 @@
@media -moz-pref('zen.theme.window.scheme', 'dark') { @media -moz-pref('zen.theme.window.scheme', 'dark') {
#PanelUI-zen-gradient-generator-scheme-dark { #PanelUI-zen-gradient-generator-scheme-dark {
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.2)); background: light-dark(#edebeb, rgb(106, 106, 106));
} }
} }
@ -795,6 +798,6 @@
@media -moz-pref('zen.theme.window.scheme', 'light') { @media -moz-pref('zen.theme.window.scheme', 'light') {
#PanelUI-zen-gradient-generator-scheme-light { #PanelUI-zen-gradient-generator-scheme-light {
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.2)); background: light-dark(#edebeb, rgb(106, 106, 106));
} }
} }

View file

@ -0,0 +1,13 @@
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
index c4627621344d35081f11a7b0e03d02eca2097609..d2e5fe429aaac8b701a03380a67f4ea978d566b3 100644
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -7376,7 +7376,7 @@ - (id)initWithContentRect:(NSRect)aContentRect
// Returns an autoreleased NSImage.
static NSImage* GetMenuMaskImage() {
- const CGFloat radius = 6.0f;
+ const CGFloat radius = 14.0f;
const NSSize maskSize = {radius * 3.0f, radius * 3.0f};
NSImage* maskImage = [NSImage imageWithSize:maskSize
flipped:FALSE

View file

@ -49,7 +49,11 @@
} }
async #insertStylesheet() { async #insertStylesheet() {
this.#modsBackend.rebuildModsStyles(); try {
this.#modsBackend.rebuildModsStyles();
} catch (e) {
console.warn('[ZenMods]: Error rebuilding mods styles:', e);
}
} }
async #rebuildModsStylesheet() { async #rebuildModsStylesheet() {

View file

@ -3,6 +3,43 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
{ {
function parseSinePath(pathStr) {
const points = [];
const commands = pathStr.match(/[MCL]\s*[\d\s\.\-,]+/g);
if (!commands) return points;
commands.forEach((command) => {
const type = command.charAt(0);
const coordsStr = command.slice(1).trim();
const coords = coordsStr.split(/[\s,]+/).map(Number);
switch (type) {
case 'M':
points.push({ x: coords[0], y: coords[1], type: 'M' });
break;
case 'C':
if (coords.length >= 6 && coords.length % 6 === 0) {
for (let i = 0; i < coords.length; i += 6) {
points.push({
x1: coords[i],
y1: coords[i + 1],
x2: coords[i + 2],
y2: coords[i + 3],
x: coords[i + 4],
y: coords[i + 5],
type: 'C',
});
}
}
break;
case 'L':
points.push({ x: coords[0], y: coords[1], type: 'L' });
break;
}
});
return points;
}
class nsZenThemePicker extends ZenMultiWindowFeature { class nsZenThemePicker extends ZenMultiWindowFeature {
static MAX_DOTS = 3; static MAX_DOTS = 3;
@ -13,6 +50,11 @@
#allowTransparencyOnSidebar = Services.prefs.getBoolPref('zen.theme.acrylic-elements', false); #allowTransparencyOnSidebar = Services.prefs.getBoolPref('zen.theme.acrylic-elements', false);
#linePath = `M 51.373 27.395 L 419.634 27.395`;
#sinePath = `M 51.373 31.629 C 60.14 -4.265 68.906 -4.265 77.671 31.629 C 86.438 67.527 95.205 67.527 103.971 31.629 C 112.738 -4.265 121.504 -4.265 130.271 31.629 C 139.037 67.527 147.803 67.527 156.57 31.629 C 165.335 -4.265 174.101 -4.265 182.868 31.629 C 191.634 67.527 200.4 67.527 209.167 31.629 C 217.933 -4.265 226.7 -4.265 235.467 31.629 C 244.233 67.527 252.999 67.527 261.765 31.629 C 270.531 -4.265 279.297 -4.265 288.064 31.629 C 296.83 67.527 305.596 67.527 314.363 31.629 C 323.13 -4.265 331.896 -4.265 340.662 31.629 M 314.438 31.629 C 323.204 -4.265 331.97 -4.265 340.737 31.629 C 349.503 67.527 358.27 67.527 367.037 31.629 C 375.802 -4.265 384.568 -4.265 393.335 31.629 C 402.101 67.527 410.867 67.527 419.634 31.629`;
#sinePoints = parseSinePath(this.#sinePath);
constructor() { constructor() {
super(); super();
if ( if (
@ -38,6 +80,10 @@
document.getElementById('PanelUI-zen-gradient-generator-custom-list') document.getElementById('PanelUI-zen-gradient-generator-custom-list')
); );
ChromeUtils.defineLazyGetter(this, 'sliderWavePath', () =>
document.getElementById('PanelUI-zen-gradient-slider-wave').querySelector('path')
);
this.panel.addEventListener('popupshowing', this.handlePanelOpen.bind(this)); this.panel.addEventListener('popupshowing', this.handlePanelOpen.bind(this));
this.panel.addEventListener('popuphidden', this.handlePanelClose.bind(this)); this.panel.addEventListener('popuphidden', this.handlePanelClose.bind(this));
this.panel.addEventListener('command', this.handlePanelCommand.bind(this)); this.panel.addEventListener('command', this.handlePanelCommand.bind(this));
@ -349,24 +395,11 @@
const centerX = rect.width / 2; const centerX = rect.width / 2;
const centerY = rect.height / 2; const centerY = rect.height / 2;
const radius = (rect.width - padding) / 2; const radius = (rect.width - padding) / 2;
const [hue, saturation] = this.rgbToHsl(r, g, b);
// Convert RGB to HSL const angle = (hue / 360) * 2 * Math.PI; // Convert to radians
const [h, s, l] = this.rgbToHsl(r, g, b); const normalizedSaturation = saturation / 100; // Convert to [0, 1]
const x = centerX + radius * normalizedSaturation * Math.cos(angle) - padding;
// We assume lightness is fixed; if not, add a warning or threshold check const y = centerY + radius * normalizedSaturation * Math.sin(angle) - padding;
// const targetLightness = this.#currentLightness / 100;
// if (Math.abs(l - targetLightness) > 0.01) return null;
// Convert hue (0-1) to angle in radians
const angleRad = (h * 360 * Math.PI) / 180;
// Convert saturation to radial distance
const distance = (1 - s) * radius;
// Convert polar to cartesian
const x = centerX + Math.cos(angleRad) * distance;
const y = centerY + Math.sin(angleRad) * distance;
return { x, y }; return { x, y };
} }
@ -960,7 +993,7 @@
onOpacityChange(event) { onOpacityChange(event) {
this.currentOpacity = parseFloat(event.target.value); this.currentOpacity = parseFloat(event.target.value);
// If we reached a whole number (e.g., 0.1, 0.2, etc.), send a haptic feedback // If we reached a whole number (e.g., 0.1, 0.2, etc.), send a haptic feedback
if (Math.round(this.currentOpacity % 0.1) === 0) { if ((this.currentOpacity * 10) % 1 === 0) {
Services.zen.playHapticFeedback(); Services.zen.playHapticFeedback();
} }
this.updateCurrentWorkspace(); this.updateCurrentWorkspace();
@ -1324,6 +1357,39 @@
browser.gZenThemePicker.currentOpacity = workspaceTheme.opacity ?? 0.5; browser.gZenThemePicker.currentOpacity = workspaceTheme.opacity ?? 0.5;
browser.gZenThemePicker.currentTexture = workspaceTheme.texture ?? 0; browser.gZenThemePicker.currentTexture = workspaceTheme.texture ?? 0;
const opacitySlider = browser.document.getElementById(
'PanelUI-zen-gradient-generator-opacity'
);
{
let opacity = browser.gZenThemePicker.currentOpacity;
const svg = browser.gZenThemePicker.sliderWavePath;
const stepSize = 0.05;
opacity = Math.floor(opacity / stepSize) * stepSize;
// Opacity can only be between 0.15 to 0.85. Make opacity relative to that range
// So 0.15 becomes 0, and 0.85 becomes 1.
if (opacity < 0.15) {
opacity = 0;
} else if (opacity > 0.85) {
opacity = 1;
} else {
opacity = (opacity - 0.15) / (0.85 - 0.15);
}
svg.setAttribute('d', this.#interpolateWavePath(opacity));
const [_, secondStop, thirdStop] = document.querySelectorAll(
'#PanelUI-zen-gradient-generator-slider-wave-gradient stop'
);
opacity += 0.025; // add a little bit of opacity so it doesn't look clipped
secondStop.setAttribute('offset', `${opacity * 100}%`);
thirdStop.setAttribute('offset', `${opacity * 100}%`);
svg.style.stroke =
opacity < 0.1
? thirdStop.getAttribute('stop-color')
: 'url(#PanelUI-zen-gradient-generator-slider-wave-gradient)';
opacitySlider.style.setProperty('--zen-thumb-height', `${40 + opacity * 10}px`);
opacitySlider.style.setProperty('--zen-thumb-width', `${10 + opacity * 10}px`);
}
for (const button of browser.document.querySelectorAll( for (const button of browser.document.querySelectorAll(
'#PanelUI-zen-gradient-generator-color-actions button' '#PanelUI-zen-gradient-generator-color-actions button'
)) { )) {
@ -1338,8 +1404,7 @@
.getElementById('PanelUI-zen-gradient-generator-color-click-to-add') .getElementById('PanelUI-zen-gradient-generator-color-click-to-add')
.toggleAttribute('hidden', workspaceTheme.gradientColors.length > 0); .toggleAttribute('hidden', workspaceTheme.gradientColors.length > 0);
browser.document.getElementById('PanelUI-zen-gradient-generator-opacity').value = opacitySlider.value = browser.gZenThemePicker.currentOpacity;
browser.gZenThemePicker.currentOpacity;
const textureSelectWrapper = browser.document.getElementById( const textureSelectWrapper = browser.document.getElementById(
'PanelUI-zen-gradient-generator-texture-wrapper' 'PanelUI-zen-gradient-generator-texture-wrapper'
); );
@ -1528,6 +1593,37 @@
this.updateCurrentWorkspace(); this.updateCurrentWorkspace();
}, 200); }, 200);
} }
#interpolateWavePath(progress) {
const linePath = this.#linePath;
const sinePath = this.#sinePath;
const referenceY = 27.3;
if (this.#sinePoints.length === 0) {
return progress < 0.5 ? linePath : sinePath;
}
if (progress <= 0.001) return linePath;
if (progress >= 0.999) return sinePath;
const t = progress;
let newPathData = '';
this.#sinePoints.forEach((p) => {
switch (p.type) {
case 'M':
const interpolatedY = referenceY + (p.y - referenceY) * t;
newPathData += `M ${p.x} ${interpolatedY} `;
break;
case 'C':
const y1 = referenceY + (p.y1 - referenceY) * t;
const y2 = referenceY + (p.y2 - referenceY) * t;
const y = referenceY + (p.y - referenceY) * t;
newPathData += `C ${p.x1} ${y1} ${p.x2} ${y2} ${p.x} ${y} `;
break;
case 'L':
newPathData += `L ${p.x} ${p.y} `;
break;
}
});
return newPathData.trim();
}
} }
window.nsZenThemePicker = nsZenThemePicker; window.nsZenThemePicker = nsZenThemePicker;

View file

@ -62,7 +62,11 @@
padding: 0 var(--panel-padding); padding: 0 var(--panel-padding);
@media (-moz-platform: macos) { @media (-moz-platform: macos) {
gap: 3rem; gap: 2rem;
}
#PanelUI-zen-gradient-opacity-wrapper {
position: relative;
} }
& label { & label {
@ -80,7 +84,7 @@
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
align-items: center; align-items: center;
margin: 5px auto 10px auto; margin: 0 auto 25px auto;
width: 100%; width: 100%;
& > box { & > box {
@ -164,31 +168,55 @@
} }
} }
#PanelUI-zen-gradient-generator-opacity, #PanelUI-zen-gradient-slider-wave {
#PanelUI-zen-gradient-generator-texture { position: absolute;
top: 3px;
left: -3px;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
display: flex;
align-items: center;
justify-content: flex-start;
scale: 1.2;
&::before {
content: '';
position: absolute;
width: 100%;
height: 14px;
background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1));
border-radius: 999px;
pointer-events: none;
z-index: -1;
top: -2px;
left: 4px;
scale: 0.85;
}
}
#PanelUI-zen-gradient-generator-opacity {
margin: 0 !important; margin: 0 !important;
margin-top: 5px !important;
background: transparent; background: transparent;
z-index: 2;
&::-moz-range-thumb { &::-moz-range-thumb {
background: var(--zen-colors-tertiary); background: light-dark(black, white);
border: 2px solid var(--zen-colors-border); border-radius: 999px;
border-radius: 12px; height: var(--zen-thumb-height);
height: 25px; width: var(--zen-thumb-width);
width: 13px;
cursor: pointer; cursor: pointer;
border: none;
} }
&::-moz-range-track { &::-moz-range-track {
background: light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.3));
border-radius: 999px; border-radius: 999px;
height: 6px; height: 6px;
} }
&::-moz-range-progress { &::-moz-range-progress {
background: var(--zen-primary-color); background: transparent;
border-radius: 999px;
height: 8px;
} }
} }
@ -273,9 +301,9 @@
min-width: fit-content !important; min-width: fit-content !important;
transition: background 0.2s; transition: background 0.2s;
appearance: none; appearance: none;
max-height: 28px; max-height: 26px;
max-width: 26px;
color: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.9)); color: light-dark(rgba(0, 0, 0, 0.7), rgba(255, 255, 255, 0.9));
backdrop-filter: blur(5px);
& .button-box { & .button-box {
gap: 0.1rem; gap: 0.1rem;
@ -304,6 +332,7 @@
#PanelUI-zen-gradient-generator-scheme { #PanelUI-zen-gradient-generator-scheme {
top: 10px; top: 10px;
max-height: 32px;
} }
@media not -moz-pref('zen.theme.gradient.show-custom-colors') { @media not -moz-pref('zen.theme.gradient.show-custom-colors') {
@ -318,9 +347,8 @@
position: relative; position: relative;
@media (-moz-platform: macos) { @media (-moz-platform: macos) {
width: 25%; width: 5rem;
aspect-ratio: 1; height: 5rem;
height: unset;
} }
&::after { &::after {