slight visual changes

This commit is contained in:
Eduard Prigoana 2026-02-09 01:00:15 +00:00
parent 003ddc0ab3
commit 9d53abada5
8 changed files with 110 additions and 53 deletions

View file

@ -2095,9 +2095,9 @@
</div>
<div class="theme-picker" id="theme-picker">
<div class="theme-option" data-theme="system">System</div>
<div class="theme-option" data-theme="light">Light</div>
<div class="theme-option" data-theme="dark">Dark</div>
<div class="theme-option" data-theme="monochrome">Black</div>
<div class="theme-option" data-theme="white">White</div>
<div class="theme-option" data-theme="dark">Dark</div>
<div class="theme-option" data-theme="ocean">Ocean</div>
<div class="theme-option" data-theme="purple">Purple</div>
<div class="theme-option" data-theme="forest">Forest</div>
@ -2132,7 +2132,8 @@
<div id="font-preset-section" class="font-section">
<select id="font-preset-select">
<option value="Inter">Inter (Default)</option>
<option value="IBM Plex Mono">IBM Plex Mono (Default)</option>
<option value="Inter">Inter</option>
<option value="Roboto">Roboto</option>
<option value="Open Sans">Open Sans</option>
<option value="Lato">Lato</option>
@ -2218,6 +2219,19 @@
<span class="slider"></span>
</label>
</div>
<div class="setting-item">
<div class="info">
<span class="label">Dynamic Colors</span>
<span class="description"
>Automatically change the app accent color based on the currently playing
track's album art</span
>
</div>
<label class="toggle-switch">
<input type="checkbox" id="dynamic-color-toggle" checked />
<span class="slider"></span>
</label>
</div>
<div class="setting-item">
<div class="info">
<span class="label">Full-screen Visualizer</span>

View file

