From 63aafae85dc185a8363483c58b8fb45a06d14ef6 Mon Sep 17 00:00:00 2001 From: xRangerDE Date: Fri, 20 Mar 2026 09:46:26 +0100 Subject: [PATCH] feat: add light theme with toggle in settings Co-Authored-By: Claude Opus 4.6 (1M context) --- src/index.html | 1 + src/main.ts | 7 +- src/renderer-locale-de.ts | 1 + src/renderer-locale-en.ts | 1 + src/renderer-settings.ts | 1 + src/renderer-texts.ts | 1 + src/styles.css | 140 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/index.html b/src/index.html index b572402..36d4259 100644 --- a/src/index.html +++ b/src/index.html @@ -380,6 +380,7 @@ +
diff --git a/src/main.ts b/src/main.ts index d03e2af..51c31aa 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3356,7 +3356,7 @@ async function processQueue(): Promise { // WINDOW CREATION // ========================================== function createWindow(): void { - nativeTheme.themeSource = 'dark'; + nativeTheme.themeSource = config.theme === 'light' ? 'light' : 'dark'; mainWindow = new BrowserWindow({ width: 1400, @@ -3698,6 +3698,7 @@ ipcMain.handle('save-config', (_, newConfig: Partial) => { const previousClientSecret = config.client_secret; const previousCacheMinutes = config.metadata_cache_minutes; const previousPersistQueueOnRestart = config.persist_queue_on_restart; + const previousTheme = config.theme; config = normalizeConfigTemplates({ ...config, ...newConfig }); @@ -3710,6 +3711,10 @@ ipcMain.handle('save-config', (_, newConfig: Partial) => { clearMetadataCaches(); } + if (config.theme !== previousTheme) { + nativeTheme.themeSource = config.theme === 'light' ? 'light' : 'dark'; + } + saveConfig(config); if (config.persist_queue_on_restart === false) { diff --git a/src/renderer-locale-de.ts b/src/renderer-locale-de.ts index f717a44..b0a87b3 100644 --- a/src/renderer-locale-de.ts +++ b/src/renderer-locale-de.ts @@ -26,6 +26,7 @@ const UI_TEXT_DE = { mergeAdd: '+ Videos hinzufugen', designTitle: 'Design', themeLabel: 'Theme', + themeLight: 'Hell', languageLabel: 'Sprache', languageDe: 'Deutsch', languageEn: 'Englisch', diff --git a/src/renderer-locale-en.ts b/src/renderer-locale-en.ts index 1616758..3d2315c 100644 --- a/src/renderer-locale-en.ts +++ b/src/renderer-locale-en.ts @@ -26,6 +26,7 @@ const UI_TEXT_EN = { mergeAdd: '+ Add videos', designTitle: 'Design', themeLabel: 'Theme', + themeLight: 'Light', languageLabel: 'Language', languageDe: 'German', languageEn: 'English', diff --git a/src/renderer-settings.ts b/src/renderer-settings.ts index b680818..594bd47 100644 --- a/src/renderer-settings.ts +++ b/src/renderer-settings.ts @@ -582,5 +582,6 @@ function openFolder(): void { function changeTheme(theme: string): void { document.body.className = `theme-${theme}`; + config.theme = theme; void window.api.saveConfig({ theme }); } diff --git a/src/renderer-texts.ts b/src/renderer-texts.ts index e291396..58c8b9d 100644 --- a/src/renderer-texts.ts +++ b/src/renderer-texts.ts @@ -68,6 +68,7 @@ function applyLanguageToStaticUI(): void { setText('mergeAddBtn', UI_TEXT.static.mergeAdd); setText('designTitle', UI_TEXT.static.designTitle); setText('themeLabel', UI_TEXT.static.themeLabel); + setText('themeLightOption', UI_TEXT.static.themeLight); setText('languageLabel', UI_TEXT.static.languageLabel); setText('languageDeText', UI_TEXT.static.languageDe); setText('languageEnText', UI_TEXT.static.languageEn); diff --git a/src/styles.css b/src/styles.css index 2736870..3c5d2eb 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1346,6 +1346,146 @@ body.theme-apple { --accent-hover: #0071e3; } +body.theme-light { + --bg-main: #f0f2f5; + --bg-sidebar: #ffffff; + --bg-card: #e4e6ea; + --text: #1a1a2e; + --text-secondary: #65676b; + --accent: #9146ff; + --accent-hover: #772ce8; + --success: #00c853; + --error: #e41e3f; + --warning: #e68a00; +} + +/* Light theme: swap white-alpha borders/backgrounds to black-alpha */ +body.theme-light .sidebar, +body.theme-light .queue-section, +body.theme-light .logo, +body.theme-light .stats-bar, +body.theme-light .header, +body.theme-light .status-bar { + border-color: rgba(0,0,0,0.1); +} + +body.theme-light .add-streamer input, +body.theme-light .form-group input:not([type="checkbox"]):not([type="radio"]), +body.theme-light .form-group select, +body.theme-light .clip-input input, +body.theme-light .time-input-group input, +body.theme-light .part-number-group input, +body.theme-light .btn-secondary, +body.theme-light .lang-option, +body.theme-light .log-panel, +body.theme-light .template-guide-table-wrap, +body.theme-light .template-guide-preview-box { + border-color: rgba(0,0,0,0.12); +} + +body.theme-light .lang-option:hover { + border-color: rgba(0,0,0,0.26); +} + +body.theme-light .streamer-item:hover { + background: rgba(0,0,0,0.05); +} + +body.theme-light .vod-btn.secondary { + background: rgba(0,0,0,0.08); +} + +body.theme-light .vod-btn.secondary:hover { + background: rgba(0,0,0,0.12); +} + +body.theme-light .nav-item:hover { + background: rgba(145, 71, 255, 0.1); +} + +body.theme-light ::-webkit-scrollbar-thumb { + background: rgba(0,0,0,0.15); +} + +body.theme-light ::-webkit-scrollbar-thumb:hover { + background: rgba(0,0,0,0.25); +} + +body.theme-light .update-modal { + border-color: rgba(0,0,0,0.1); + background: + linear-gradient(180deg, rgba(145, 70, 255, 0.12) 0%, rgba(145, 70, 255, 0.03) 24%, rgba(240, 242, 245, 0.98) 100%), + var(--bg-card); +} + +body.theme-light .update-modal-eyebrow { + color: #4a2a8a; +} + +body.theme-light .update-changelog-card { + border-color: rgba(0,0,0,0.08); + background: rgba(255, 255, 255, 0.6); +} + +body.theme-light .update-changelog-header { + border-bottom-color: rgba(0,0,0,0.06); +} + +body.theme-light .update-changelog-toggle { + color: #4a2a8a; +} + +body.theme-light .update-changelog-toggle:hover { + color: #1a1a2e; +} + +body.theme-light .update-changelog-heading, +body.theme-light .update-changelog-content strong { + color: #1a1a2e; +} + +body.theme-light .template-guide-preview-box { + background: rgba(0, 0, 0, 0.04); +} + +body.theme-light .template-guide-output { + background: rgba(0, 0, 0, 0.06); +} + +body.theme-light .template-guide-table th, +body.theme-light .template-guide-table td { + border-bottom-color: rgba(0,0,0,0.08); +} + +body.theme-light .log-panel { + background: #f8f9fb; + color: #2c3e50; +} + +body.theme-light .app-toast { + background: rgba(255, 255, 255, 0.96); + color: #1a1a2e; + border-color: rgba(0,0,0,0.12); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +body.theme-light .btn-retry { + background: #dce4f0; + color: #2a3344; +} + +body.theme-light .btn-retry:hover { + background: #c8d4e8; +} + +body.theme-light .btn-clear:hover { + background: #d0d2d6; +} + +body.theme-light .modal { + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); +} + /* Modal Styles */ .modal-overlay { position: fixed;