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
|
|
@ -231861,6 +231861,105 @@ class PtyClient extends EventEmitter2 {
|
|||
}
|
||||
}
|
||||
|
||||
// src/bun/settings-db.ts
|
||||
import { Database as Database2 } from "bun:sqlite";
|
||||
import { homedir as homedir3 } from "os";
|
||||
import { mkdirSync as mkdirSync2 } from "fs";
|
||||
import { join as join7 } from "path";
|
||||
var CONFIG_DIR = join7(homedir3(), ".config", "agor");
|
||||
var DB_PATH = join7(CONFIG_DIR, "settings.db");
|
||||
var SCHEMA = `
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA busy_timeout = 500;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS schema_version (
|
||||
version INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
config TEXT NOT NULL -- JSON blob
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS custom_themes (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
palette TEXT NOT NULL -- JSON blob
|
||||
);
|
||||
`;
|
||||
|
||||
class SettingsDb {
|
||||
db;
|
||||
constructor() {
|
||||
mkdirSync2(CONFIG_DIR, { recursive: true });
|
||||
this.db = new Database2(DB_PATH);
|
||||
this.db.exec(SCHEMA);
|
||||
const version = this.db.query("SELECT version FROM schema_version LIMIT 1").get();
|
||||
if (!version) {
|
||||
this.db.exec("INSERT INTO schema_version (version) VALUES (1)");
|
||||
}
|
||||
}
|
||||
getSetting(key) {
|
||||
const row = this.db.query("SELECT value FROM settings WHERE key = ?").get(key);
|
||||
return row?.value ?? null;
|
||||
}
|
||||
setSetting(key, value) {
|
||||
this.db.query("INSERT INTO settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(key, value);
|
||||
}
|
||||
getAll() {
|
||||
const rows = this.db.query("SELECT key, value FROM settings").all();
|
||||
return Object.fromEntries(rows.map((r) => [r.key, r.value]));
|
||||
}
|
||||
getProject(id) {
|
||||
const row = this.db.query("SELECT config FROM projects WHERE id = ?").get(id);
|
||||
if (!row)
|
||||
return null;
|
||||
try {
|
||||
return JSON.parse(row.config);
|
||||
} catch {
|
||||
console.error(`[settings-db] Failed to parse project config for id=${id}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
setProject(id, config) {
|
||||
const json = JSON.stringify(config);
|
||||
this.db.query("INSERT INTO projects (id, config) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET config = excluded.config").run(id, json);
|
||||
}
|
||||
listProjects() {
|
||||
const rows = this.db.query("SELECT config FROM projects").all();
|
||||
return rows.flatMap((r) => {
|
||||
try {
|
||||
return [JSON.parse(r.config)];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
getCustomThemes() {
|
||||
const rows = this.db.query("SELECT id, name, palette FROM custom_themes").all();
|
||||
return rows.flatMap((r) => {
|
||||
try {
|
||||
return [{ id: r.id, name: r.name, palette: JSON.parse(r.palette) }];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
saveCustomTheme(id, name531, palette) {
|
||||
const json = JSON.stringify(palette);
|
||||
this.db.query("INSERT INTO custom_themes (id, name, palette) VALUES (?, ?, ?) ON CONFLICT(id) DO UPDATE SET name = excluded.name, palette = excluded.palette").run(id, name531, json);
|
||||
}
|
||||
close() {
|
||||
this.db.close();
|
||||
}
|
||||
}
|
||||
var settingsDb = new SettingsDb;
|
||||
|
||||
// src/bun/index.ts
|
||||
var DEV_SERVER_PORT = 9760;
|
||||
var DEV_SERVER_URL = `http://localhost:${DEV_SERVER_PORT}`;
|
||||
|
|
@ -231932,6 +232031,53 @@ var rpc = BrowserView.defineRPC({
|
|||
ptyClient.closeSession(sessionId);
|
||||
} catch {}
|
||||
return { ok: true };
|
||||
},
|
||||
"settings.get": ({ key }) => {
|
||||
try {
|
||||
return { value: settingsDb.getSetting(key) };
|
||||
} catch (err) {
|
||||
console.error("[settings.get]", err);
|
||||
return { value: null };
|
||||
}
|
||||
},
|
||||
"settings.set": ({ key, value }) => {
|
||||
try {
|
||||
settingsDb.setSetting(key, value);
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
console.error("[settings.set]", err);
|
||||
return { ok: false };
|
||||
}
|
||||
},
|
||||
"settings.getAll": () => {
|
||||
try {
|
||||
return { settings: settingsDb.getAll() };
|
||||
} catch (err) {
|
||||
console.error("[settings.getAll]", err);
|
||||
return { settings: {} };
|
||||
}
|
||||
},
|
||||
"settings.getProjects": () => {
|
||||
try {
|
||||
const projects = settingsDb.listProjects().map((p) => ({
|
||||
id: p.id,
|
||||
config: JSON.stringify(p)
|
||||
}));
|
||||
return { projects };
|
||||
} catch (err) {
|
||||
console.error("[settings.getProjects]", err);
|
||||
return { projects: [] };
|
||||
}
|
||||
},
|
||||
"settings.setProject": ({ id, config }) => {
|
||||
try {
|
||||
const parsed = JSON.parse(config);
|
||||
settingsDb.setProject(id, { id, ...parsed });
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
console.error("[settings.setProject]", err);
|
||||
return { ok: false };
|
||||
}
|
||||
}
|
||||
},
|
||||
messages: {}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -4,8 +4,8 @@
|
|||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Svelte App</title>
|
||||
<script type="module" crossorigin src="/assets/index-I2iZIyVf.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-x9Y0o9Mz.css">
|
||||
<script type="module" crossorigin src="/assets/index-CZZnRPP5.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DSZtflYD.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue