docs: rewrite documentation and README from current codebase, add flaw analysis
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
Remove outdated claims (CRDT, DocRooms, presence, .md files on disk) and document the actual architecture, API, permissions and known flaws. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e9c4ffa8c
commit
bc13235da6
14 files changed
+733
-1618
No files matched your search
+28
-93
@@ -1,104 +1,39 @@
|
||||
# 📝 Kernmodul 3: Workspace Outliner-Engine, Wiki-Links & Pure-DB Storage
|
||||
# Modul: Workspace (Outliner-Notizen)
|
||||
|
||||
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**.
|
||||
Code: [WorkspaceView.tsx](../../frontend/src/features/workspace/WorkspaceView.tsx) (Explorer, Tags, To-Do-Rollup), [DocumentEditor.tsx](../../frontend/src/features/workspace/DocumentEditor.tsx), [OutlinerTree.tsx](../../frontend/src/features/workspace/OutlinerTree.tsx), [OutlinerBlock.tsx](../../frontend/src/features/workspace/OutlinerBlock.tsx), [CodeBlockItem.tsx](../../frontend/src/features/workspace/CodeBlockItem.tsx), [LinkModal.tsx](../../frontend/src/features/workspace/LinkModal.tsx); Backend: Dokument-, Ordner- und Tag-Handler, `Store.PatchDocumentBlocks`.
|
||||
|
||||
---
|
||||
## Datenhaltung
|
||||
|
||||
## 🌳 1. Die Logseq-Outliner-Engine
|
||||
- Eine Notiz ist ein Datensatz in `documents` plus geordnete Zeilen in `blocks` (`position` als Kommazahl, `level` für die Einrückung). Alles liegt in SQLite; es gibt keine Dateien auf der Platte.
|
||||
- Bei jeder Änderung wird `documents.markdown_cache` neu erzeugt; `block_tags` wird aus `#Hashtags` der Blöcke neu aufgebaut.
|
||||
- Der Export als `.md` erfolgt im Browser (Button im Editor, Blob-Download).
|
||||
- Blocktypen: Überschriften `h1`–`h3`, `paragraph`/`text`, `bullet`, `todo`, `code`, `callout`, `divider`, `table`, `progress`.
|
||||
|
||||
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`):
|
||||
## Editor
|
||||
|
||||
```
|
||||
• 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)
|
||||
```
|
||||
- **Outliner:** `Enter` neuer Block, `Tab`/`Shift+Tab` ein-/ausrücken, `Shift+Enter` weicher Umbruch, Blöcke ein-/ausklappen.
|
||||
- **Zoom (Hoisting):** Klick auf den Bullet fokussiert den Ast; die Breadcrumb-Leiste führt zurück.
|
||||
- **Drag & Drop** verschiebt Blöcke samt Unterästen; auf einen anderen Block gezogen, wird der Block zum Unterpunkt.
|
||||
- **Slash-Befehle:** `/todo`, `/link`, `/h1`, `/h2`, `/h3`, `/code`, `/callout`, `/divider` (Liste in `OutlinerBlock.tsx`).
|
||||
- **Links:** `[[Notiztitel]]`, Markdown-Links `[Titel](url)` und reine URLs werden als Token dargestellt; `LinkModal` hilft beim Verknüpfen von Notizen.
|
||||
- **Einfügen:** Mehrzeiliger Text wird anhand von Markdown-Präfixen und Einrückung in Blöcke zerlegt; Überschriften gruppieren darunterliegenden Text und Code.
|
||||
- **Speichern:** Der Editor speichert 800 ms nach der letzten Eingabe das gesamte Dokument (`PUT /documents/{id}`). Der schlanke Block-Endpunkt `PATCH /documents/{id}/blocks` wird derzeit vom To-Do-Rollup beim Abhaken genutzt.
|
||||
|
||||
### 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.
|
||||
## Explorer, Tags, To-Dos
|
||||
|
||||
### 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.
|
||||
- Ordnerbaum mit Favoriten (`doc_pins`), Verschieben per Drag & Drop (`/documents/{id}/move`, `/folders/move`).
|
||||
- **Tags:** Alle `#Hashtags` werden aggregiert (`/workspace/tags`). Eine Tag-Seite zeigt alle Fundstellen gruppiert nach Notiz und kann eine eigene Freitext-Notiz tragen (`tag_pages`).
|
||||
- **To-Do-Rollup:** Die Ansicht „To-Dos“ sammelt alle `todo`-Blöcke aller Notizen, filterbar nach Ordner. Abhaken im Rollup ändert den Block in der Notiz.
|
||||
- **Enhanced Tasks:** Ein `todo`-Block lässt sich als verknüpfte Aufgabe führen (`/documents/{id}/blocks/{blockId}/enhanced-task`); Erledigt-Status bleibt zwischen Notiz und Aufgabenansicht synchron.
|
||||
|
||||
### 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.
|
||||
## Freigabe
|
||||
|
||||
### 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.
|
||||
- Einzelne Notizen und ganze **geteilte Ordner** lassen sich an Benutzer oder Gruppen geben. Empfänger haben **nur Leserechte**; nur der Eigentümer schreibt ([sharing-and-permissions.md](../sharing-and-permissions.md), [FLAW-17](../flaws.md)).
|
||||
- Empfänger ordnen geteilte Notizen und Ordner in ihrem eigenen Baum ein (`doc_user_folders`, `workspace_folder_mounts`), ohne dass der Eigentümer etwas davon merkt.
|
||||
- Änderungen erreichen offene Fenster über `DOC_BLOCKS_PATCHED`/`DOC_UPDATED` ([websocket.md](../api/websocket.md)).
|
||||
|
||||
---
|
||||
## Grenzen
|
||||
|
||||
## 🔗 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.
|
||||
- Keine gleichzeitige Mehrbenutzerbearbeitung, keine Cursor-Anzeige, keine Versionshistorie.
|
||||
- Keine Virtualisierung langer Dokumente; sehr große Notizen können auf Mobilgeräten träge werden *(nicht gemessen)*.
|
||||
- Suche (`/search`) erfasst nur Titel und Inhalt eigener Notizen ([FLAW-18](../flaws.md)).
|
||||
Reference in new issue
Block a user