fix(studio): a copied clip keeps its look and motion, and a duplicated section keeps its name - #4756
Open
miguel-heygen wants to merge 5 commits into
Open
miguel-heygen wants to merge 5 commits into
miguel-heygen wants to merge 5 commits into
Conversation
…d section keeps its name
…in the timeline's scope
miguel-heygen
force-pushed
the
fix/studio-copy-keeps-look
branch
from
September 30, 2026 07:44
76eede7 to
9dcd46a
Compare
miguel-heygen
marked this pull request as ready for review
September 30, 2026 09:29
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A clip copied with Cmd+C and Cmd+V, or duplicated with Cmd+D, now looks and moves like its original. Duplicating a section no longer renames both it and its copy.
Why
goodbyebecomesgoodbye-2). The film's CSS rules and GSAP tweens name the original by that id, so the copy lost both. It drew in the default black 24 px text and never faded in. On a dark film it was invisible.data-composition-id, which is how two instances of one sub-composition are written. At load, the runtime gives each instance a unique id (benefit-fresh__hf1,benefit-fresh__hf2) and keeps the authored one indata-hf-original-composition-id. The timeline label was built from the unique id, so both clips read "Benefit Fresh Hf1" and "Benefit Fresh Hf2".To reproduce either bug on main: in a film with
<h2 id="goodbye">styled by#goodbye { color: ... }and tweened bytl.from("#goodbye", ...), select the clip and press Cmd+D. For the name, do the same on a clip that hosts a sub-composition throughdata-composition-src.How
packages/studio/src/utils/clipboardLook.ts(new): for each id the paste renamed, it copies every top-level CSS rule keyed to the original id for the copy's id, using the browser's own CSS parser. Only the entries of a selector list that name the id are copied, and never one under:not(), so the copy restyles nothing else. It also copies the original's tweens through the GSAP writer. It reads scripts and styles in one pass, so a<style>written inside a script's text stays script.pasteTimelineClipscalls it when the clips come from the same file of the same project. Duplicate always does; paste does when the copy's project and file are the target's. The clipboard now records the project.packages/parsers/src/gsapWriterAcorn.tscopyAnimationsInScript: a copy of a tween is exact or absent.window.go && tl.from(...)) are not copied. Their start depends on what comes before them, so a copy could not be placed exactly.return. The timeline is in scope there, and nothing that follows in its scope is pushed back. That holds when the timeline is declared at the top, inside anifortry, or inside a function.gsap.seton the original is copied right after itself.duplicateCssRulesForId,splitAnimationsInScript), but runs in the browser, where paste and duplicate edit the file. The server's postcss version also covers@mediaand escaped ids. Sharing one owner would put postcss in the browser bundle; that is left for a follow-up.packages/core/src/runtime/timeline.ts: a clip's label, and a scene's, is built from the authored composition id when the runtime renamed the instance.Not covered, and the copy keeps today's behaviour in these cases:
@mediaor@supports;Test plan
What I measured
On a Linux box:
clipboardLook.test.tsruns the pasted film's own script with real GSAP. It checks three things: the copy's rules equal the original's, the copy's tween starts where the copy lands (4 s), and the title's positionless tween still starts at 1.5 s. It fails with the carry call removed. It also fails when the copies are inserted right after the original tween, which pushes the title's tween back.gsapWriter.acorn.test.tshas seven new tests:tl.callcallback;ifblock that declares the timeline;return;clipboardLook.test.tsruns the pasted film with real GSAP in four tests. The key one mixes a stagger, a delay, a positionless tween, a label, a tween on a variable and one in a loop, inside anifblock. After the paste every one of the film's own tweens starts exactly where it did. The copy of the tween at a number starts 3 s after its original, as the clip does. Its check that the film's own tweens keep their starts fails when the copies are placed right after the copied tween. The others cover selector lists,:not(), a<style>string inside a script, and another file.timeline.test.tshas one new test: two instances of a scene are both named "Benefit Fresh". It fails without the fix, reading "Benefit Fresh Hf1" and "Hf2".timeline.test.ts71 of 71,gsapWriter.acorn.test.ts37 of 37, Studio clipboard and payload tests 35 of 35.What I did NOT exercise
Before
At 5 s only the duplicate (4 to 7 s) is on screen, and it is invisible. The duplicated section and its original read "Benefit Fresh Hf2" and "Benefit Fresh Hf1".
After
At 5 s the duplicate shows in the original's orange. Both sections read "Benefit Fresh".