Shared editor language selection; paced WebSocket reconnects
- LangSelect.vue: one language selector for the page and structure tabs (small flag, clean dropdown), v-modeled on the shell-wide editorLang — switching in either panel switches both AND the page preview. While the panel is open the selection overrides the normal language preferences (swapdoc.setLangOverride: loadPlain and pagerite.js fetches/prefetches pin ?lang=, the primary language by its own code); closing restores. - reconnect.js: every socket (page/banner editors, analytics view, the activity channel) now connects through a staggered slot — simultaneous attempts at page load (Vite's HMR socket plus ours, repeated on every refresh) trip the browser's WebSocket throttling, leaving all sockets to the host "pending" for minutes, which was the recurring empty editor. A watchdog closes sockets stuck CONNECTING so they reschedule through the policy (jittered exponential backoff, reset only by a healthy connection) instead of hanging forever; a reconnected editor re-opens its document when the previous open died with its socket.
This commit is contained in:
@@ -15,6 +15,10 @@ Media uploads everywhere use the image icon buttons (pasting into the editor wor
|
||||
|
||||
In-place page re-rendering shared by the banner/site/structure tabs lives in `swapdoc.js` (`runScripts`/`loadPlain`: fetch a page, swap the dynamic regions, replaceState). It also exports `dropPageCache`, which the editor tabs call after any save that can alter the rendered HTML of other pages (theme, headings, structure, banners, site brand/CSS, favicon). Dropping the cache while editing avoids re-fetching every page immediately; the public runtime re-preloads visible links once the editor panel closes.
|
||||
|
||||
The page and structure tabs share one language selector: `LangSelect.vue` (small flag + dropdown) v-modeled on the shell-wide selection in `editorLang.js` (`''` = primary). While the panel is open that selection overrides the page's normal language preferences: EditorShell calls `swapdoc.setLangOverride`, which pins every `loadPlain` fetch (`?lang=`, the primary by its own code) and pagerite.js's own fetches/prefetches (`pagerite:session-lang`), until the panel closes and the override clears.
|
||||
|
||||
All WebSockets (page/banner editors, analytics view, the pagerite.js activity channel) pace their connections through `reconnect.js`: new sockets are created a staggered slot apart (a page load opens Vite's HMR socket plus several of ours at the same moment, and such bursts — like rapid retries — trip the browser's WebSocket throttling, leaving every socket to the host "pending" for minutes), a watchdog closes sockets stuck CONNECTING so they reschedule instead of hanging forever, and retries follow an exponential backoff with jitter that only a healthy connection resets.
|
||||
|
||||
## Saving behavior
|
||||
|
||||
Everything saves immediately as you edit (brand/title/CSS debounced, slug on commit since it renames the path), theme change swaps the stylesheet in place, tree rows navigate in place without transitions when focused, and the front page is a root-only row whose empty slug is editable like any other. Saves that can affect other pages drop the prefetch cache; the cache is rebuilt when the editor panel closes so navigation stays instant.
|
||||
|
||||
+17
-7
@@ -219,16 +219,24 @@ def get_translation(data, path, lang) -> Translation | None:
|
||||
|
||||
### Editor flow
|
||||
|
||||
The page editor has a language picker (flag + name; the same
|
||||
country-flag-icons set as the analytics visitor cells) listing the primary
|
||||
language and the union of the page's translations (`node.langs`) and the
|
||||
site-wide `translate_langs`. It always opens in the primary language, even
|
||||
when the page itself was served in a translation. A note under the toolbar
|
||||
states the blast radius:
|
||||
The page and structure editors share one language selector (`LangSelect.vue`:
|
||||
a small flag button opening a dropdown; the same country-flag-icons set as
|
||||
the analytics visitor cells), v-modeled on one shell-wide selection
|
||||
(`editorLang.js`, `''` = the primary language). The page editor lists the
|
||||
primary language and the union of the page's translations (`node.langs`) and
|
||||
the site-wide `translate_langs`; it always opens in the primary language,
|
||||
even when the page itself was served in a translation. A note under the
|
||||
toolbar states the blast radius:
|
||||
edits to the primary language re-chunk the original (invalidating the
|
||||
affected translation fragments everywhere); edits to a translation stay
|
||||
local to that language.
|
||||
|
||||
While the editor panel is open, its language selection **overrides the
|
||||
normal language preferences** for the page preview: EditorShell pins every
|
||||
in-place re-render and pagerite.js fetch/prefetch to it (`?lang=` — the
|
||||
primary language pins by its own code, which `select_language` honors), and
|
||||
closing the panel restores the normal preferences.
|
||||
|
||||
- WS `open` with a `lang` returns the effective **hybrid** Markdown and
|
||||
title for that language (ungated by `node.langs` — a language without
|
||||
any fragments yet starts from the original text), plus the language
|
||||
@@ -254,7 +262,9 @@ local to that language.
|
||||
updates `Data.chunks` / `node.chunks` — only genuinely new text lands in
|
||||
the kanta change diff (see docs/migrate.md).
|
||||
|
||||
The **structure editor** has the same flag strip for titles. The tree it
|
||||
The **structure editor** selects from the same languages with the same
|
||||
`LangSelect` (the selection is shared — switching in either tab switches
|
||||
both, and the preview). The tree it
|
||||
lists (`GET /_api/pages?lang=`) comes back with per-language titles where a
|
||||
translation exists (`translated` marks those rows; untranslated rows show
|
||||
the original title, dimmed). Retitling in a non-primary language posts the
|
||||
|
||||
Reference in New Issue
Block a user