feat(v2): implement session persistence, file watcher, and markdown viewer

Phase 4 complete (MVP ship):
- SessionDb (rusqlite, WAL mode): sessions + layout_state tables, CRUD
- FileWatcherManager (notify v6): watch files, emit Tauri change events
- MarkdownPane: marked.js rendering with Catppuccin styles, live reload
- Layout store wired to persistence (addPane/removePane/setPreset persist)
- restoreFromDb() on startup restores panes in layout order
- Sidebar "M" button opens file picker for markdown files
- New adapters: session-bridge.ts, file-bridge.ts
- Deps: rusqlite (bundled), dirs 5, notify 6, marked
This commit is contained in:
Hibryda 2026-03-06 12:19:56 +01:00
parent 5ca035d438
commit bdb87978a9
14 changed files with 1075 additions and 17 deletions

View file

@ -0,0 +1,29 @@
import { invoke } from '@tauri-apps/api/core';
import { listen, type UnlistenFn } from '@tauri-apps/api/event';
export interface FileChangedPayload {
pane_id: string;
path: string;
content: string;
}
/** Start watching a file; returns initial content */
export async function watchFile(paneId: string, path: string): Promise<string> {
return invoke('file_watch', { paneId, path });
}
export async function unwatchFile(paneId: string): Promise<void> {
return invoke('file_unwatch', { paneId });
}
export async function readFile(path: string): Promise<string> {
return invoke('file_read', { path });
}
export async function onFileChanged(
callback: (payload: FileChangedPayload) => void
): Promise<UnlistenFn> {
return listen<FileChangedPayload>('file-changed', (event) => {
callback(event.payload);
});
}

View file

@ -0,0 +1,45 @@
import { invoke } from '@tauri-apps/api/core';
export interface PersistedSession {
id: string;
type: string;
title: string;
shell?: string;
cwd?: string;
args?: string[];
created_at: number;
last_used_at: number;
}
export interface PersistedLayout {
preset: string;
pane_ids: string[];
}
export async function listSessions(): Promise<PersistedSession[]> {
return invoke('session_list');
}
export async function saveSession(session: PersistedSession): Promise<void> {
return invoke('session_save', { session });
}
export async function deleteSession(id: string): Promise<void> {
return invoke('session_delete', { id });
}
export async function updateSessionTitle(id: string, title: string): Promise<void> {
return invoke('session_update_title', { id, title });
}
export async function touchSession(id: string): Promise<void> {
return invoke('session_touch', { id });
}
export async function saveLayout(layout: PersistedLayout): Promise<void> {
return invoke('layout_save', { layout });
}
export async function loadLayout(): Promise<PersistedLayout> {
return invoke('layout_load');
}