feat: add light theme with toggle in settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
xRangerDE 2026-03-20 09:46:26 +01:00
parent 424b312551
commit 63aafae85d
7 changed files with 151 additions and 1 deletions

View File

@ -380,6 +380,7 @@
<option value="discord">Discord</option>
<option value="youtube">YouTube</option>
<option value="apple">Apple</option>
<option value="light" id="themeLightOption">Light</option>
</select>
</div>
<div class="form-group">

View File

@ -3356,7 +3356,7 @@ async function processQueue(): Promise<void> {
// 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<Config>) => {
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<Config>) => {
clearMetadataCaches();
}
if (config.theme !== previousTheme) {
nativeTheme.themeSource = config.theme === 'light' ? 'light' : 'dark';
}
saveConfig(config);
if (config.persist_queue_on_restart === false) {

View File

@ -26,6 +26,7 @@ const UI_TEXT_DE = {
mergeAdd: '+ Videos hinzufugen',
designTitle: 'Design',
themeLabel: 'Theme',
themeLight: 'Hell',
languageLabel: 'Sprache',
languageDe: 'Deutsch',
languageEn: 'Englisch',

View File

@ -26,6 +26,7 @@ const UI_TEXT_EN = {
mergeAdd: '+ Add videos',
designTitle: 'Design',
themeLabel: 'Theme',
themeLight: 'Light',
languageLabel: 'Language',
languageDe: 'German',
languageEn: 'English',

View File

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

View File

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

View File

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