feat(frontend): gemeinsam am Server-Dokument arbeiten (?live=, Schritt 6)

Der Editor fuehrt ein Dokument des Backends: laden, nach 1,5 s Ruhe das Diff
schicken, ueber einen offenen Abruf fremde Aenderungen einspielen — ohne
Neuladen, mit mitwandernder Schreibmarke. Dazu CORS im Backend; ohne das
blockiert der Browser jeden Aufruf.

Zwei Fehler hat erst der Live-Test gegen das laufende Backend gefunden, beide
an der Naht zwischen Modul und Verdrahtung (D54-Nachtrag 3):

Der Konflikt entstand nie. Mit laufendem Feed zieht die Schattenkopie staendig
nach, die eigene Basis ist also nie veraltet — der Server haette nie 409
geantwortet, und die fremde Zeile waere stillschweigend ueberschrieben worden.
Der Client prueft die Ueberschneidung jetzt selbst gegen den ungesendeten
Text; den kennt der Server nicht.

Die Nummer begann nach jedem Neuladen wieder bei 1, waehrend die Kennung
blieb — der Server hielt die erste echte Aenderung fuer eine Wiederholung und
tat nichts. Beides liegt jetzt im sessionStorage: je Tab, ueberlebt Neuladen.
Je Tab ist zugleich die richtige Aussage, zwei Tabs sind zwei Schreiber.

Nachgemessen im Browser: fremde Aenderung erscheint ohne Neuladen, Getipptes
erreicht den Server, beide Konflikt-Knoepfe tun was sie sagen, und die
Schreibmarke steht nach zwei fremd eingefuegten Zeilen darueber unveraendert
bei Zeile+2, Spalte 8. 518 Frontend-Tests, 135 im Backend.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-26 17:48:17 +02:00
co-authored by Claude Opus 5
parent 5881be1a2c
commit 08965157a1
12 changed files with 666 additions and 7 deletions
+23
View File
@@ -818,6 +818,29 @@ Export- oder `/timeslider`-Pfad wird abgeschnitten.
Siehe D31.
### Gemeinsam an einem Server-Dokument arbeiten (`?live=`)
Liegt der Plan auf einem Werkbaum-Backend, nimmt der Editor dessen
Dokument-Adresse: `…?live=https://example.org/api/v1/documents/<uuid>`.
Anders als beim Pad (`?etherpad=`) wird hier **im Editor selbst geschrieben**,
und alle sehen die Änderungen der anderen, ohne neu zu laden.
- **Das Textfeld bleibt beschreibbar.** Nach kurzer Ruhe (1,5 s) schickt der
Editor die Änderung als Zeilen-Diff; ein offener Abruf hält die Gegenrichtung
bereit und spielt fremde Änderungen ein. Die **Schreibmarke wandert mit**
fügt jemand oberhalb Zeilen ein, bleibt sie an ihrer Stelle im Text.
- **Der Name ist der Titel des Dokuments** (alle sehen denselben), die
vollständige Adresse steht im Tooltip.
- **Überschneiden sich zwei Änderungen wirklich** — dieselben Zeilen —, fragt
ein Band oben, wessen Fassung gelten soll: *Fremde übernehmen* oder *Eigene
durchsetzen*. Alles andere führt der Server selbst zusammen, ohne zu fragen.
Verloren geht nichts: Der verworfene Stand bleibt in den früheren Ständen,
jede Version in der Historie des Servers.
- Der Abruf läuft **nur im sichtbaren Tab**; im Hintergrund ruht er und holt
beim Zurückkommen den Rückstand.
Siehe D76 (Protokoll und Begründung) und
`backend/docs/live-editing-proposal.md`.
### Legende im Editor-Panel
Neben dem Textfeld steht eine aufklappbare **Legende** (Notation in Kurzform,
abschließend eine Bedienungs-Zeile). Sie ist **scrollbar**, wenn ihr Inhalt