+
{:else}
{/if}
diff --git a/apps/tauri/src/app.css b/apps/tauri/src/app.css
index ec6380a..2e94fc4 100644
--- a/apps/tauri/src/app.css
+++ b/apps/tauri/src/app.css
@@ -68,3 +68,68 @@ body {
background-color: #242424;
color: #e5e7eb;
}
+
+/* ── Theme overrides ─────────────────────────────────────────────── */
+
+[data-theme="dark"] {
+ --color-primary: #2d87b8;
+ --color-primary-hover: #2474a0;
+ --color-surface-light: #242424;
+ --color-surface-dark: #242424;
+ --color-card-light: #303030;
+ --color-card-dark: #303030;
+ --color-text-light: #e5e7eb;
+ --color-text-dark: #e5e7eb;
+ --color-text-secondary-light: #9ca3af;
+ --color-text-secondary-dark: #9ca3af;
+ --color-border-light: #3d3d3d;
+ --color-border-dark: #3d3d3d;
+}
+
+[data-theme="nord"] {
+ --color-primary: #88c0d0;
+ --color-primary-hover: #7ab3c3;
+ --color-surface-light: #2e3440;
+ --color-surface-dark: #2e3440;
+ --color-card-light: #3b4252;
+ --color-card-dark: #3b4252;
+ --color-text-light: #eceff4;
+ --color-text-dark: #eceff4;
+ --color-text-secondary-light: #d8dee9;
+ --color-text-secondary-dark: #d8dee9;
+ --color-border-light: #434c5e;
+ --color-border-dark: #434c5e;
+ --color-danger: #bf616a;
+}
+
+[data-theme="dracula"] {
+ --color-primary: #bd93f9;
+ --color-primary-hover: #a87ef0;
+ --color-surface-light: #282a36;
+ --color-surface-dark: #282a36;
+ --color-card-light: #343746;
+ --color-card-dark: #343746;
+ --color-text-light: #f8f8f2;
+ --color-text-dark: #f8f8f2;
+ --color-text-secondary-light: #bfbfbf;
+ --color-text-secondary-dark: #bfbfbf;
+ --color-border-light: #44475a;
+ --color-border-dark: #44475a;
+ --color-danger: #ff5555;
+}
+
+[data-theme="solarized"] {
+ --color-primary: #268bd2;
+ --color-primary-hover: #1e7ac0;
+ --color-surface-light: #002b36;
+ --color-surface-dark: #002b36;
+ --color-card-light: #073642;
+ --color-card-dark: #073642;
+ --color-text-light: #93a1a1;
+ --color-text-dark: #93a1a1;
+ --color-text-secondary-light: #657b83;
+ --color-text-secondary-dark: #657b83;
+ --color-border-light: #094959;
+ --color-border-dark: #094959;
+ --color-danger: #dc322f;
+}
diff --git a/apps/tauri/src/lib/stores/app.svelte.ts b/apps/tauri/src/lib/stores/app.svelte.ts
index fd42e50..b23e8b7 100644
--- a/apps/tauri/src/lib/stores/app.svelte.ts
+++ b/apps/tauri/src/lib/stores/app.svelte.ts
@@ -20,9 +20,7 @@ let config = $state
(null);
let lists = $state([]);
let activeListId = $state(null);
let tasks = $state([]);
-let darkMode = $state(
- globalThis.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false,
-);
+let osDark = globalThis.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
let syncing = $state(false);
let syncMode = $state<"full" | "push" | "pull">("full");
let lastSyncResult = $state(null);
@@ -56,6 +54,16 @@ let hasWorkspace = $derived(
Object.keys(config.workspaces).length > 0,
);
+const DARK_THEMES = new Set(["dark", "nord", "dracula", "solarized"]);
+let currentTheme = $derived(
+ config?.current_workspace
+ ? config.workspaces[config.current_workspace]?.theme ?? null
+ : null,
+);
+let isDark = $derived(
+ currentTheme ? DARK_THEMES.has(currentTheme) : osDark,
+);
+
// ── Actions ──────────────────────────────────────────────────────────
async function loadConfig() {
@@ -311,8 +319,31 @@ function setSyncMode(mode: "full" | "push" | "pull") {
syncMode = mode;
}
-function toggleDarkMode() {
- darkMode = !darkMode;
+async function setTheme(theme: string | null) {
+ if (!config?.current_workspace) return;
+ try {
+ await invoke("set_workspace_theme", {
+ workspaceName: config.current_workspace,
+ theme,
+ });
+ config = await invoke("get_config");
+ } catch (e) {
+ error = String(e);
+ }
+}
+
+async function addWebdavWorkspace(name: string, webdavUrl: string, username: string, password: string) {
+ try {
+ await invoke("add_webdav_workspace", { name, webdavUrl, username, password });
+ config = await invoke("get_config");
+ await loadLists();
+ const ws = config?.workspaces[name];
+ if (ws) invoke("watch_workspace", { path: ws.path }).catch((e) => console.warn("File watcher failed:", e));
+ screen = "tasks";
+ error = null;
+ } catch (e) {
+ error = String(e);
+ }
}
function setScreen(s: Screen) {
@@ -350,8 +381,11 @@ export const app = {
get completedTasks() {
return completedTasks;
},
- get darkMode() {
- return darkMode;
+ get currentTheme() {
+ return currentTheme;
+ },
+ get isDark() {
+ return isDark;
},
get syncing() {
return syncing;
@@ -388,7 +422,8 @@ export const app = {
setGroupByDueDate,
triggerSync,
setSyncMode,
- toggleDarkMode,
+ setTheme,
+ addWebdavWorkspace,
setScreen,
clearError,
};