feat(electrobun): wire persistence — SQLite, 17 themes, font system
Persistence: - bun:sqlite at ~/.config/agor/settings.db (WAL mode, 500ms busy_timeout) - 4 tables: schema_version, settings, projects, custom_themes - 5 RPC handlers: settings.get/set/getAll, projects get/set Theme system (LIVE switching): - All 17 themes ported from Tauri (4 Catppuccin + 7 Editor + 6 Deep Dark) - applyCssVars() sets 26 --ctp-* vars on document.documentElement - Parallel xterm ITheme mapping per theme - theme-store.svelte.ts: Svelte 5 rune store, persists to SQLite Font system: - font-store.svelte.ts: UI/terminal font family + size - Live CSS var application (--ui-font-family/size, --term-font-family/size) - onTermFontChange() callback registry for terminal instances - Persists all 4 font settings to SQLite AppearanceSettings wired: 17-theme grouped dropdown, font steppers Init on startup: restores saved theme + fonts from SQLite
This commit is contained in:
parent
0b9e8b305a
commit
6002a379e4
13 changed files with 1043 additions and 53 deletions
86
ui-electrobun/src/mainview/theme-store.svelte.ts
Normal file
86
ui-electrobun/src/mainview/theme-store.svelte.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Svelte 5 rune-based theme store.
|
||||
* Applies all 26 --ctp-* CSS vars to document.documentElement instantly.
|
||||
* Persists selection via settings RPC.
|
||||
*
|
||||
* Usage:
|
||||
* import { themeStore } from './theme-store.svelte';
|
||||
* themeStore.setTheme('tokyo-night');
|
||||
* await themeStore.initTheme(rpc);
|
||||
*/
|
||||
|
||||
import { applyCssVars, THEME_LIST, type ThemeId } from "./themes.ts";
|
||||
|
||||
const SETTING_KEY = "theme";
|
||||
const DEFAULT_THEME: ThemeId = "mocha";
|
||||
|
||||
// ── Minimal RPC interface ─────────────────────────────────────────────────────
|
||||
// Avoids importing the full Electroview class — just the subset we need.
|
||||
|
||||
interface SettingsRpc {
|
||||
request: {
|
||||
"settings.get"(p: { key: string }): Promise<{ value: string | null }>;
|
||||
"settings.set"(p: { key: string; value: string }): Promise<{ ok: boolean }>;
|
||||
};
|
||||
}
|
||||
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
function isValidThemeId(id: string): id is ThemeId {
|
||||
return THEME_LIST.some((t) => t.id === id);
|
||||
}
|
||||
|
||||
// ── Store ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
function createThemeStore() {
|
||||
let currentThemeId = $state<ThemeId>(DEFAULT_THEME);
|
||||
let rpc: SettingsRpc | null = null;
|
||||
|
||||
/** Apply CSS vars immediately — synchronous, no flash. */
|
||||
function applyToDocument(id: ThemeId): void {
|
||||
applyCssVars(id);
|
||||
currentThemeId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the active theme.
|
||||
* Applies CSS vars immediately and persists asynchronously.
|
||||
*/
|
||||
function setTheme(id: ThemeId): void {
|
||||
applyToDocument(id);
|
||||
if (rpc) {
|
||||
rpc.request["settings.set"]({ key: SETTING_KEY, value: id }).catch((err) => {
|
||||
console.error("[theme-store] Failed to persist theme:", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load persisted theme from settings on startup.
|
||||
* Call once in App.svelte onMount.
|
||||
*/
|
||||
async function initTheme(rpcInstance: SettingsRpc): Promise<void> {
|
||||
rpc = rpcInstance;
|
||||
try {
|
||||
const result = await rpc.request["settings.get"]({ key: SETTING_KEY });
|
||||
const saved = result.value;
|
||||
if (saved && isValidThemeId(saved)) {
|
||||
applyToDocument(saved);
|
||||
} else {
|
||||
// Apply default to ensure vars are set even when nothing was persisted.
|
||||
applyToDocument(DEFAULT_THEME);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[theme-store] Failed to load theme from settings:", err);
|
||||
applyToDocument(DEFAULT_THEME);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
get currentTheme() { return currentThemeId; },
|
||||
setTheme,
|
||||
initTheme,
|
||||
};
|
||||
}
|
||||
|
||||
export const themeStore = createThemeStore();
|
||||
Loading…
Add table
Add a link
Reference in a new issue