mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* fix(web): keep deck page counters in sync during keyboard paging Host-driven deck navigation (keyboard shortcuts and prev/next buttons) used to mutate slide classes/transforms directly in the srcdoc bridge, bypassing the artifact's own navigation script. Decks that render their own page counter from an internal index never saw the move, so the bottom page number stayed frozen on the first slide while the canvas advanced. The bridge now prefers dispatching the navigation key to the artifact's own keyboard handler and only falls back to direct DOM mutation when no handler moves the deck. The mirror gap: iframe-focused keyboard navigation on transform-track decks mutates only the shared track element, which the bridge's MutationObserver (slide attributes only) never saw, leaving the HOST counter stale. The observer now watches the track's style too. Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) * worker: 使用键盘快捷键翻页的时候,下面的页码不会变动 Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) * fix(web): wait out deferred deck key handlers before the bridge's direct-DOM fallback Review follow-up for #5594: the artifact-key probe treated only a synchronous index change as proof the artifact handled the key. Decks that defer their keydown state update (requestAnimationFrame or setTimeout) fell through to direct DOM mutation immediately AND received the key twice — the window dispatch and the document re-dispatch both reach a deferred window listener — so one host "next" advanced two slides and desynced the artifact's internal index. The probe is now asynchronous: dispatch to one target, then wait one bounded mutation window (MutationObserver on class/style/hidden plus a 48ms cap) for the active index or track transform to change before trying the next dispatch target or the direct-DOM fallback. Synchronous handlers still resolve on a zero-latency fast path, and a responsive dispatch target is cached so later keypresses skip re-probing. Decks with no keyboard handling must not pay the probe wait: the key path is gated on the artifact actually shipping keyboard navigation, seeded from a source scan of the artifact html before any od bridge is injected plus registration-time tracking through the existing addEventListener patch — the same two-pronged pattern the od:slide message-listener flag already uses. This preserves the pinned invariant that the bridge-owned fallback stays synchronous for handler-less decks. Regression fixtures: a deferred window-listening deck (red on the synchronous probe with a visible double advance to slide 3) and seed-scan assertions proving od-injected bridge scripts do not contaminate the keyboard-navigation flag. Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code) * fix(web): catch external-script deck keyboard runtimes with a head-start registry hook Review follow-up for #5594: detectArtifactKeyboardNavigation() only sees inline HTML bytes, so decks that load their keyboard runtime via <script src> (design-templates/html-ppt wires ../assets/runtime.js, which registers an ArrowRight/ArrowLeft document keydown handler) were classified handler-less. Their listeners also register before the deck bridge executes at the end of <body>, so the bridge's own addEventListener patches installed too late — the flag stayed false, host-driven od:slide fell back to direct DOM mutation, and artifact-owned counters / internal indices went stale again. A tiny registry hook is now injected at the start of <head> — before any artifact script — wrapping window/document addEventListener and flagging keydown listeners that pass the shared navigation-key screen into window.__odArtifactKeydownNavigation. The deck bridge reads that flag lazily alongside its inline-source seed and its own late patches, so registrations are observed no matter when they happen relative to the bridge. The bridge marks its own top-of-file keydown listeners via __odDeckBridgeOwnListenerInstall so the framework branch's key-token source does not classify every framework deck as artifact-navigable. The navigation-key screen is now a single shared snippet between the hook and the bridge. Regression: a fixture that registers its keydown handler before the bridge evaluates with no keydown token in the html bytes (the script-src shape) — red on the previous commit (counter stays 1 while the canvas moves), green with the hook. Generated-By: looper 0.0.0-dev (runner=worker, agent=claude-code)