desktop app: improve trimming behaviour
This PR: previously if you trim the first clip or segment, it would go under the next one. This PR prevents that.
https://github.com/user-attachments/assets/af4d310d-079e-4d3c-9b3c-4e1592701cdb
Summary by CodeRabbit
-
Bug Fixes
- Improved timeline dragging to prevent segment overlap and ensure coordinated dragging across segments.
- Prevented proposing zoom segments when there isnβt enough space for the minimum duration.
- Removed stray debug console output from timeline editing.
-
UI
- Adjusted visual stacking during drags and zoom previews for clearer layering and focus.
Walkthrough
Introduces a shared drag-tracking state to coordinate dragging across timeline segments, clamps start/end to avoid overlaps, adjusts z-index during active drags, and tightens zoom-segment proposal guards to only return proposals when minimum duration and next-segment bounds permit.
Changes
| Cohort / File(s) | Change Summary |
|---|---|
Drag state coordination apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx |
Adds shared activeDragState for cross-segment dragging; computes relative segment positions using current and previous segment offsets and clamps to avoid overlap; sets/clears shared state on drag start/cleanup; adds conditional z-50 elevation when dragging; removes stray console log and some inline prev-segment comparison logic. |
Zoom segment validation & layering apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsx |
Replaces fallback segment construction with guards that return undefined when space < minDuration; computes max bound from next segment start or total duration and ensures max - previewTime >= minDuration; uses computed max for proposals; adjusts UI stacking classes (z-10 for main container, z-0 for placeholder). |
Sequence Diagram(s)
sequenceDiagram
participant User
participant ClipTrack as ClipTrack Component
participant ActiveState as activeDragState (shared)
participant PrevSegment as Previous Segment
participant Renderer
Note over User,ClipTrack: Start dragging a segment handle
User ->> ClipTrack: pointerdown(start handle)
ClipTrack ->> ClipTrack: compute local offset, set startHandleDrag
ClipTrack ->> ActiveState: setActiveDragState({ index, offset })
ActiveState -->> ClipTrack: shared state stored
Note over ClipTrack,PrevSegment: During drag updates
User ->> ClipTrack: pointermove(delta)
ClipTrack ->> ClipTrack: compute proposedStart = base + localOffset + prevOffset
ClipTrack ->> ClipTrack: clampedStart = clamp(proposedStart, min, prevEnd)
ClipTrack ->> Renderer: render segment with clampedStart (z-50 if active)
Note over ClipTrack,ActiveState: On drag end/cleanup
User ->> ClipTrack: pointerup
ClipTrack ->> ClipTrack: clear startHandleDrag
ClipTrack ->> ActiveState: setActiveDragState(null)
ClipTrack ->> Renderer: render final state
Estimated code review effort
π― 3 (Moderate) | β±οΈ ~20β25 minutes
- Review focus:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsxβ correctness of offset accumulation, clamping logic, and shared state lifecycle (race conditions on async set).apps/desktop/src/routes/editor/Timeline/ZoomTrack.tsxβ correctness of new guards (edge cases when next segment is adjacent) and the computedmaxboundary.- UI z-index adjustments for unintended stacking regressions in overlapping UI states.
Possibly related PRs
- CapSoftware/Cap#1273: Modifies
ClipTrack.tsxdrag/trim logic β likely overlapping changes to shared drag state and start-handle calculations. - CapSoftware/Cap#1213: Changes to zoom/segment creation and per-track hover/drag behavior β related to
ZoomTrack.tsxvalidation and UI state.
Suggested labels
Desktop
Suggested reviewers
- Brendonovich
Poem
π°
I nudged the clips so timelines glide,
Offsets synced, no overlaps to hide.
Zooms now check the space before they play,
Layers stack tidy β hop, hooray! π₯
Pre-merge checks and finishing touches
β Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | β οΈ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
β Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. |
| Title Check | β Passed | The title "desktop app: improve trimming behaviour" directly aligns with the PR's stated objective and the changes made in both affected files. The PR explicitly addresses a bug where trimming the first clip or segment causes it to overlap with the following segment, and the changes implement this fix through enhanced overlap prevention logic (clamping in ClipTrack and boundary checks in ZoomTrack) and improved z-index handling. The title is clear, concise, and appropriately describes the main intent without being vague or misleading. |
β¨ Finishing touches
- [ ] π Generate docstrings
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
improve-trimming-behaviour
π Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π₯ Commits
Reviewing files that changed from the base of the PR and between 7f86cfdf804e896e258ebfabbd5f675909eb03ea and fc60532ee79fe6fff6d9761e8a77f86d426c9c01.
π Files selected for processing (1)
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx(5 hunks)
π§° Additional context used
π Path-based instructions (2)
**/*.{ts,tsx}
π CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code. Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.
Files:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
**/*.{ts,tsx,js,jsx}
π CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx). Use PascalCase for React/Solid components.
Files:
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx
𧬠Code graph analysis (1)
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx (1)
packages/database/auth/auth-options.ts (1)
maxDuration(20-20)
β° Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
π Additional comments (4)
apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx (4)
200-204: Excellent approach to coordinate drag state across segments.The shared
activeDragStatesignal effectively enables subsequent segments to adjust their visual position when a previous segment is being trimmed, preventing the overlap issue described in the PR.
409-409: Visual elevation during drag works perfectly.The conditional
z-50class ensures the segment being trimmed always renders above adjacent segments, directly addressing the overlap issue shown in the PR demo.
555-580: Improved overlap prevention logic.The removal of the
prevSegmentIsSameClipcheck correctly ensures no overlap occurs regardless of clip boundaries, which aligns with the PR objective.One observation: the
activeDragStateupdate (lines 575-580) happens asynchronously viarequestAnimationFrame, while the project update (lines 582-588) is synchronous. This batching improves performance but could theoretically cause a one-frame delay before subsequent segments adjust their position.Please verify during manual testing that rapid dragging doesn't produce noticeable visual lag or "jumping" of subsequent segments.
596-596: Proper cleanup of shared drag state.Resetting
activeDragStatetonullon cleanup correctly prevents stale offset values from affecting subsequent segments after the drag operation completes.
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.
Comment @coderabbitai help to get the list of available commands and usage tips.