diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a2158fc..d857e75 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -13,6 +13,7 @@ "dependencies": { "@neo-companion/shared": "workspace:*", "@tauri-apps/api": "^2.9.0", + "@tauri-apps/plugin-dialog": "^2.2.0", "@tiptap/core": "3.26.0", "@tiptap/extension-heading": "3.26.0", "@tiptap/extension-list": "3.26.0", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index d0e7c53..d54f36d 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -15,6 +15,7 @@ tauri-build = { version = "2", features = [] } [dependencies] tauri = { version = "2", features = ["tray-icon"] } tauri-plugin-opener = "2" +tauri-plugin-dialog = "2" tauri-plugin-window-state = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json index f76d964..18538a6 100644 --- a/apps/desktop/src-tauri/capabilities/default.json +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -13,6 +13,7 @@ "core:window:allow-show", "core:window:allow-start-dragging", "opener:default", + "dialog:default", "window-state:default" ] } diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index adb99d8..482f326 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -5,6 +5,7 @@ use tauri::{LogicalSize, Manager, Size, WindowEvent}; pub fn run() { let builder = tauri::Builder::default() .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_window_state::Builder::default().build()); #[cfg(target_os = "windows")] diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index ed65e78..0f231f2 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -35,6 +35,7 @@ import WallpaperView from "./views/WallpaperView.vue"; import SettingsView from "./views/SettingsView.vue"; import KnowledgeView from "./views/KnowledgeView.vue"; import { useSettings } from "./composables/useSettings"; +import { useTheme } from "./composables/useTheme"; const viewMode = new URLSearchParams(window.location.search).get("view"); const isPetView = viewMode === "pet"; @@ -67,7 +68,7 @@ const weather = ref(null); const lastWindow = ref(null); const serverReady = ref(false); const errorText = ref(""); -const isPanelDark = ref(false); +const theme = useTheme(); const activePanelPage = ref("focus"); const wallpaperVisible = ref(true); const focusStartTime = ref(""); @@ -240,7 +241,7 @@ function onTaskToggle(task: typeof tasks.tasks.value[0]) { } function togglePanelTheme() { - isPanelDark.value = !isPanelDark.value; + theme.toggleTheme(); } function setActivePanelPage(pageId: string) { @@ -305,7 +306,7 @@ function toggleImmersive() { -
+
@@ -317,7 +318,7 @@ function toggleImmersive() { diff --git a/apps/desktop/src/api.ts b/apps/desktop/src/api.ts index 35a12d0..1073967 100644 --- a/apps/desktop/src/api.ts +++ b/apps/desktop/src/api.ts @@ -1,4 +1,5 @@ import type { ChatMessage, FocusSession, Task, TtsResult, WeatherSummary, WsMessage } from "@neo-companion/shared"; +import type { BoardColumn, KnowledgeNote, KnowledgeProject, KnowledgeTask, TaskStatus } from "./composables/useKnowledgeMock"; export const API_BASE = import.meta.env.VITE_NEO_SERVER_URL ?? "http://127.0.0.1:10103"; export const WS_BASE = API_BASE.replace(/^http/, "ws"); @@ -32,7 +33,55 @@ export const api = { weather: () => request("/api/weather"), chat: (message: string) => request<{ text: string }>("/api/ai/chat", { method: "POST", body: JSON.stringify({ message }) }), speak: (text: string, style?: string) => - request("/api/tts/speak", { method: "POST", body: JSON.stringify({ text, style }) }) + request("/api/tts/speak", { method: "POST", body: JSON.stringify({ text, style }) }), + + // ── Knowledge workspace ── + knowledgeListProjects: () => request("/api/knowledge/projects?root=1"), + knowledgeChildProjects: (parentId: string) => + request(`/api/knowledge/projects?parentId=${encodeURIComponent(parentId)}`), + knowledgeProjectPath: (id: string) => + request(`/api/knowledge/projects/${encodeURIComponent(id)}/path`), + knowledgeCreateProject: (input: { title: string; parentId?: string | null; description?: string; color?: string; icon?: string }) => + request("/api/knowledge/projects", { method: "POST", body: JSON.stringify(input) }), + knowledgeUpdateProject: (id: string, patch: Partial>) => + request(`/api/knowledge/projects/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(patch) }), + knowledgeDeleteProject: (id: string) => + request(`/api/knowledge/projects/${encodeURIComponent(id)}`, { method: "DELETE" }), + knowledgeListNotes: (projectId: string) => + request(`/api/knowledge/projects/${encodeURIComponent(projectId)}/notes`), + knowledgeCreateNote: (projectId: string, title: string) => + request(`/api/knowledge/projects/${encodeURIComponent(projectId)}/notes`, { method: "POST", body: JSON.stringify({ title }) }), + knowledgeUpdateNote: (id: string, patch: Partial>) => + request(`/api/knowledge/notes/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(patch) }), + knowledgeDeleteNote: (id: string) => + request(`/api/knowledge/notes/${encodeURIComponent(id)}`, { method: "DELETE" }), + knowledgeBacklinks: (id: string) => + request<{ sourceType: "note" | "task"; sourceId: string }[]>(`/api/knowledge/notes/${encodeURIComponent(id)}/backlinks`), + knowledgeListColumns: (projectId: string) => + request(`/api/knowledge/projects/${encodeURIComponent(projectId)}/columns`), + knowledgeCreateColumn: (projectId: string, input: { title: string; status: TaskStatus; order: number }) => + request(`/api/knowledge/projects/${encodeURIComponent(projectId)}/columns`, { method: "POST", body: JSON.stringify(input) }), + knowledgeUpdateColumn: (id: string, patch: Partial>) => + request(`/api/knowledge/columns/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(patch) }), + knowledgeDeleteColumn: (id: string) => + request(`/api/knowledge/columns/${encodeURIComponent(id)}`, { method: "DELETE" }), + knowledgeListTasks: (projectId: string) => + request(`/api/knowledge/projects/${encodeURIComponent(projectId)}/tasks`), + knowledgeCreateTask: (projectId: string, columnId: string, title: string) => + request(`/api/knowledge/projects/${encodeURIComponent(projectId)}/tasks`, { method: "POST", body: JSON.stringify({ columnId, title }) }), + knowledgeUpdateTask: (id: string, patch: Partial> & { linkedNoteId?: string | null }) => + request(`/api/knowledge/tasks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(patch) }), + knowledgeDeleteTask: (id: string) => + request(`/api/knowledge/tasks/${encodeURIComponent(id)}`, { method: "DELETE" }), + knowledgeMoveTask: (id: string, columnId: string, index: number) => + request(`/api/knowledge/tasks/${encodeURIComponent(id)}/move`, { method: "POST", body: JSON.stringify({ columnId, index }) }), + knowledgeGetRootPath: () => request<{ path: string }>("/api/knowledge/root-path"), + knowledgeSetRootPath: (path: string) => + request<{ path: string }>("/api/knowledge/root-path", { method: "PUT", body: JSON.stringify({ path }) }), + knowledgeMirrorExport: (path?: string) => + request<{ projects: number; notes: number; columns: number; tasks: number }>("/api/knowledge/mirror/export", { method: "POST", body: JSON.stringify({ path }) }), + knowledgeMirrorImport: (path?: string) => + request<{ importedProjects: number; importedNotes: number; importedColumns: number; importedTasks: number; skipped: number }>("/api/knowledge/mirror/import", { method: "POST", body: JSON.stringify({ path }) }) }; let activeWs: WebSocket | null = null; diff --git a/apps/desktop/src/components/knowledge/BacklinksPanel.vue b/apps/desktop/src/components/knowledge/BacklinksPanel.vue new file mode 100644 index 0000000..bb0b1e0 --- /dev/null +++ b/apps/desktop/src/components/knowledge/BacklinksPanel.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/apps/desktop/src/components/knowledge/BoardCard.vue b/apps/desktop/src/components/knowledge/BoardCard.vue deleted file mode 100644 index 58ec4f2..0000000 --- a/apps/desktop/src/components/knowledge/BoardCard.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/BoardColumn.vue b/apps/desktop/src/components/knowledge/BoardColumn.vue index 225a0a1..460107b 100644 --- a/apps/desktop/src/components/knowledge/BoardColumn.vue +++ b/apps/desktop/src/components/knowledge/BoardColumn.vue @@ -1,22 +1,159 @@ diff --git a/apps/desktop/src/components/knowledge/BoardPane.vue b/apps/desktop/src/components/knowledge/BoardPane.vue deleted file mode 100644 index d381c35..0000000 --- a/apps/desktop/src/components/knowledge/BoardPane.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/BoardTaskCard.vue b/apps/desktop/src/components/knowledge/BoardTaskCard.vue new file mode 100644 index 0000000..75d6808 --- /dev/null +++ b/apps/desktop/src/components/knowledge/BoardTaskCard.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/desktop/src/components/knowledge/BreadcrumbNav.vue b/apps/desktop/src/components/knowledge/BreadcrumbNav.vue new file mode 100644 index 0000000..9f82e8d --- /dev/null +++ b/apps/desktop/src/components/knowledge/BreadcrumbNav.vue @@ -0,0 +1,37 @@ + + + diff --git a/apps/desktop/src/components/knowledge/KnowledgeBoardPanel.vue b/apps/desktop/src/components/knowledge/KnowledgeBoardPanel.vue new file mode 100644 index 0000000..1f1388a --- /dev/null +++ b/apps/desktop/src/components/knowledge/KnowledgeBoardPanel.vue @@ -0,0 +1,68 @@ + + + diff --git a/apps/desktop/src/components/knowledge/KnowledgeNotesPanel.vue b/apps/desktop/src/components/knowledge/KnowledgeNotesPanel.vue new file mode 100644 index 0000000..7410582 --- /dev/null +++ b/apps/desktop/src/components/knowledge/KnowledgeNotesPanel.vue @@ -0,0 +1,153 @@ + + + diff --git a/apps/desktop/src/components/knowledge/KnowledgeTasksPanel.vue b/apps/desktop/src/components/knowledge/KnowledgeTasksPanel.vue new file mode 100644 index 0000000..7bd4660 --- /dev/null +++ b/apps/desktop/src/components/knowledge/KnowledgeTasksPanel.vue @@ -0,0 +1,95 @@ + + + diff --git a/apps/desktop/src/components/knowledge/KnowledgeTopbar.vue b/apps/desktop/src/components/knowledge/KnowledgeTopbar.vue deleted file mode 100644 index b7f0c98..0000000 --- a/apps/desktop/src/components/knowledge/KnowledgeTopbar.vue +++ /dev/null @@ -1,62 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/MarkdownPreview.vue b/apps/desktop/src/components/knowledge/MarkdownPreview.vue new file mode 100644 index 0000000..f047d50 --- /dev/null +++ b/apps/desktop/src/components/knowledge/MarkdownPreview.vue @@ -0,0 +1,75 @@ + + + diff --git a/apps/desktop/src/components/knowledge/NoteList.vue b/apps/desktop/src/components/knowledge/NoteList.vue deleted file mode 100644 index 5db9125..0000000 --- a/apps/desktop/src/components/knowledge/NoteList.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/NotePreview.vue b/apps/desktop/src/components/knowledge/NotePreview.vue deleted file mode 100644 index ee3018d..0000000 --- a/apps/desktop/src/components/knowledge/NotePreview.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/NotesPane.vue b/apps/desktop/src/components/knowledge/NotesPane.vue deleted file mode 100644 index aac5790..0000000 --- a/apps/desktop/src/components/knowledge/NotesPane.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/ProjectBrowser.vue b/apps/desktop/src/components/knowledge/ProjectBrowser.vue new file mode 100644 index 0000000..e9635ad --- /dev/null +++ b/apps/desktop/src/components/knowledge/ProjectBrowser.vue @@ -0,0 +1,53 @@ + + + diff --git a/apps/desktop/src/components/knowledge/ProjectCard.vue b/apps/desktop/src/components/knowledge/ProjectCard.vue new file mode 100644 index 0000000..833347c --- /dev/null +++ b/apps/desktop/src/components/knowledge/ProjectCard.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/desktop/src/components/knowledge/ProjectSidebar.vue b/apps/desktop/src/components/knowledge/ProjectSidebar.vue deleted file mode 100644 index e421c87..0000000 --- a/apps/desktop/src/components/knowledge/ProjectSidebar.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/ProjectWorkspace.vue b/apps/desktop/src/components/knowledge/ProjectWorkspace.vue new file mode 100644 index 0000000..14c8115 --- /dev/null +++ b/apps/desktop/src/components/knowledge/ProjectWorkspace.vue @@ -0,0 +1,106 @@ + + + diff --git a/apps/desktop/src/components/knowledge/QuickCreateBar.vue b/apps/desktop/src/components/knowledge/QuickCreateBar.vue new file mode 100644 index 0000000..eb4cc87 --- /dev/null +++ b/apps/desktop/src/components/knowledge/QuickCreateBar.vue @@ -0,0 +1,73 @@ + + + diff --git a/apps/desktop/src/components/knowledge/TasksPane.vue b/apps/desktop/src/components/knowledge/TasksPane.vue deleted file mode 100644 index 3e5a3d9..0000000 --- a/apps/desktop/src/components/knowledge/TasksPane.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/apps/desktop/src/components/knowledge/ThemeToggle.vue b/apps/desktop/src/components/knowledge/ThemeToggle.vue new file mode 100644 index 0000000..d757b5f --- /dev/null +++ b/apps/desktop/src/components/knowledge/ThemeToggle.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/desktop/src/components/settings/sections/KnowledgeSection.vue b/apps/desktop/src/components/settings/sections/KnowledgeSection.vue index 29fcdf0..da75005 100644 --- a/apps/desktop/src/components/settings/sections/KnowledgeSection.vue +++ b/apps/desktop/src/components/settings/sections/KnowledgeSection.vue @@ -1,15 +1,17 @@