Skip to content

fix(studio): undoing a crop leaves a GSAP-animated layer where its file puts it - #4868

Closed
miguel-heygen wants to merge 7 commits into
mainfrom
fix/studio-crop-undo-gsap-refold
Closed

miguel-heygen wants to merge 7 commits into
mainfrom
fix/studio-crop-undo-gsap-refold

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #4853; review only the commits after e185c11.

What

An undo or redo of a crop (or any style-only edit) on a layer GSAP animates now puts the layer back exactly where its file and script put it. Before, the layer jumped: a gsap.set hold lost its position (10 px off on the edit-accuracy fixture), a tween counted the stylesheet translate twice, and a CSS rotate was applied twice.

Why

The in-place undo copies the file's attributes onto the live element. That wipes what GSAP wrote inline when it first parsed the element (translate: none; rotate: none; scale: none and, for an off-timeline gsap.set, the transform itself), while GSAP's cache (el._gsap) keeps the values it parsed. When the script did not change (a crop changes only style), the restore only seeked, so GSAP never parsed the element again and the stylesheet transform came back under GSAP's own.

Related work

Stacked on #4853 (gesture-aware attribute sync); its tests stay green. Takes the idea of #4771 (re-run the script when the sync touches an element GSAP parsed), not its branch.

How

  • applyUndoRestoreToPreview: when a synced element was parsed by GSAP and the document has a GSAP script, re-run the restored script in place (the soft-reload path a script change already takes), even if the script text is unchanged. A document with several GSAP scripts cannot re-run one in place, so that case reloads.
  • applySoftReload takes those elements as reparse and resets GSAP's cache for exactly them. Its existing sweep only found GSAP elements that still had an inline transform, which the sync had just removed.

Why a re-run and not only clearing GSAP's cache and seeking: an off-timeline gsap.set hold has no tween left to render after the cache is cleared, so only re-running the script puts the hold back. Re-running is also what a fresh load does, so holds, tweens and rotation all match it.

