Files
cex/frontend/theme.ts
2026-09-07 15:16:52 -04:00

46 lines
2.2 KiB
TypeScript

import { invoke, isTauri } from '@tauri-apps/api/core';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
type Theme = 'system' | 'dark' | 'light';
export function installTheme() {
const media = window.matchMedia('(prefers-color-scheme: dark)');
const select = document.getElementById('theme-select') as HTMLSelectElement;
let preference: Theme = 'system';
let changed = false;
let saves = Promise.resolve();
for (const mode of ['dark', 'light'] as const) {
monaco.editor.defineTheme(`cex-${mode}`, {
base: mode === 'dark' ? 'vs-dark' : 'vs', inherit: true, rules: [],
colors: mode === 'dark' ? {
'editor.background': '#171c23', 'editor.foreground': '#dce3eb',
'editorLineNumber.foreground': '#738195', 'editorLineNumber.activeForeground': '#a4dccb',
'editor.lineHighlightBackground': '#202832', 'editor.selectionBackground': '#31564e',
'editorCursor.foreground': '#83d8bd',
} : {
'editor.background': '#ffffff', 'editor.foreground': '#243347',
'editorLineNumber.foreground': '#788496', 'editorLineNumber.activeForeground': '#176e59',
'editor.lineHighlightBackground': '#f2f6f8', 'editor.selectionBackground': '#c9e6dc',
'editorCursor.foreground': '#176e59',
},
});
}
function apply() {
const mode = preference === 'system' ? (media.matches ? 'dark' : 'light') : preference;
document.documentElement.dataset.theme = mode;
select.value = preference;
monaco.editor.setTheme(`cex-${mode}`);
}
select.onchange = () => {
changed = true; preference = select.value as Theme; apply();
const theme = preference;
if (isTauri()) saves = saves.then(() => invoke('save_theme', { theme })).then(() => {
select.title = 'Color theme';
}).catch(error => { select.title = `Theme applied, but could not save preference: ${String(error)}`; });
};
media.addEventListener('change', () => { if (preference === 'system') apply(); });
apply();
if (isTauri()) void invoke<Theme>('load_theme').then(value => {
if (!changed && ['system', 'dark', 'light'].includes(value)) { preference = value; apply(); }
}).catch(error => { select.title = `Using system theme. Could not load preference: ${String(error)}`; });
}