@ -5,6 +5,7 @@ import {
nowPlayingSettings,
lyricsSettings,
backgroundSettings,
dynamicColorSettings,
cardSettings,
waveformSettings,
replayGainSettings,
@ -779,6 +780,19 @@ export function initializeSettings(scrobbler, player, api, ui) {
});
}
// Dynamic Color Toggle
const dynamicColorToggle = document.getElementById('dynamic-color-toggle');
if (dynamicColorToggle) {
dynamicColorToggle.checked = dynamicColorSettings.isEnabled();
dynamicColorToggle.addEventListener('change', (e) => {
dynamicColorSettings.setEnabled(e.target.checked);
if (!e.target.checked) {
// Reset colors immediately when disabled
window.dispatchEvent(new CustomEvent('reset-dynamic-color'));
}
});
}
// Waveform Toggle
const waveformToggle = document.getElementById('waveform-toggle');
if (waveformToggle) {

View file

@ -237,7 +237,7 @@ export const themeManager = {
if (theme === 'system') {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', isDark ? 'dark' : 'white');
} else {
document.documentElement.setAttribute('data-theme', theme);
}
@ -371,6 +371,23 @@ export const backgroundSettings = {
},
};
export const dynamicColorSettings = {
STORAGE_KEY: 'dynamic-color-enabled',
isEnabled() {
try {
// Default to true if not set
return localStorage.getItem(this.STORAGE_KEY) !== 'false';
} catch {
return true;
}
},
setEnabled(enabled) {
localStorage.setItem(this.STORAGE_KEY, enabled ? 'true' : 'false');
},
};
export const cardSettings = {
COMPACT_ARTIST_KEY: 'card-compact-artist',
COMPACT_ALBUM_KEY: 'card-compact-album',
@ -1155,7 +1172,7 @@ export const sidebarSectionSettings = {
if (typeof window !== 'undefined' && window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (themeManager.getTheme() === 'system') {
document.documentElement.setAttribute('data-theme', e.matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', e.matches ? 'dark' : 'white');
}
});
}
@ -1168,10 +1185,10 @@ export const fontSettings = {
getDefaultConfig() {
return {
type: 'preset',
family: 'Inter',
fallback: 'sans-serif',
weights: [400, 500, 600, 700, 800],
type: 'google',
family: 'IBM Plex Mono',
fallback: 'monospace',
weights: [100, 200, 300, 400, 500, 600, 700],
};
},

View file

@ -23,9 +23,11 @@ import { openLyricsPanel } from './lyrics.js';
import {
recentActivityManager,
backgroundSettings,
dynamicColorSettings,
cardSettings,
visualizerSettings,
homePageSettings,
fontSettings,
} from './storage.js';
import { db } from './db.js';
import { getVibrantColorFromImage } from './vibrant-color.js';
@ -42,7 +44,6 @@ import {
createProjectCardHTML,
createTrackFromSong,
} from './tracker.js';
import { fontSettings } from './storage.js';
fontSettings.applyFont();
@ -85,6 +86,11 @@ export class UIRenderer {
this.searchAbortController = null;
this.vibrantColorCache = new Map();
this.visualizer = null;
// Listen for dynamic color reset events
window.addEventListener('reset-dynamic-color', () => {
this.resetVibrantColor();
});
}
// Helper for Heart Icon
@ -96,7 +102,13 @@ export class UIRenderer {
}
async extractAndApplyColor(url) {
if (!backgroundSettings.isEnabled() || !url) {
if (!url) {
this.resetVibrantColor();
return;
}
// Check if dynamic coloring is enabled
if (!dynamicColorSettings.isEnabled()) {
this.resetVibrantColor();
return;
}
@ -695,7 +707,7 @@ export class UIRenderer {
const root = document.documentElement;
const theme = root.getAttribute('data-theme');
const isLightMode = theme === 'light';
const isLightMode = theme === 'white';
let hex = color.replace('#', '');
// Handle shorthand hex

View file

@ -190,7 +190,7 @@ export class LCDPreset {
const { kick, primaryColor, mode } = params;
this.primaryColor = primaryColor;
const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
const isDark = document.documentElement.getAttribute('data-theme') !== 'white';
// --- Background ---
ctx.clearRect(0, 0, width, height);

View file

@ -18,7 +18,7 @@ export class ParticlesPreset {
const { width, height } = canvas;
const { kick, intensity, primaryColor, mode } = params;
const sensitivity = params.sensitivity || 1.0;
const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
const isDark = document.documentElement.getAttribute('data-theme') !== 'white';
// Clear background
ctx.clearRect(0, 0, width, height);

View file

@ -457,7 +457,7 @@ export class UnknownPleasuresWebGL {
draw(ctx, canvas, analyser, dataArray, params) {
const gl = ctx;
const { width, height } = canvas;
const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
const isDark = document.documentElement.getAttribute('data-theme') !== 'white';
// Set CSS blend mode based on mode and theme
// Solid: normal (opaque background)

View file

@ -43,23 +43,23 @@
:root[data-theme='monochrome'] {
color-scheme: dark;
--background: #000;
--foreground: #fafafa;
--card: #111;
--card-foreground: #fafafa;
--primary: #fafafa;
--primary-foreground: #111;
--secondary: #27272a;
--secondary-foreground: #fafafa;
--muted: #27272a;
--muted-foreground: #a1a1aa;
--border: #27272a;
--input: #27272a;
--ring: #fafafa;
--highlight: #fff;
--highlight-rgb: 255, 255, 255;
--background: #0a0a0a;
--foreground: #f5f5f5;
--card: #141414;
--card-foreground: #f5f5f5;
--primary: #f5f5f5;
--primary-foreground: #0a0a0a;
--secondary: #1f1f1f;
--secondary-foreground: #e0e0e0;
--muted: #1f1f1f;
--muted-foreground: #a0a0a0;
--border: #2a2a2a;
--input: #1f1f1f;
--ring: #f5f5f5;
--highlight: #f5f5f5;
--highlight-rgb: 245, 245, 245;
--active-highlight: var(--highlight);
--explicit-badge: #fafafa;
--explicit-badge: #f5f5f5;
}
:root[data-theme='dark'] {
@ -231,33 +231,33 @@
--muted-foreground: #6c6f85;
--border: #ccd0da;
--input: #bcc0cc;
--ring: #1e66f5;
--ring: #fdfdfd;
--highlight: #1e66f5;
--highlight-rgb: #7287fd;
--active-highlight: #7287fd;
--explicit-badge: #df8e1d;
}
:root[data-theme='light'] {
:root[data-theme='white'] {
color-scheme: light;
--background: #fff;
--foreground: #000;
--card: #f4f4f5;
--card-foreground: #000;
--primary: #2563eb;
--primary-foreground: #fff;
--secondary: #e4e4e7;
--secondary-foreground: #000;
--muted: #e4e4e7;
--muted-foreground: #62626a;
--border: #e4e4e7;
--input: #e4e4e7;
--ring: #2563eb;
--highlight: #2563eb;
--highlight-rgb: 37, 99, 235;
--background: #f5f5f5;
--foreground: #1a1a1a;
--card: #e8e8e8;
--card-foreground: #1a1a1a;
--primary: #1a1a1a;
--primary-foreground: #f5f5f5;
--secondary: #ddd;
--secondary-foreground: #2a2a2a;
--muted: #e0e0e0;
--muted-foreground: #555;
--border: #ccc;
--input: #e0e0e0;
--ring: #1a1a1a;
--highlight: #1a1a1a;
--highlight-rgb: 26, 26, 26;
--active-highlight: var(--highlight);
--explicit-badge: #f58a8a;
--explicit-badge: #1a1a1a;
--cover-filter: blur(50px) brightness(1.6) opacity(0.35);
}
@ -268,7 +268,7 @@
margin: 0;
padding: 0;
-webkit-tap-highlight-color: transparent;
font-family: var(--font-family, 'Inter', sans-serif) !important;
font-family: var(--font-family, 'IBM Plex Mono', monospace) !important;
}
html {
@ -281,7 +281,7 @@ html {
body {
background-color: var(--background);
color: var(--foreground);
font-family: var(--font-family, 'Inter', sans-serif) !important;
font-family: var(--font-family, 'IBM Plex Mono', monospace) !important;
overflow: hidden;
transition:
background-color 0.3s ease,
@ -391,7 +391,7 @@ kbd {
}
/* Light mode adjustments */
:root[data-theme='light'] #page-background {
:root[data-theme='white'] #page-background {
mask-image: linear-gradient(to bottom, rgb(0, 0, 0, 1) 0%, rgb(0, 0, 0, 0) 100%);
}
@ -423,7 +423,7 @@ kbd {
animation: slide-up var(--transition-slow) var(--ease-out-back);
}
:root[data-theme='light'] .now-playing-bar {
:root[data-theme='white'] .now-playing-bar {
background-color: color-mix(in srgb, var(--card) 80%, transparent);
border-color: rgb(0, 0, 0, 0.1);
}