Phase 5 of the collaboration plan:
- Remove PATCH /documents/{id}/blocks, PatchDocumentBlocks, the
DOC_BLOCKS_PATCHED event and its types, FlushDocumentState and
LoadDocumentState. PUT /documents/{id} rejects blocks (400) and only
changes title, icon, folder and pin; editors may now change title/icon.
- The to-do overview ticks via a single operation on /docs/{id}/sync
(new skipLog flag). Task links set the block tick with a targeted
operation and notify open editors; creating a linked task needs edit
rights.
- Keep the three share tables: DocRole already decides centrally, and
rewriting the visibility queries would only add risk (documented in plan).
- Tests adapted to the new paths; share e2e test now also ticks a to-do in
the overview.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.4 KiB
Modul: Workspace (Outliner-Notizen)
Code: WorkspaceView.tsx (Explorer, Tags, To-Do-Rollup), DocumentEditor.tsx, OutlinerTree.tsx, OutlinerBlock.tsx, CodeBlockItem.tsx, LinkModal.tsx; Backend: Dokument-, Ordner- und Tag-Handler, Store.PatchDocumentBlocks.
Datenhaltung
- Eine Notiz ist ein Datensatz in
documentsplus ein Baum von Blöcken inblocks(parent_id, Sortierschlüsselorder_key). Jede Änderung läuft überinternal/collabund wird im Logdoc_opsfestgehalten. Ebene und Position für die Oberfläche berechnet der Server beim Lesen. Alles liegt in SQLite; es gibt keine Dateien auf der Platte. - Bei jeder Änderung wird
documents.markdown_cacheneu erzeugt;block_tagswird aus#Hashtagsder Blöcke neu aufgebaut. - Der Export als
.mderfolgt im Browser (Button im Editor, Blob-Download). - Blocktypen: Überschriften
h1–h3,paragraph/text,bullet,todo,code,callout,divider,table,progress.
Editor
-
Outliner:
Enterneuer Block,Tab/Shift+Tabein-/ausrücken,Shift+Enterweicher 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 inOutlinerBlock.tsx). -
Links:
[[Notiztitel]], Markdown-Links[Titel](url)und reine URLs werden als Token dargestellt;LinkModalhilft 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: Jede Notiz hat im Browser eine
DocSyncEngine(lib/docSync/). Der Editor meldet jede Änderung der Block-Liste; die Engine übersetzt sie in Operationen, speichert sie zuerst in IndexedDB und sendet sie dann gesammelt (300 ms) anPOST /docs/{id}/sync. Beim Öffnen zeigt sie sofort den gespeicherten Stand, auch offline. -
Abgleich bei geteilten oder mehrfach geöffneten Notizen, nach Verfügbarkeit:
- Push über WebSocket oder SSE: Der Server meldet
DOC_SEQ, die Engine gleicht sofort ab (im Test 0,2–0,3 s). - Long-Polling (
/docs/{id}/changes), wenn ein Proxy WebSocket und SSE blockiert oder SSE puffert: ebenso schnell. - Abfrage alle 3 s, wenn auch Long-Polling dreimal scheitert (bei
onlinewird Long-Polling erneut versucht).
Solange 1. oder 2. läuft, gleicht die Engine zusätzlich alle 7 s ab, wenn sie Sperren hält (Verlängerung), sonst alle 30 s zur Sicherheit. Ein Fokuswechsel meldet die Sperre sofort an. Der Editor zeigt den Weg an („Live“, „Live (Long-Polling)“, „Abgleich alle 3 s“).
- Push über WebSocket oder SSE: Der Server meldet
-
Private Notizen, die nur einmal geöffnet sind, gleichen alle 30 s ab, außerdem sofort bei Rückkehr ins Netz oder in den Tab. Beim Verlassen sendet die Engine Ausstehendes mit
keepaliveund gibt ihre Sperren frei. -
Textkonflikte: Jede Textänderung trägt die Version, die der Nutzer beim Tippen vor sich hatte. Hat jemand anderes den Bullet inzwischen geändert oder gesperrt, legt der Server eine Konfliktkopie an; es wird nie still überschrieben.
-
Sperren: Der Bullet mit dem Cursor, verlassene Bullets für 20 s und neu angelegte Bullets werden gehalten. Bullets, die jemand anderes hält, zeigen ein Schloss mit Namen und sind schreibgeschützt; Enter darin legt einen neuen Bullet darunter an. Löschen, Zusammenführen, Ein-/Ausrücken und Ziehen werden bei gesperrten Bullets nicht ausgeführt (Hinweis unten im Editor).
-
Präsenz: Im Kopf der Notiz steht, wer sie gerade sonst noch geöffnet hat.
-
Konfliktkopien sind farbig markiert („Konflikt – Version von …“) mit „Übernehmen“ (Text ersetzt den ursprünglichen Punkt bzw. den Titel, die Kopie verschwindet) und „Verwerfen“.
-
Rückgängig:
Strg+Z/Cmd+Znimmt die eigene letzte Änderung zurück,Strg+Umschalt+ZoderStrg+Ywiederholt (auch im Titel und über das Kontextmenü/mobile Tastaturen). Tippen im selben Punkt bis 1 s Pause ist ein Schritt; bis zu 200 Schritte je Tab. Hat jemand anderes den Punkt inzwischen geändert oder hält ihn gesperrt, wird der Schritt mit Hinweis übersprungen. -
PUT /documents/{id}ändert nur noch Symbol, Anheften und Ordner (Titel wird ins Log übernommen); Inhalte laufen ausschließlich über die Engine. Das To-Do-Rollup hakt per einzelner Operation über denselben Sync-Endpunkt ab.
Explorer, Tags, To-Dos
- Ordnerbaum mit Favoriten (
doc_pins), Verschieben per Drag & Drop (/documents/{id}/move,/folders/move). - Tags: Alle
#Hashtagswerden 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.
Freigabe
- 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, FLAW-17).
- 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 den Weckruf
DOC_SEQund anschließenden Sync; Notizlisten überDOC_UPDATED(websocket.md).
Grenzen
- 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).