feat: Adresszeile folgt dem Dokument, Live-Sitzung ebenso (D80)
Wer bei offenem `?live=` umschaltet, behielt die alte Adresse — optisch falsch, und ein Neuladen holte das falsche Dokument zurück. Der Parameter gehört jetzt zum aktiven Dokument, für `?live=` wie für `?sourceUrl=`; `?etherpad=` wird nur noch weggeräumt. Fremde Parameter (`?server=`) bleiben wörtlich stehen, damit die URL lesbar bleibt. Dabei gefunden: Die Live-Sitzung lief weiter, während ein anderes Dokument vorn stand — `setLiveText()` schrieb fremde Änderungen in dessen Text. Die Sitzung gehört jetzt dem sichtbaren Dokument: Umschalten beendet sie, Umschalten auf ein Server-Dokument nimmt sie auf. Was noch im Debounce steckt, geht vorher raus, und `pushLive()` hält seine Sitzung fest statt anzunehmen, dass sich über ein `await` hinweg nichts ändert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
627f6feca8
commit
fdca934cf0
@@ -19,6 +19,9 @@ reverse.
|
||||
|
||||
## 2026-08-26
|
||||
|
||||
- The address bar follows the document you switch to: `?live=` and `?sourceUrl=` name what is in front of you, so a reload brings back the same plan
|
||||
- Switching to a server document in the picker now really opens it live — before it only showed its last state
|
||||
- Fix: a foreign change to a server document could land in the text of a local document you had switched to
|
||||
- Changes in a shared document now reach the others after 0.6 s instead of 1.5 s — the wait before sending was almost the whole delay
|
||||
|
||||
- The Etherpad integration is gone: collaboration now runs through a Werkbaum backend, and an old `?etherpad=` link says so instead of doing nothing
|
||||
|
||||
@@ -6819,3 +6819,85 @@ die 600 ms sind gesetzt, und was daneben liegt (Server 39 ms, Rundlauf 130 ms,
|
||||
PATCH → sichtbar 46 ms) ist einzeln gemessen. Dieselbe Lehre wie D25
|
||||
(synthetische `TouchEvent`s), D17-Nachtrag 4 (Bildschirmtastatur) und D53
|
||||
(synthetisches Strg+Z): Was die Umgebung stellt, stellt der Emulator nicht.
|
||||
|
||||
## D80 — Die Adresszeile beschreibt das aktive Dokument, und die Live-Sitzung folgt ihm
|
||||
Gemeldet: Wer bei offenem `?live=…` auf ein anderes Dokument umschaltet, behält
|
||||
die alte Adresse — „das sieht optisch falsch aus, und beim Neuladen würde wohl
|
||||
auch das Dokument aus `live=` wieder geladen". Beides stimmt, und beim
|
||||
Nachsehen kam ein dritter, schwererer Befund dazu.
|
||||
|
||||
**Die Adresse ist kein Andenken an den Aufruf, sondern der Stand.** Sie ist der
|
||||
Link, den man weitergibt, und das, was ein Neuladen wiederherstellt. Zeigt sie
|
||||
auf etwas anderes als der Bildschirm, ist eines von beiden gelogen — und beim
|
||||
Neuladen entscheidet die Adresse. Die Regel lautet deshalb: **Der Parameter
|
||||
gehört zum aktiven Dokument.** Umschalten auf ein lokales Dokument räumt ihn
|
||||
weg, Umschalten auf ein anderes Server-Dokument tauscht ihn aus.
|
||||
|
||||
**Sie gilt für beide Eingänge, nicht nur für `?live=`.** `?sourceUrl=` (D23)
|
||||
hatte dasselbe Problem, und eine Regel, die nur für einen der beiden gilt, ist
|
||||
keine. Beide Eingänge sind ohnehin schon die **Identität** des Dokuments
|
||||
(`live:<url>`, `url:<href>`) — der Parameter lässt sich also aus der id
|
||||
zurückrechnen, statt nebenher geführt zu werden. `?etherpad=` ist ausgebaut
|
||||
(D78) und wird nur noch weggeräumt.
|
||||
|
||||
**Für `?sourceUrl=` ist das keine neue Gefahr**, obwohl der Parameter beim
|
||||
Zurückschalten wiederkommt und ein Neuladen den Text dann erneut holt (D23:
|
||||
„lokale Änderungen daran überleben ein Neuladen nicht"). Bisher stand er
|
||||
**immer** da, unabhängig davon, was vorn war — es wird also nicht mehr
|
||||
überschrieben als vorher, sondern weniger.
|
||||
|
||||
**Fremde Parameter bleiben wörtlich stehen — auch ihre Schreibweise.** Der
|
||||
naheliegende Weg über `URLSearchParams` schriebe jedes `:` und `/` als
|
||||
`%3A`/`%2F` und machte damit gerade die URL unleserlich, um die es hier geht;
|
||||
`?server=` (D76-Nachtrag 8) fiele bei einem Neubau der Adresse ganz weg.
|
||||
Maskiert wird nur, was den Query-String sonst zerrisse (`&`, `#`). Die
|
||||
entscheidbare Hälfte steht als reine Funktion in `docurl.js`
|
||||
(Hausregel D54-Nachtrag 3), die `history.replaceState`-Seite in app.js.
|
||||
|
||||
**Der dritte Befund: Die Live-Sitzung lief weiter, während ein anderes Dokument
|
||||
vorn stand.** `switchDoc()` hat bisher nur `activeId` gewechselt; `liveState`
|
||||
blieb, der Feed lief, und `setLiveText()` schreibt in `src.value` **und** in
|
||||
`activeDoc().text` — eine fremde Änderung am Server-Dokument landete also im
|
||||
Text des Dokuments, das man gerade ansieht. Nachgemessen war die Lücke echt:
|
||||
Die Meldung des Nutzers ist die Tür dazu.
|
||||
|
||||
**Also gehört die Sitzung dem sichtbaren Dokument.** Umschalten beendet sie;
|
||||
Umschalten auf ein Server-Dokument nimmt sie auf (`startLive()`, aus
|
||||
`loadLive()` herausgelöst — derselbe Weg, nur mit der URL aus dem Dokument
|
||||
statt aus dem Parameter). Der Nebengewinn ist der eigentliche: Ein
|
||||
Server-Dokument, das man im Wähler auswählt, ist danach wirklich live. Vorher
|
||||
zeigte es stumm seinen letzten Stand — die Adresse hätte also nicht nur
|
||||
optisch, sondern der Sache nach gelogen, wenn man sie einfach mitgeführt hätte.
|
||||
|
||||
**Verdrahtet an genau einer Stelle:** `loadActiveIntoEditor()` — jeder Weg zu
|
||||
einem anderen aktiven Dokument führt dort durch (Umschalten, Anlegen, Löschen,
|
||||
Datei öffnen, Server-Dokument laden). Während des Starts ruht die Regel
|
||||
(`bootDone`): `loadRemoteSource()` und `loadLive()` lesen ihre Parameter erst,
|
||||
nachdem das zuletzt aktive Dokument wiederhergestellt ist — ein vorschnelles
|
||||
Aufräumen nähme ihnen die Vorlage.
|
||||
|
||||
**Was noch im Debounce steckt, wird beim Umschalten losgeschickt.** Sonst
|
||||
verlöre ein Wechsel innerhalb von 600 ms nach dem letzten Tastendruck genau
|
||||
diese Änderung an den Server. Gesendet wird, **bevor** `activeId` wechselt —
|
||||
`pushLive()` liest `src.value` synchron, danach zeigt das Feld schon den
|
||||
anderen Text.
|
||||
|
||||
**Und `pushLive()` hält jetzt seine Sitzung fest, nicht nur deren Felder.**
|
||||
Wer während des Sendens umschaltet, beendet sie; die Fortsetzung nach dem
|
||||
`await` dürfte danach weder schreiben noch in ein `null` greifen (das
|
||||
`finally` hätte es getan). Dieselbe Sorte Annahme, die D76-Nachtrag 9 schon
|
||||
einmal an dieser Funktion korrigiert hat: dass sich über ein `await` hinweg
|
||||
nichts ändert.
|
||||
|
||||
**Nachgemessen** im Browser gegen ein lokales Backend, mit zwei
|
||||
Server-Dokumenten: Umschalten auf ein lokales Dokument räumt `?live=` weg,
|
||||
Umschalten auf das andere Server-Dokument tauscht die URL aus, `?sourceUrl=`
|
||||
verhält sich symmetrisch und bleibt unmaskiert lesbar. Eine fremde Änderung
|
||||
erreicht das per Wähler geöffnete Server-Dokument ohne Neuladen (die Sitzung
|
||||
läuft also wirklich); dieselbe Änderung, während ein lokales Dokument vorn
|
||||
steht, lässt dessen Text unangetastet (vorher hätte sie ihn überschrieben);
|
||||
beim Zurückschalten steht der Server-Stand da. Eine Zeile, im selben Zug
|
||||
getippt und umgeschaltet, kommt beim Server an. 514 Tests, davon 13 neue in
|
||||
`tests/docurl.test.js`; Gegenproben: fremde Parameter mitwerfen → genau die
|
||||
zwei danach benannten Zusicherungen fallen, `encodeURIComponent` statt der
|
||||
sparsamen Maskierung → genau die sieben, die die Lesbarkeit festhalten.
|
||||
|
||||
@@ -766,6 +766,9 @@ Seite aufgelöst; zugelassen sind nur `http`/`https`). Der Text wird als
|
||||
Tooltip); derselbe Link aktualisiert dieses Dokument, statt ein neues anzulegen.
|
||||
Ist der Parameter gesetzt, wird bei **jedem** Laden neu geholt — die URL ist die
|
||||
Quelle der Wahrheit, lokale Änderungen daran überleben ein Neuladen nicht.
|
||||
Die **Adresszeile folgt dem aktiven Dokument** (§9, `?live=`): Beim Umschalten
|
||||
auf ein anderes verschwindet der Parameter, beim Zurückschalten steht er wieder
|
||||
da.
|
||||
Scheitert das Laden (häufigster Fall: das Ziel sendet keinen
|
||||
`Access-Control-Allow-Origin`-Header, außerdem 404/Netzfehler), bleibt der
|
||||
bisherige Stand stehen und es erscheint eine **Warnung**. Siehe D23.
|
||||
@@ -796,6 +799,13 @@ anderen, ohne neu zu laden.
|
||||
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.
|
||||
- **Die Adresszeile beschreibt das Dokument, das vorn ist.** Umschalten auf ein
|
||||
lokales Dokument räumt `?live=` weg, Umschalten auf ein anderes
|
||||
Server-Dokument trägt dessen Adresse ein — ein Neuladen bringt also zurück,
|
||||
was man vor sich hatte. Dasselbe gilt für `?sourceUrl=` (oben). Und die
|
||||
gemeinsame Sitzung gehört dem sichtbaren Dokument: Wer ein Server-Dokument im
|
||||
Wähler auswählt, arbeitet darin wieder gemeinsam; wer es verlässt, hört auf,
|
||||
mitzuschreiben. Siehe D80.
|
||||
|
||||
Siehe D76 (Protokoll und Begründung) und
|
||||
`backend/docs/live-editing-proposal.md`.
|
||||
|
||||
Reference in New Issue
Block a user