Test plan

  • Unit tests added/updated: gsapUndoRestore.browser.test.ts drives real Chrome with the edit-accuracy fixtures (hold, tween, xPercent tween with CSS rotate: 30deg), crops the live layer, runs the undo and compares the layer's box with the box before the edit. It fails on fix(studio): an undo that lands mid-drag keeps the box under the pointer #4853's head (hold [600, 330] vs [600, 320]; tween [660, 367.5] vs [620, 337.5]; rotated box swapped) and passes with the fix. gsapUndoRestore.test.ts and gsapSoftReload.test.ts pass unchanged.
  • Edit accuracy bench: the 45 crop-(hold|tween)-*-root cases that failed on main pass every gated metric (CI gate: 0 regressed, 49 newly passing, the 45 crop cases banked from that run's artifact). The resize-hold-*-root undo boxes are unchanged by this PR (the same numbers as main to 0.1 px); this PR does not fix them.
  • Comments follow CONTRIBUTING.md "Comments"

Before

Edit-accuracy fixture crop-hold-px-r0-root-z100 in Studio at #4853's head: crop, then Cmd+Z. The layer lands 10 px (composition) below where its file puts it; redo is off by the same 10 px.

Before: after Cmd+Z the layer sits below the red line

After

Same case with this PR: undo and redo land exactly (box error 0).

After: after Cmd+Z the layer sits on the red line

@miguel-heygen
miguel-heygen force-pushed the fix/studio-crop-undo-gsap-refold branch from b1c84ae to a11bb11 Compare October 1, 2026 16:47
@miguel-heygen
miguel-heygen force-pushed the fix/studio-drag-after-undo branch from 90d53ad to bbcd151 Compare October 1, 2026 16:48
@miguel-heygen
miguel-heygen force-pushed the fix/studio-crop-undo-gsap-refold branch from a11bb11 to 99f1934 Compare October 1, 2026 17:25
@miguel-heygen
miguel-heygen changed the base branch from fix/studio-drag-after-undo to main October 1, 2026 17:25
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Edit accuracy: 888 passing here, 843 on the base branch

The gate fails: 4 case(s) that pass on the base branch fail here; 45 newly passing case(s) are not banked in baseline.json.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Regressed (4)

  • resize-hold-center-r0-root-z200
  • resize-hold-xpercent-r0-root-z200
  • resize-hold-xpercent-r0-root-z50
  • resize-hold-xpercent-r0-root-z100

Newly passing (49)

  • crop-hold-center-r30-root-z50
  • crop-hold-pct-r30-root-z50
  • crop-hold-px-r30-root-z50
  • crop-hold-xpercent-r30-root-z50
  • crop-tween-center-r30-root-z50
  • crop-tween-pct-r30-root-z50
  • crop-tween-px-r30-root-z50
  • crop-tween-xpercent-r30-root-z50
  • crop-hold-center-r0-root-z200
  • crop-hold-pct-r0-root-z200
  • crop-hold-px-r0-root-z200
  • crop-hold-xpercent-r0-root-z200
  • crop-tween-center-r0-root-z200
  • crop-tween-pct-r0-root-z200
  • crop-tween-px-r0-root-z200
  • crop-hold-center-r30-root-z100
  • crop-hold-pct-r30-root-z100
  • crop-hold-px-r30-root-z100
  • crop-hold-xpercent-r30-root-z100
  • crop-tween-center-r30-root-z100
  • crop-tween-pct-r30-root-z100
  • crop-tween-px-r30-root-z100
  • crop-tween-xpercent-r30-root-z100
  • crop-hold-center-r0-root-z50
  • crop-hold-pct-r0-root-z50
  • crop-hold-px-r0-root-z50
  • crop-hold-xpercent-r0-root-z50
  • crop-tween-center-r0-root-z50
  • crop-tween-pct-r0-root-z50
  • crop-tween-px-r0-root-z50
  • ...

Not banked (commit the artifact's baseline.json) (45)

  • crop-hold-center-r30-root-z50
  • crop-hold-pct-r30-root-z50
  • crop-hold-px-r30-root-z50
  • crop-hold-xpercent-r30-root-z50
  • crop-tween-center-r30-root-z50
  • crop-tween-pct-r30-root-z50
  • crop-tween-px-r30-root-z50
  • crop-tween-xpercent-r30-root-z50
  • crop-hold-center-r0-root-z200
  • crop-hold-pct-r0-root-z200
  • crop-hold-px-r0-root-z200
  • crop-hold-xpercent-r0-root-z200
  • crop-tween-center-r0-root-z200
  • crop-tween-pct-r0-root-z200
  • crop-tween-px-r0-root-z200
  • crop-hold-center-r30-root-z100
  • crop-hold-pct-r30-root-z100
  • crop-hold-px-r30-root-z100
  • crop-hold-xpercent-r30-root-z100
  • crop-tween-center-r30-root-z100
  • crop-tween-pct-r30-root-z100
  • crop-tween-px-r30-root-z100
  • crop-tween-xpercent-r30-root-z100
  • crop-hold-center-r0-root-z50
  • crop-hold-pct-r0-root-z50
  • crop-hold-px-r0-root-z50
  • crop-hold-xpercent-r0-root-z50
  • crop-tween-center-r0-root-z50
  • crop-tween-pct-r0-root-z50
  • crop-tween-px-r0-root-z50
  • ...

Quarantined, measured but not gated (1)

Unstable (2)

  • seqnudge-none-pct-r0-nested-z100: tracking 0.03, pressJump 0, drop 0, reload 0, render 0.01, undo false, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.01, undo true, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.01, undo true, teleport true
  • sequndo-none-px-r0-root-z100: tracking 0.03, pressJump 0, drop 0, reload 0, render 0.02, undo true, teleport true / tracking 0.03, pressJump 0, drop 0, reload 0, render 0.02, undo true, teleport true / tracking 0.03, pressJump 312.36, drop 0, reload 0, render 0.04, undo true, teleport false

@miguel-heygen
miguel-heygen force-pushed the fix/studio-crop-undo-gsap-refold branch from efaa875 to b6cbcff Compare October 1, 2026 18:59
@miguel-heygen

Copy link
Copy Markdown
Collaborator Author

Folded into #4869, which now carries this fix (undoing a crop leaves a GSAP-animated layer where its file puts it) together with the other GSAP edit fixes.

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