slight visual changes
This commit is contained in:
parent
003ddc0ab3
commit
9d53abada5
8 changed files with 110 additions and 53 deletions
20
index.html
20
index.html
|
|
@ -2095,9 +2095,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="theme-picker" id="theme-picker">
|
<div class="theme-picker" id="theme-picker">
|
||||||
<div class="theme-option" data-theme="system">System</div>
|
<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="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="ocean">Ocean</div>
|
||||||
<div class="theme-option" data-theme="purple">Purple</div>
|
<div class="theme-option" data-theme="purple">Purple</div>
|
||||||
<div class="theme-option" data-theme="forest">Forest</div>
|
<div class="theme-option" data-theme="forest">Forest</div>
|
||||||
|
|
@ -2132,7 +2132,8 @@
|
||||||
|
|
||||||
<div id="font-preset-section" class="font-section">
|
<div id="font-preset-section" class="font-section">
|
||||||
<select id="font-preset-select">
|
<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="Roboto">Roboto</option>
|
||||||
<option value="Open Sans">Open Sans</option>
|
<option value="Open Sans">Open Sans</option>
|
||||||
<option value="Lato">Lato</option>
|
<option value="Lato">Lato</option>
|
||||||
|
|
@ -2218,6 +2219,19 @@
|
||||||
<span class="slider"></span>
|
<span class="slider"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</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="setting-item">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span class="label">Full-screen Visualizer</span>
|
<span class="label">Full-screen Visualizer</span>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
nowPlayingSettings,
|
nowPlayingSettings,
|
||||||
lyricsSettings,
|
lyricsSettings,
|
||||||
backgroundSettings,
|
backgroundSettings,
|
||||||
|
dynamicColorSettings,
|
||||||
cardSettings,
|
cardSettings,
|
||||||
waveformSettings,
|
waveformSettings,
|
||||||
replayGainSettings,
|
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
|
// Waveform Toggle
|
||||||
const waveformToggle = document.getElementById('waveform-toggle');
|
const waveformToggle = document.getElementById('waveform-toggle');
|
||||||
if (waveformToggle) {
|
if (waveformToggle) {
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ export const themeManager = {
|
||||||
|
|
||||||
if (theme === 'system') {
|
if (theme === 'system') {
|
||||||
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
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 {
|
} else {
|
||||||
document.documentElement.setAttribute('data-theme', theme);
|
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 = {
|
export const cardSettings = {
|
||||||
COMPACT_ARTIST_KEY: 'card-compact-artist',
|
COMPACT_ARTIST_KEY: 'card-compact-artist',
|
||||||
COMPACT_ALBUM_KEY: 'card-compact-album',
|
COMPACT_ALBUM_KEY: 'card-compact-album',
|
||||||
|
|
@ -1155,7 +1172,7 @@ export const sidebarSectionSettings = {
|
||||||
if (typeof window !== 'undefined' && window.matchMedia) {
|
if (typeof window !== 'undefined' && window.matchMedia) {
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||||||
if (themeManager.getTheme() === 'system') {
|
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() {
|
getDefaultConfig() {
|
||||||
return {
|
return {
|
||||||
type: 'preset',
|
type: 'google',
|
||||||
family: 'Inter',
|
family: 'IBM Plex Mono',
|
||||||
fallback: 'sans-serif',
|
fallback: 'monospace',
|
||||||
weights: [400, 500, 600, 700, 800],
|
weights: [100, 200, 300, 400, 500, 600, 700],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
18
js/ui.js
18
js/ui.js
|
|
@ -23,9 +23,11 @@ import { openLyricsPanel } from './lyrics.js';
|
||||||
import {
|
import {
|
||||||
recentActivityManager,
|
recentActivityManager,
|
||||||
backgroundSettings,
|
backgroundSettings,
|
||||||
|
dynamicColorSettings,
|
||||||
cardSettings,
|
cardSettings,
|
||||||
visualizerSettings,
|
visualizerSettings,
|
||||||
homePageSettings,
|
homePageSettings,
|
||||||
|
fontSettings,
|
||||||
} from './storage.js';
|
} from './storage.js';
|
||||||
import { db } from './db.js';
|
import { db } from './db.js';
|
||||||
import { getVibrantColorFromImage } from './vibrant-color.js';
|
import { getVibrantColorFromImage } from './vibrant-color.js';
|
||||||
|
|
@ -42,7 +44,6 @@ import {
|
||||||
createProjectCardHTML,
|
createProjectCardHTML,
|
||||||
createTrackFromSong,
|
createTrackFromSong,
|
||||||
} from './tracker.js';
|
} from './tracker.js';
|
||||||
import { fontSettings } from './storage.js';
|
|
||||||
|
|
||||||
fontSettings.applyFont();
|
fontSettings.applyFont();
|
||||||
|
|
||||||
|
|
@ -85,6 +86,11 @@ export class UIRenderer {
|
||||||
this.searchAbortController = null;
|
this.searchAbortController = null;
|
||||||
this.vibrantColorCache = new Map();
|
this.vibrantColorCache = new Map();
|
||||||
this.visualizer = null;
|
this.visualizer = null;
|
||||||
|
|
||||||
|
// Listen for dynamic color reset events
|
||||||
|
window.addEventListener('reset-dynamic-color', () => {
|
||||||
|
this.resetVibrantColor();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper for Heart Icon
|
// Helper for Heart Icon
|
||||||
|
|
@ -96,7 +102,13 @@ export class UIRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async extractAndApplyColor(url) {
|
async extractAndApplyColor(url) {
|
||||||
if (!backgroundSettings.isEnabled() || !url) {
|
if (!url) {
|
||||||
|
this.resetVibrantColor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if dynamic coloring is enabled
|
||||||
|
if (!dynamicColorSettings.isEnabled()) {
|
||||||
this.resetVibrantColor();
|
this.resetVibrantColor();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -695,7 +707,7 @@ export class UIRenderer {
|
||||||
|
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
const theme = root.getAttribute('data-theme');
|
const theme = root.getAttribute('data-theme');
|
||||||
const isLightMode = theme === 'light';
|
const isLightMode = theme === 'white';
|
||||||
|
|
||||||
let hex = color.replace('#', '');
|
let hex = color.replace('#', '');
|
||||||
// Handle shorthand hex
|
// Handle shorthand hex
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ export class LCDPreset {
|
||||||
const { kick, primaryColor, mode } = params;
|
const { kick, primaryColor, mode } = params;
|
||||||
|
|
||||||
this.primaryColor = primaryColor;
|
this.primaryColor = primaryColor;
|
||||||
const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
|
const isDark = document.documentElement.getAttribute('data-theme') !== 'white';
|
||||||
|
|
||||||
// --- Background ---
|
// --- Background ---
|
||||||
ctx.clearRect(0, 0, width, height);
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export class ParticlesPreset {
|
||||||
const { width, height } = canvas;
|
const { width, height } = canvas;
|
||||||
const { kick, intensity, primaryColor, mode } = params;
|
const { kick, intensity, primaryColor, mode } = params;
|
||||||
const sensitivity = params.sensitivity || 1.0;
|
const sensitivity = params.sensitivity || 1.0;
|
||||||
const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
|
const isDark = document.documentElement.getAttribute('data-theme') !== 'white';
|
||||||
|
|
||||||
// Clear background
|
// Clear background
|
||||||
ctx.clearRect(0, 0, width, height);
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@ export class UnknownPleasuresWebGL {
|
||||||
draw(ctx, canvas, analyser, dataArray, params) {
|
draw(ctx, canvas, analyser, dataArray, params) {
|
||||||
const gl = ctx;
|
const gl = ctx;
|
||||||
const { width, height } = canvas;
|
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
|
// Set CSS blend mode based on mode and theme
|
||||||
// Solid: normal (opaque background)
|
// Solid: normal (opaque background)
|
||||||
|
|
|
||||||
76
styles.css
76
styles.css
|
|
@ -43,23 +43,23 @@
|
||||||
:root[data-theme='monochrome'] {
|
:root[data-theme='monochrome'] {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
|
|
||||||
--background: #000;
|
--background: #0a0a0a;
|
||||||
--foreground: #fafafa;
|
--foreground: #f5f5f5;
|
||||||
--card: #111;
|
--card: #141414;
|
||||||
--card-foreground: #fafafa;
|
--card-foreground: #f5f5f5;
|
||||||
--primary: #fafafa;
|
--primary: #f5f5f5;
|
||||||
--primary-foreground: #111;
|
--primary-foreground: #0a0a0a;
|
||||||
--secondary: #27272a;
|
--secondary: #1f1f1f;
|
||||||
--secondary-foreground: #fafafa;
|
--secondary-foreground: #e0e0e0;
|
||||||
--muted: #27272a;
|
--muted: #1f1f1f;
|
||||||
--muted-foreground: #a1a1aa;
|
--muted-foreground: #a0a0a0;
|
||||||
--border: #27272a;
|
--border: #2a2a2a;
|
||||||
--input: #27272a;
|
--input: #1f1f1f;
|
||||||
--ring: #fafafa;
|
--ring: #f5f5f5;
|
||||||
--highlight: #fff;
|
--highlight: #f5f5f5;
|
||||||
--highlight-rgb: 255, 255, 255;
|
--highlight-rgb: 245, 245, 245;
|
||||||
--active-highlight: var(--highlight);
|
--active-highlight: var(--highlight);
|
||||||
--explicit-badge: #fafafa;
|
--explicit-badge: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme='dark'] {
|
:root[data-theme='dark'] {
|
||||||
|
|
@ -231,33 +231,33 @@
|
||||||
--muted-foreground: #6c6f85;
|
--muted-foreground: #6c6f85;
|
||||||
--border: #ccd0da;
|
--border: #ccd0da;
|
||||||
--input: #bcc0cc;
|
--input: #bcc0cc;
|
||||||
--ring: #1e66f5;
|
--ring: #fdfdfd;
|
||||||
--highlight: #1e66f5;
|
--highlight: #1e66f5;
|
||||||
--highlight-rgb: #7287fd;
|
--highlight-rgb: #7287fd;
|
||||||
--active-highlight: #7287fd;
|
--active-highlight: #7287fd;
|
||||||
--explicit-badge: #df8e1d;
|
--explicit-badge: #df8e1d;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme='light'] {
|
:root[data-theme='white'] {
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
|
|
||||||
--background: #fff;
|
--background: #f5f5f5;
|
||||||
--foreground: #000;
|
--foreground: #1a1a1a;
|
||||||
--card: #f4f4f5;
|
--card: #e8e8e8;
|
||||||
--card-foreground: #000;
|
--card-foreground: #1a1a1a;
|
||||||
--primary: #2563eb;
|
--primary: #1a1a1a;
|
||||||
--primary-foreground: #fff;
|
--primary-foreground: #f5f5f5;
|
||||||
--secondary: #e4e4e7;
|
--secondary: #ddd;
|
||||||
--secondary-foreground: #000;
|
--secondary-foreground: #2a2a2a;
|
||||||
--muted: #e4e4e7;
|
--muted: #e0e0e0;
|
||||||
--muted-foreground: #62626a;
|
--muted-foreground: #555;
|
||||||
--border: #e4e4e7;
|
--border: #ccc;
|
||||||
--input: #e4e4e7;
|
--input: #e0e0e0;
|
||||||
--ring: #2563eb;
|
--ring: #1a1a1a;
|
||||||
--highlight: #2563eb;
|
--highlight: #1a1a1a;
|
||||||
--highlight-rgb: 37, 99, 235;
|
--highlight-rgb: 26, 26, 26;
|
||||||
--active-highlight: var(--highlight);
|
--active-highlight: var(--highlight);
|
||||||
--explicit-badge: #f58a8a;
|
--explicit-badge: #1a1a1a;
|
||||||
--cover-filter: blur(50px) brightness(1.6) opacity(0.35);
|
--cover-filter: blur(50px) brightness(1.6) opacity(0.35);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,7 +268,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-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 {
|
html {
|
||||||
|
|
@ -281,7 +281,7 @@ html {
|
||||||
body {
|
body {
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
font-family: var(--font-family, 'Inter', sans-serif) !important;
|
font-family: var(--font-family, 'IBM Plex Mono', monospace) !important;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition:
|
transition:
|
||||||
background-color 0.3s ease,
|
background-color 0.3s ease,
|
||||||
|
|
@ -391,7 +391,7 @@ kbd {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Light mode adjustments */
|
/* 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%);
|
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);
|
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);
|
background-color: color-mix(in srgb, var(--card) 80%, transparent);
|
||||||
border-color: rgb(0, 0, 0, 0.1);
|
border-color: rgb(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue