feat(studio): timeline multi-select (marquee) + relative group time editing#2111
Merged
Conversation
Collaborator
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
Use selectedElementIds as the live selection set with selectedElementId as anchor. Keep single-click selection as a one-element set and clear both fields together.
Render selected styling from selectedElementIds in the timeline. Sync the set into preview group selection boxes without collapsing the anchor.
Persist group timing edits through one coalesced write per source file. Keep batch timing queued behind any z-index commit for the same gesture.
Fan selected body drags through a group move session that snapshots all selected members. The grabbed clip snap result is applied first, then one shared delta is clamped. Live preview patches every moved member and release persists once through batch timing.
Apply handle deltas through a group resize session that snapshots selected members. Clamp one shared delta against zero start and min duration before preview and commit. Playback-start changes are calculated per member with the existing trim formula.
setSelectedElementId no longer resets the selection set when re-selecting an element that is already a member: DOM-to-selection sync echoes fire on every pointer move during a group drag and were collapsing the set to the grabbed clip. Also drops the duplicate clearSelectedElementIds action in favor of clearSelection, which the marquee now uses to clear on an empty drag.
The marquee and range overlays used a hardcoded blue; they now use the timeline theme accent for the border with a translucent accent fill.
…mp math Extract resolveTimelineIdForSelection so DOM-to-timeline id mapping lives in one place with a single sourceFile / activeCompPath / index.html fallback, fixing a sub-composition selection that previously diverged between callers. Extract shared start-trim delta helpers used by both single-clip and group resize, and remove the never-called refreshDomEditGroupSelectionsFromPreview.
…pping, marquee) Group move/resize rejects the gesture when any selected member forbids the op (e.g. a locked clip), so a group never edits a clip that individually cannot move, and a persist failure now propagates so the optimistic preview rolls back. Snapping excludes every moving member, not just the grabbed clip. The marquee hit-test uses the real pixels-per-second (was floored at 1, wrong below 1x zoom), and a sub-threshold marquee click scrubs the playhead like a plain lane click.
The DOM-selection to timeline sync routes through the canonical resolveTimelineIdForSelection (source-file, ancestor, active-comp fallback) instead of a narrow domId/id match that mismatched sub-composition clips. The preview-sync equality check compares selection as sets both ways and includes the anchor, so duplicate resolutions no longer mask an unsynced member.
The store-to-preview sync no longer applies a partial selection: if a resolvable member's DOM node is not ready yet it bails and retries on the next effect run, so the write-back can never shrink the store's selection by dropping an unresolved member. Marquee row hit-testing reuses shouldShowTimelineLayerGroupHeader instead of re-deriving the group-header placement rule, keeping one owner for that predicate.
…ection setSelectedElementId now always collapses to one element (genuine user intent); a new setSelectionAnchor moves the anchor within a multi-selection without collapsing it, used only by the DOM-to-store sync echoes so a group survives a gesture. applyDomSelection mirrors the whole DOM group into the store via setSelection instead of writing only the anchor, so the store stays authoritative and a preview click collapses while a preserved-group echo keeps every member.
9183a04 to
9cf575c
Compare
A timeline move/resize recorded the timing patch, then a server GSAP rewrite mutated the same file afterward, leaving the recorded after stale so an undo hit a hash conflict. The GSAP mutation now snapshots the touched files and records a follow-up edit under the same coalesceKey, with a per-entry coalesceMs override large enough to survive the GSAP round trip, so undo restores the original in one step. Applies to single-clip and group edits.
…cker handleTimelineElementSelect tags each call with a monotonic token and ignores its result if a newer selection started while it was resolving, so a rapid A-to-B clip click can no longer let A's slower async lookup land after B and restore the wrong selection.
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.

Adds rubber-band (marquee) multi-selection to the Studio timeline plus relative group time editing.
What
Single source of truth
selectedElementIdsin the player store, withselectedElementIdas the anchor. Re-selecting a current member (a DOM-to-selection sync echo during a group drag) updates the anchor without collapsing the set.resolveTimelineIdForSelectionowns DOM-to-timeline id mapping (one sourceFile / activeCompPath / index.html fallback); shared start-trim delta helpers back both single-clip and group resize.Verification
Studio typecheck and 1509 unit tests green; lint and format clean. Marquee, group move, and group resize verified live in a headless Studio preview.
Stacked on #2068; retarget to main after that merges.