# 📝 Kernmodul 3: Workspace Outliner-Engine, Wiki-Links & Pure-DB Storage Der MindSift Workspace ([`WorkspaceView.tsx`](../../frontend/src/features/workspace/WorkspaceView.tsx)) kombiniert ein **hierarchisches Bullet-Point Notizsystem (inspiriert von Logseq)** mit einem **persönlichen Wiki**, **Live-Kollaboration** und einem **globalen To-Do Rollup Dashboard**. --- ## 🌳 1. Die Logseq-Outliner-Engine Im Gegensatz zu klassischen Fließtext-Editoren basiert der MindSift Workspace auf einer **flachen, relationalen Liste von Blöcken** (`blocks`-Tabelle in SQLite). Jeder Block ist ein gedanklicher Knotenpunkt mit einer flexiblen Einrückungsebene (`level: 0, 1, 2, ...`) und einer fortlaufenden Fließkommaposition (`position`): ``` • Projekt MindSift v2.0 (level 0) • Architektur-Entscheidung (level 1) - [x] Database-First Blocks implementieren (level 2) - [ ] Performance Benchmark mit 10.000 Blöcken (level 2) • Notizen aus dem Dev-Meeting (level 1) > Wichtig: Keine verschachtelten SQLite Queries ausführen! (level 2) ``` ### Tastatur-Navigation & Shortcuts - `Enter`: Erstellt einen neuen Block auf derselben Hierarchieebene. - `Tab`: Rückt den aktuellen Block ein (wird Kindknoten des vorherigen Blocks). - `Shift + Tab`: Rückt den Block um eine Ebene aus (verringert die Tiefe). - `Shift + Enter`: Weicher Zeilenumbruch innerhalb desselben Blocks (z.B. für mehrzeilige Notizen oder Code). - `Backspace` (auf leerem Block): Löscht den Block sofort. Das Ausrücken erfolgt strikt und kontrolliert über `Shift + Tab`. - `/` (Slash-Commands): Öffnet das Umwandlungsmenü (`/todo`, `/link`, `/h1`, `/h2`, `/h3`, `/code`, `/callout`, `/quote`, `/divider`). - **Markdown-Tastatur-Kürzel:** Tippen von `[] ` oder `[ ] ` wandelt den Block sofort in ein Todo um; `# `, `## `, `### ` erzeugt Überschriften. ### Eingabestabilität & Zombie-Fokus-Schutz (`OutlinerBlock.tsx`) 1. **Echter Fokus-Check:** Remote-Updates (`block_updated`) werden nur dann abgewehrt, wenn der Block tatsächlich aktiv im Betriebssystem editiert wird: `isFocusedRef.current === true && document.hasFocus()`. 2. **Sofort-Flush bei Fensterwechsel:** Sobald das Browser-Fenster den Fokus verliert (`window.addEventListener('blur', ...)`), wird ein offener 150ms-Debounce sofort gecancelt und der Text augenblicklich per WebSocket übertragen. 3. **Stale Closures eliminiert:** Alle Callbacks werden in `useRef` gehalten, sodass asynchrone Debounce-Timer garantiert die aktuellste Komponenten-Referenz verwenden. ### Zoom-In Hoisting (Fokus-Modus) Klickt der Benutzer auf den Bullet-Dot (`•`) eines Blocks, blendet der Editor alle übergeordneten und benachbarten Blöcke aus und zoomt **ausschließlich in diesen Ast** hinein: - Der gewählte Punkt wird zur prominenten Überschrift im Fokus-Modus. - Eine klickbare Breadcrumb-Leiste oben zeigt den Pfad an (z.B. `Workspace / Projekte / MindSift / Architektur`). - Ein Klick auf ein beliebiges Breadcrumb-Element zoomt sofort auf die jeweilige Ebene zurück. ### Drag & Drop von Blöcken Der Bullet-Dot dient gleichzeitig als Drag-Anfasser. Wird ein Block verschoben, erkennt die Engine automatisch alle untergeordneten Kind-Blöcke (`isDescendantBlock`) und verschiebt den **kompletten Unterbaum** an die neue Zielposition. --- ## 🔗 2. Wiki-Links (`[[Link]]`), Web-Links (`/link`) & Hashtags 1. **Interne Wiki-Links:** - Text in doppelten eckigen Klammern (z.B. `[[Reiseplanung 2026]]`) wird automatisch als klickbare Notiz-Pille gerendert. - Klick darauf öffnet die verknüpfte Notiz direkt im Editor. 2. **Slash-Befehl `/link` & Link-Modal:** - `/link` öffnet ein Modal mit zwei Modi: - **Notiz verknüpfen:** Durchsucht bestehende Notizen und fügt `[[Titel]]` ein. - **Web-Link:** Eingabe von Titel und URL, fügt Standard-Markdown `[Titel](url)` ein. 3. **Hashtags (`#tag`):** - Hashtags im Fließtext werden automatisch indiziert (`block_tags`-Tabelle). - In der linken Leiste listet der Tag-Explorer alle verwendeten Schlagworte auf. Klick auf ein Tag filtert alle Dokumente und Blöcke, die dieses Tag enthalten. --- ## ⚡ 3. Echtzeit-Kollaboration & Automatische Markdown-Kompilierung MindSift setzt auf eine latenzfreie In-Memory Kollaborations-Architektur ([`internal/ws/docroom.go`](../../internal/ws/docroom.go)): ### Funktionsweise 1. **In-Memory DocRoom pro geöffnetem Dokument:** - Hält den synchronen Zustand von `title` und `blocks[]` im RAM. - Granulare Mutations-Events (`block_updated`, `block_created`, `block_deleted`, `block_moved`, `title_updated`). - Ephemeres Presence-Tracking (`cursor_moved`, `client_left`) zeigt farbige Benutzer-Avatare im Header und Cursors am aktiven Block an. 2. **Echo-Schutz:** - Jeder Client identifiziert sich mit einer eindeutigen `clientId`. - Der Server sendet Mutations-Events ausschließlich an andere Clients im selben Raum (`clientId != senderClientId`), um Cursor-Springen und Selbstechos zu verhindern. ### Automatische Markdown-Kompilierung & SQLite Debounce-Flush ``` Eingabe im OutlinerBlock │ ├──▶ WebSocket (block_updated Event) │ │ │ ▼ │ Go DocRoom: In-Memory Mutation & Broadcast an Peers │ └──▶ 1.5s Inaktivitäts-Debounce (oder Raum-Exit) │ ▼ SQLite Transaktion: 1. Persistiert Blöcke in `blocks` 2. Regex-Extraktion von #tags in `block_tags` 3. Kompiliert Block-Hierarchie zu Standard-Markdown und speichert Cache in `documents.markdown_cache` ``` 1. **Kompiliertes Markdown:** Jeder Block wird gemäß seiner `level`-Tiefe mit 2 Leerzeichen pro Einrückungsebene als sauberes Markdown formatiert (`documents.markdown_cache`). 2. **Pure Database Architecture:** Alle Daten liegen transaktional und sicher in SQLite. Es werden keine unkontrollierten Dateien auf der Festplatte abgelegt; Notizen können jederzeit per Klick als `.md`-Datei exportiert werden. --- ## 📊 4. Globaler To-Do Rollup Dashboard Über den Tab **„Globale To-Dos"** bietet der Workspace eine aggregierte Übersicht aller im gesamten Wiki verteilten Aufgaben: - Scannt in Echtzeit alle unvollendeten `- [ ] ` Checkboxen über alle Ordner und Notizen hinweg. - Übersichtliche Gruppierung nach **Ordner ➔ Dokument ➔ Aufgabe**. - **Ordner-Filter:** Klick auf einen Ordner isoliert nur dessen Aufgaben für fokussiertes Arbeiten. - **2-Wege-Live-Sync:** Wird eine Checkbox im Rollup abgehakt, wird der Block in SQLite sofort auf `checked = 1` aktualisiert und via WebSocket an alle aktiven Clients gebroadcastet.