Files
MindSift/Doku/modules/workspace.md
T
sandrodachandClaude Opus 5.5 51f90eb7e4
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m26s
feat(notes): browser sync engine with offline queue; editor saves through the operation log
Phase 2 of the collaboration plan:
- frontend/src/lib/docSync: TypeScript port of the block tree, operations,
  effects and order keys (kept identical to Go via shared test vectors),
  diff from the editor's flat list to operations, IndexedDB persistence,
  HTTP transport and DocSyncEngine (one request in flight, idempotent
  resends, backoff, 3 s/30 s polling, keepalive flush and leave on exit,
  block leases for focus, 20 s grace and new blocks).
- Text changes carry the version the user saw when typing (first change
  wins when coalescing; a stale focused field keeps its old base), so a
  concurrent edit becomes a conflict copy instead of a silent overwrite.
- DocumentEditor uses the engine instead of the 800 ms whole-document PUT;
  editors (not only owners) can edit, remote changes appear live.
- Server: task IDs of linked blocks are delivered again, linked tasks follow
  ticked/deleted blocks after sync, note tags are derived, title changes
  notify other users; block IDs already used in another note are renamed
  (starter content with fixed IDs was empty for every further user).
- Fix: unlinking tasks from blocks wrote to non-existent columns and never
  worked (error was swallowed).
- Tests: Go/TS order key vectors, diff round trips, engine races (lost
  responses, offline + reload, edits arriving between typing and sending,
  stale focused field, duplicate first block), plus a Playwright test with
  two browsers against the real image (e2e/run.sh).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:28:15 +01:00

4.9 KiB
Raw Blame History

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 documents plus ein Baum von Blöcken in blocks (parent_id, Sortierschlüssel order_key). Jede Änderung läuft über internal/collab und wird im Log doc_ops festgehalten. 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_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.

Editor

  • 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: 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) an POST /docs/{id}/sync. Beim Öffnen zeigt sie sofort den gespeicherten Stand, auch offline.
  • Abgleich: Bei geteilten oder mehrfach geöffneten Notizen fragt die Engine alle 3 s nach Änderungen, sonst alle 30 s, sowie sofort bei Rückkehr ins Netz oder in den Tab. Beim Verlassen sendet sie Ausstehendes mit keepalive und 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. Die Anzeige gesperrter Bullets folgt in Phase 3 des Plans.
  • Den bisherigen Speicherweg (PUT /documents/{id}) nutzt der Editor nur noch für Symbol und Anheften; Titel und Inhalt laufen über die Engine. PATCH /documents/{id}/blocks nutzt das To-Do-Rollup; beide Wege landen im selben Änderungs-Log.

Explorer, Tags, To-Dos

  • 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.

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 DOC_BLOCKS_PATCHED/DOC_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).