Skip to content

fix(studio): stop a Studio edit from reloading the preview - #3128

Closed
miguel-heygen wants to merge 3 commits into
mainfrom
stack/p1-write-receipts
Closed

fix(studio): stop a Studio edit from reloading the preview#3128
miguel-heygen wants to merge 3 commits into
mainfrom
stack/p1-write-receipts

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

What

A write made by Studio itself no longer reloads the preview iframe. Writes from outside Studio still do.

Why

Every Studio edit went to disk, the file watcher saw the change, and the preview reloaded as if an external editor had touched the file. The result was a visible flash after every edit, and any in-flight gesture lost its state.

How

The client mints a write token, marks it before issuing the request, and sends it as a header. The server records a receipt against the file version and attaches it to the watcher event, so the client recognises its own write and suppresses the reload. Marked before the request because the watcher event can beat the response.

Every write path claims its writes, not just the DOM ones: batch, patch-element, group, timeline and caption. A rollback write deliberately does not claim, so the preview does reload.

Test plan

  • 68 server route tests, 1189 studio hook/util tests
  • Editing an element in Studio does not flash the preview; touching the file in an external editor still reloads it

First of eight stacked PRs re-cutting #3077, which stays open as the reference for the whole tree.

…ere external

Every mutation route wrote the file without leaving a write receipt, so the
watcher's broadcast of Studio's own edit arrived with no identity on it. The
external-change coordinator could not tell that echo from an agent or an editor
writing the file behind Studio's back, so it took the safe branch and did a full
iframe reload. That reload hides the stage for the length of the reload, which is
what the flash after a text edit was.

Every mutation write now goes through one helper that records the receipt, and
the client claims the write before the request goes out rather than after it: the
server writes and the watcher fires while the request is still in flight, so a
token marked from the response can arrive after the echo it was meant to match.

Reproduced in the browser before and after, with the reload path traced end to
end. Before, a patch-element write logged `token: null` then a reload from the
coordinator; after, the same write logs the token and `suppressed: own write
token`, with no reload.

Adds `hf-reload-debug` (localStorage, off by default) alongside the existing
`hf-resize-debug`: it records each file-change decision and its reason, plus the
stack of whoever asked for a full reload.
…DOM ones

The receipt only helps when the client marked the token it sent, and the GSAP
mutation writers never sent one. A drag commits through gsap-mutations, so the
server minted a token the client had never seen, the change came back looking
like someone else's, and the preview did the full reload the receipt was meant
to prevent.

Same one-line claim on both GSAP mutation writers, the timing sync's mutation
call, and the caption auto-save PUT.

The rollback call stays deliberately unclaimed and says why: it runs because a
mutation did not converge, so the preview is on bytes nobody can vouch for and
the reload is the point.

Verified live: a drag-shaped update-properties on the timeline now logs
`suppressed: own write token` with no reload, where it logged a coordinator
reload before.
Claiming the timeline writes pushed this file one line past the 600-line
gate. Same change as the branch made later, landed with the commit that
caused it.
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Superseded: reordering the stack so the preview fixes land before the rich-text feature. GitHub locks base branches on a recognised stack, so the chain is being recreated rather than retargeted.

@miguel-heygen
miguel-heygen deleted the stack/p1-write-receipts branch August 9, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant