Skip to content

fix(editor): apply Edit Clip as one save, and refuse Full Camera with no webcam - #444

Merged
EtienneLescot merged 2 commits into
mainfrom
claude/fix-355-353-clip-apply-and-camera-gate
Aug 21, 2026
Merged

fix(editor): apply Edit Clip as one save, and refuse Full Camera with no webcam#444
EtienneLescot merged 2 commits into
mainfrom
claude/fix-355-353-clip-apply-and-camera-gate

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Two independent bugs, one PR: both fixes land in useTimeline.ts and their tests interleave in useTimeline.test.ts. Splitting them into parallel PRs would guarantee a rebase for whichever merged second, for no reviewer benefit — each is its own commit, review them separately.

#355 — Apply loses one edit when source range and crop change together

Changing both and clicking Apply fired two independent saves built from the SAME pre-Apply document: the crop write never saw the source-range change, so whichever IPC write landed last silently dropped the other edit. No error, no toast, and the loser depends on timing — which is what reads as "the app randomly forgets my crop".

updateClipSourceRange + updateClipCrop are replaced by a single applyClipEdit that runs the shared setClipSourceRange recipe and then maps the crop onto the resequenced clips of that same document before saving once. That order is also the only one that can be right: resequencing changes which clips exist to be cropped.

Two supporting details. The document is read from the store rather than the render closure — the idiom setTrimEntries and insertClipAt already use — so the call is safe to queue; and Apply now goes through enqueueTimelineWrite, since this race is exactly what useSequentialTimelineOps exists to prevent.

The test asserts both edits survive and that save was called exactly once; a second pins the modal's tri-state crop contract (undefined = untouched, null = cleared).

#353 — Full Camera on a project with no webcam

The toolbar button and the C shortcut wrote a camera-fullscreen region on projects with no webcam at all. It persisted, rendered nothing in preview and nothing in export — effectiveLayout short-circuits with no webcamRect to grow — and the user got no feedback, ever. The agent's own tool already refused this exact action and said why, so the app contradicted itself depending on which entry point you used.

The gate goes on the shared mutation, keyed on hasAnyClipWithCamera — the consolidated answer the Layout pane already uses — so both entry points and any future one are covered by construction rather than one guard per button.

Then the surfaces are made honest before they are clicked: the toolbar button is disabled and dimmed, and the empty lane stops advertising "Press C to add a Full Camera segment".

That lane was found during a visual pass, after the button was already correct — the fix was half-honest and no unit test would have caught it. It borrows the Layout pane's existing "No Webcam" wording, so the two surfaces agree about the same project and no new locale keys are needed. Verified on screen: the camera lane reads "No Webcam" while the others keep their shortcut hints.

A sweep for callers that depended on the mutation always writing turned up none. The agent path (electron/ai-edition/agent-tools.ts) has its own implementation and its own gate, and does not go through this hook, so its tests are unaffected.

Fixes #355
Fixes #353

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Clip source-range and crop changes now save together, preventing one edit from overwriting the other.
    • Crop settings can be preserved or cleared reliably when editing clips.
    • Camera fullscreen actions are unavailable when no webcam footage exists.
    • The timeline now displays a clear “No Webcam” message when no camera track is present.
    • Fullscreen camera regions are no longer created without a valid camera source.
  • Documentation

    • Clarified that crop settings previously applied across the entire document.

…t, one save

Changing both the source range and the crop and clicking Apply fired two
independent saves built from the SAME pre-Apply document: the crop write never
saw the source-range change, so whichever IPC write landed last silently
dropped the other edit. No error, no toast, and the loser depends on timing —
which is what reads as "the app randomly forgets my crop".

Replace the two hook methods with a single `applyClipEdit` that runs the shared
`setClipSourceRange` recipe and then maps the crop onto the *resequenced* clips
of that same document before saving once. That order is also the only one that
can be right: resequencing changes which clips exist to be cropped.

Two supporting details. The document is read from the store rather than the
render closure, the idiom `setTrimEntries` and `insertClipAt` already use, so
the call is safe to queue; and Apply now goes through `enqueueTimelineWrite`,
the serialisation this race is exactly what `useSequentialTimelineOps` exists to
prevent.

Fixes #355
The toolbar button and the `C` shortcut wrote a camera-fullscreen region on
projects with no webcam at all. The region persisted into
`legacyEditor.cameraFullscreenRegions`, rendered nothing in the preview and
nothing in the export — `effectiveLayout` short-circuits with no `webcamRect` to
grow — and the user got no feedback, ever. The agent's own tool already refused
this exact action and said why, so the app contradicted itself depending on
which entry point you used.

Gate the shared mutation on `hasAnyClipWithCamera`, the consolidated answer the
Layout pane already uses, so both UI entry points and any future one are covered
by construction rather than one guard per button.

Then make the surfaces honest before they are clicked: the toolbar button is
disabled and dimmed, and the empty lane stops advertising "Press C to add a Full
Camera segment" — it borrows the Layout pane's existing "No Webcam" wording, so
the two surfaces agree about the same project and no new locale keys are needed.
The lane was found still inviting the keystroke during a visual pass, after the
button was already correct.

Fixes #353
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 079440fa-49dd-44bc-8895-d0f092893ecb

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc63df and 3bb220e.

📒 Files selected for processing (6)
  • src/components/ai-edition/Modals.tsx
  • src/components/ai-edition/NewEditorShell.tsx
  • src/components/ai-edition/v4/V4Timeline.geometry.test.tsx
  • src/components/ai-edition/v4/V4Timeline.tsx
  • src/lib/ai-edition/store/useTimeline.test.ts
  • src/lib/ai-edition/store/useTimeline.ts

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The timeline store now applies source-range and crop edits in one save. Camera fullscreen actions are blocked when no camera exists. The timeline UI shows disabled controls and a no-webcam message for camera-less assets.

Changes

Timeline editing and camera availability

Layer / File(s) Summary
Atomic clip edit persistence
src/lib/ai-edition/store/useTimeline.ts, src/lib/ai-edition/store/useTimeline.test.ts
applyClipEdit combines source-range and crop updates in one save. Tests cover crop preservation, removal, and range adjustment behavior.
Edit modal integration
src/components/ai-edition/NewEditorShell.tsx, src/components/ai-edition/Modals.tsx
The edit handler submits source-range and optional crop changes through applyClipEdit. The related documentation comment reflects the updated API.
Camera fullscreen validation
src/lib/ai-edition/store/useTimeline.ts, src/lib/ai-edition/store/useTimeline.test.ts
addCameraFullscreen returns without writing when no timeline clip has camera media. Tests cover both no-camera and valid-camera cases.
Camera-aware timeline controls
src/components/ai-edition/v4/V4Timeline.tsx, src/components/ai-edition/v4/V4Timeline.geometry.test.tsx
Camera fullscreen controls are disabled without camera media. The empty lane displays the no-webcam message, with tests for both camera states.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Merge Risk: ⚪ Minimal · up to 3bb22

The PR makes clip edits save atomically and prevents Full Camera actions when no webcam exists; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: arhxam

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes both primary fixes: atomic Edit Clip saves and blocking Full Camera without a webcam.
Description check ✅ Passed The description thoroughly explains both bugs, fixes, linked issues, and validation, although it does not use every template heading or checkbox.
Linked Issues check ✅ Passed The changes satisfy issues #355 and #353 by combining edits into one save and preventing camera regions without a webcam.
Out of Scope Changes check ✅ Passed The code, tests, UI changes, and documentation update directly support the two linked issue objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-355-353-clip-apply-and-camera-gate

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.

@EtienneLescot

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@EtienneLescot
EtienneLescot merged commit 742046a into main Aug 21, 2026
18 checks passed
@EtienneLescot
EtienneLescot deleted the claude/fix-355-353-clip-apply-and-camera-gate branch August 21, 2026 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant