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:
co-authored by
Claude Opus 5
parent
5881be1a2c
commit
08965157a1
+12
-1
@@ -114,7 +114,18 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
|
||||
Knoten-Eigenschaften dort in `nodeAria()` mitpflegen und dafür a11y-i18n-Keys
|
||||
(`a11y*`) in **allen 9 Sprachen** anlegen. Knoten sind `tabindex="0"`
|
||||
(Fokus = Lesereihenfolge), `#warn` ist eine Live-Region.
|
||||
- Zustand wird im `localStorage` gehalten (noch kein Backend): `werkbaum-lang`
|
||||
- **Server-Dokumente (`?live=`, D76):** `live.js` hält die entscheidbare Hälfte
|
||||
(Adressen, Zeilen-Diff, Rebasen, Cursor-Rechnung, Feed-Regel), `app.js` die
|
||||
Verdrahtung: `loadLive()` holt Text und Version und merkt beides als
|
||||
**Schattenkopie**, `scheduleLivePush()` schickt nach 1,5 s Ruhe das Diff,
|
||||
`runFeed()` hält einen Abruf offen (nur im sichtbaren Tab). Zwei Fallen, beide
|
||||
im Live-Test gefunden (D76-Nachtrag 7): `clientId` **und** `seq` gehören in den
|
||||
`sessionStorage` (je Tab, überlebt Neuladen — sonst hält der Server die erste
|
||||
Änderung nach einem Reload für eine Wiederholung und tut nichts), und der
|
||||
**Konflikt entsteht beim Tippen**, nicht erst beim Senden — der Server kennt
|
||||
den ungesendeten Text nicht. Fremde Änderungen werden bewusst **nicht**
|
||||
undo-fähig eingespielt.
|
||||
- Zustand wird im `localStorage` gehalten (Server-Dokumente ausgenommen): `werkbaum-lang`
|
||||
(Sprache), `werkbaum-docs` (JSON-Array der Dokumente `[{id,name,text}]`),
|
||||
`werkbaum-active` (id des aktiven Dokuments), `werkbaum-src` (Spiegel des
|
||||
aktiven Texts, Abwärtskompatibilität), `werkbaum-ui` (JSON: Modus, verworfene,
|
||||
|
||||
Reference in New Issue
Block a user