Skip to content

feat: add range selection functionality to element interaction#800

Open
oguzhancttnky wants to merge 3 commits into
OpenCut-app:mainfrom
oguzhancttnky:feature/shift-click-timeline-selection
Open

feat: add range selection functionality to element interaction#800
oguzhancttnky wants to merge 3 commits into
OpenCut-app:mainfrom
oguzhancttnky:feature/shift-click-timeline-selection

Conversation

@oguzhancttnky
Copy link
Copy Markdown

@oguzhancttnky oguzhancttnky commented May 17, 2026

Closes #801

Adds Shift-click range selection for timeline clips on the same row.

Summary by CodeRabbit

  • New Features
    • Shift-range selection: hold Shift and click to select a contiguous range of timeline elements between an anchor and a target.
    • Anchor-aware selection: range selection uses an anchor when on the same track; otherwise selection falls back to the clicked element, and editor selection is updated for each element in the chosen range.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 17, 2026

@oguzhancttnky is attempting to deploy a commit to the OpenCut OSS Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 58acbfc1-1ad8-415e-bc04-fd1810a6aec8

📥 Commits

Reviewing files that changed from the base of the PR and between a9c37b9 and ae2b34e.

📒 Files selected for processing (2)
  • apps/web/src/timeline/controllers/element-interaction-controller.ts
  • apps/web/src/timeline/hooks/element/use-element-selection.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/src/timeline/controllers/element-interaction-controller.ts
  • apps/web/src/timeline/hooks/element/use-element-selection.ts

📝 Walkthrough

Walkthrough

Adds shift-click range selection: new selectRange API, a hook selectElementRange that computes inclusive contiguous ranges ordered by startTime, and controller wiring that tracks an anchor and calls selectRange on shift-click.

Changes

Range Selection Feature

Layer / File(s) Summary
Selection API Contract
apps/web/src/timeline/controllers/element-interaction-controller.ts
ElementSelectionApi gains selectRange method accepting an optional anchor and required target, returning the selected element refs.
Range selection logic & hook export
apps/web/src/timeline/hooks/element/use-element-selection.ts
Adds selectElementRange (resolve target track via findTrackInSceneTracks, validate anchor on same track, order elements by startTime with stable tie-break, select inclusive slice between anchor and target, fallback to target-only) and returns it from the hook.
Controller wiring & anchor handling
apps/web/src/timeline/controllers/element-interaction-controller.ts, apps/web/src/timeline/hooks/element/use-element-interaction.ts
Controller stores elementSelectionAnchor, wires selection.selectRange to the hook callback, handles shift-mousedown by calling selectRange(anchor, target) and sets selectedElements from the returned range, and updates/preserves anchor during click handling with an early return for multi-selection/range paths.

Sequence Diagram

sequenceDiagram
  participant User
  participant ElementInteractionController
  participant ElementSelectionApi
  participant useElementSelection

  User->>ElementInteractionController: Shift+click targetElement
  ElementInteractionController->>ElementSelectionApi: selectRange(anchor?, target)
  ElementSelectionApi->>useElementSelection: selectElementRange(anchor?, target)
  useElementSelection->>useElementSelection: Resolve track & anchor
  useElementSelection->>useElementSelection: Order elements by startTime (stable)
  useElementSelection->>useElementSelection: Compute inclusive slice anchor→target
  useElementSelection-->>ElementSelectionApi: selectedElementRefs[]
  ElementSelectionApi-->>ElementInteractionController: selectedElementRefs[]
  ElementInteractionController->>ElementInteractionController: Update selectedElements & anchor
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped from anchor to end with a twitch of my paw,
Shifted the range and each clip found its place,
Ordered by time, tied indices kept pace,
From first click to target the selection did span,
A tiny rabbit cheer for a timeline well-planned.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description is minimal but adequate, referencing the linked issue and briefly describing the feature. However, it does not follow the repository's description template. Consider filling out the template sections relevant to this feature, or clarify if the maintainer approval mentioned in the template has been obtained.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding range selection functionality to element interaction, which is the primary focus of this PR.
Linked Issues check ✅ Passed The PR implementation meets all coding requirements from issue #801: adds selectRange method and anchor-based range selection [#801], preserves Ctrl/Cmd-click behavior [#801], and implements same-row fallback selection [#801].
Out of Scope Changes check ✅ Passed All changes are scoped to range selection functionality. The modifications add the selectRange method, anchor state management, and range selection logic—all directly aligned with issue #801 requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/timeline/hooks/element/use-element-selection.ts (1)

86-99: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Deduplicate incoming elements as well, not just overlap with current selection.

On Lines 88-98, duplicates inside elements survive the merge, so selection can contain repeated refs.

💡 Proposed fix
 const mergeElementsIntoSelection = useCallback(
 	({ elements }: { elements: ElementRef[] }) => {
-		const merged = [
-			...selectedElements.filter(
-				(selectedElement) =>
-					!elements.some(
-						(element) =>
-							element.trackId === selectedElement.trackId &&
-							element.elementId === selectedElement.elementId,
-					),
-			),
-			...elements,
-		];
+		const merged: ElementRef[] = [];
+		const seen = new Set<string>();
+		for (const element of [...selectedElements, ...elements]) {
+			const key = `${element.trackId}:${element.elementId}`;
+			if (seen.has(key)) continue;
+			seen.add(key);
+			merged.push(element);
+		}
 		editor.selection.setSelectedElements({ elements: merged });
 	},
 	[selectedElements, editor],
 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/timeline/hooks/element/use-element-selection.ts` around lines 86
- 99, mergeElementsIntoSelection currently only filters out incoming elements
that overlap with selectedElements but does not deduplicate duplicates within
the incoming elements array itself, allowing repeated ElementRef entries to be
merged into selection; update the function to first deduplicate the incoming
elements (based on element.trackId + element.elementId) before merging, then
build merged = [...existingFiltered, ...dedupedIncoming] and call
editor.selection.setSelectedElements with that merged list (refer to
mergeElementsIntoSelection, selectedElements, elements parameter, and
editor.selection.setSelectedElements).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/web/src/timeline/hooks/element/use-element-selection.ts`:
- Around line 86-99: mergeElementsIntoSelection currently only filters out
incoming elements that overlap with selectedElements but does not deduplicate
duplicates within the incoming elements array itself, allowing repeated
ElementRef entries to be merged into selection; update the function to first
deduplicate the incoming elements (based on element.trackId + element.elementId)
before merging, then build merged = [...existingFiltered, ...dedupedIncoming]
and call editor.selection.setSelectedElements with that merged list (refer to
mergeElementsIntoSelection, selectedElements, elements parameter, and
editor.selection.setSelectedElements).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7396d58d-c64e-4e5c-9de9-cd27c94b3b79

📥 Commits

Reviewing files that changed from the base of the PR and between 6fdb155 and 97db7aa.

📒 Files selected for processing (3)
  • apps/web/src/timeline/controllers/element-interaction-controller.ts
  • apps/web/src/timeline/hooks/element/use-element-interaction.ts
  • apps/web/src/timeline/hooks/element/use-element-selection.ts

@oguzhancttnky oguzhancttnky force-pushed the feature/shift-click-timeline-selection branch from e51e76d to e223348 Compare May 17, 2026 12:37
@oguzhancttnky oguzhancttnky force-pushed the feature/shift-click-timeline-selection branch from a9c37b9 to ae2b34e Compare May 17, 2026 18:54
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.

[FEATURE] Shift-click range selection for timeline clips

1 participant