Skip to content

Add webcam mirror toggle#633

Open
AjTheSpidey wants to merge 2 commits into
siddharthvaddem:mainfrom
AjTheSpidey:codex/webcam-mirror-toggle
Open

Add webcam mirror toggle#633
AjTheSpidey wants to merge 2 commits into
siddharthvaddem:mainfrom
AjTheSpidey:codex/webcam-mirror-toggle

Conversation

@AjTheSpidey
Copy link
Copy Markdown
Contributor

@AjTheSpidey AjTheSpidey commented May 21, 2026

Fixes #632.

Added a Mirror webcam switch in the editor layout panel. When it is on, the webcam flips in the preview and the same flip is used during GIF/MP4 export, so the saved file matches what you see while editing.

Tested locally:

  • npx biome check --write on the touched files
  • npx vitest --run src/components/video-editor/projectPersistence.test.ts src/lib/exporter/frameRenderer.test.ts
  • npm run build-vite

One note: full npm run lint still hits existing formatter/line-ending errors in untouched repo files, so I kept the check scoped to the files changed here.

Summary by CodeRabbit

  • New Features

    • Added a "Mirror webcam" toggle in the settings panel (default: off).
    • Mirrored webcam preview in playback and applied to video/GIF exports.
    • Mirror setting is persisted with projects and restored on load.
  • Tests

    • Added unit tests covering mirrored and non-mirrored webcam frame drawing and project state normalization.
  • Localization

    • Added "Mirror webcam" translations across multiple languages.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

PR implements horizontal webcam mirroring across the entire app: adds a mirror toggle to SettingsPanel, threads the setting through editor state and project persistence, applies live preview mirroring via CSS transform in VideoPlayback, and exports mirrored frames via a new canvas utility in GIF and MP4 outputs.

Changes

Webcam Mirroring Feature

Layer / File(s) Summary
Core types and default constant
src/components/video-editor/types.ts, src/lib/exporter/webcamFrameDrawing.ts
Adds DEFAULT_WEBCAM_MIRRORED constant and introduces WebcamFrameCrop and WebcamCanvasContext.
Canvas drawing utility + tests
src/lib/exporter/webcamFrameDrawing.ts, src/lib/exporter/frameRenderer.test.ts
Implements drawWebcamFrameImage with optional horizontal mirroring and unit tests for normal, mirrored, and failure paths.
Export pipeline integration
src/lib/exporter/frameRenderer.ts, src/lib/exporter/gifExporter.ts, src/lib/exporter/videoExporter.ts
Replaces inlined webcam draw with drawWebcamFrameImage and threads webcamMirrored through FrameRenderer, GifExporter, and VideoExporter.
Editor state and project persistence
src/hooks/useEditorHistory.ts, src/components/video-editor/projectPersistence.ts, src/components/video-editor/projectPersistence.test.ts
Adds webcamMirrored: boolean to editor/project state, initializes default, normalizes loaded projects, and tests normalization behavior.
UI controls, preview rendering, and wiring
src/components/video-editor/SettingsPanel.tsx, src/components/video-editor/VideoPlayback.tsx, src/components/video-editor/VideoEditor.tsx
Adds mirror toggle to SettingsPanel, applies scaleX(-1) to webcam preview in VideoPlayback when enabled, and threads the setting through VideoEditor into saves/exports.
Localization updates
src/i18n/locales/*/settings.json
Adds mirrorWebcam (and related noWebcam/webcamSize adjustments) to multiple locale files for the new UI label.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • siddharthvaddem

Poem

a toggle whispers "flip me" in the settings light
preview tilts its face, mirrored just right
exports learn the secret, canvas does its dance
tiny feature, lowkey cursed, now given a chance ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. 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 and concisely summarizes the main change: adding a mirror toggle for the webcam feature.
Description check ✅ Passed The description provides context (fixes #632), explains the feature (Mirror webcam switch), describes testing steps, but doesn't fully populate the template sections like Type of Change or a proper checklist.
Linked Issues check ✅ Passed The PR fully implements the objective from #632: adds a webcam mirror toggle that flips the image horizontally in preview and during export (GIF/MP4).
Out of Scope Changes check ✅ Passed All changes are directly related to the webcam mirroring feature: state management, UI controls, rendering logic, export configuration, and i18n strings for the feature.

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

Actionable comments posted: 2

🤖 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.

Inline comments:
In `@src/components/video-editor/SettingsPanel.tsx`:
- Around line 1194-1199: The "Mirror webcam" label and its aria-label are
hardcoded; replace both with your i18n lookup (e.g., use the t function from
your translation hook) so the text and aria-label are localized. In
SettingsPanel (where webcamMirrored and onWebcamMirroredChange are used) change
"Mirror webcam" to something like t('settings.mirrorWebcam') and the Switch
aria-label to t('settings.mirrorWebcamAria') (and add those keys to the locale
files), ensuring you import/use the existing translation hook (e.g., const { t }
= useTranslation()) in the component.

In `@src/lib/exporter/webcamFrameDrawing.ts`:
- Around line 20-26: The mirrored branch in webcamFrameDrawing uses ctx.save(),
ctx.translate(...), ctx.scale(...), ctx.drawImage(...), then ctx.restore(); but
if drawImage throws the transform leaks—wrap the transform and draw in a
try/finally so ctx.restore() always runs; specifically locate the mirrored
handling block that calls ctx.save(), ctx.translate, ctx.scale and ctx.drawImage
and ensure restore() is invoked in finally before returning from the function.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 25b5b6c5-a18f-4633-ab71-fa740eb019d9

📥 Commits

Reviewing files that changed from the base of the PR and between 9f7f498 and 411f9a3.

📒 Files selected for processing (12)
  • src/components/video-editor/SettingsPanel.tsx
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/VideoPlayback.tsx
  • src/components/video-editor/projectPersistence.test.ts
  • src/components/video-editor/projectPersistence.ts
  • src/components/video-editor/types.ts
  • src/hooks/useEditorHistory.ts
  • src/lib/exporter/frameRenderer.test.ts
  • src/lib/exporter/frameRenderer.ts
  • src/lib/exporter/gifExporter.ts
  • src/lib/exporter/videoExporter.ts
  • src/lib/exporter/webcamFrameDrawing.ts

Comment thread src/components/video-editor/SettingsPanel.tsx Outdated
Comment thread src/lib/exporter/webcamFrameDrawing.ts
@AjTheSpidey AjTheSpidey force-pushed the codex/webcam-mirror-toggle branch from e5f023c to 2cf09a8 Compare May 24, 2026 01:00
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.

🧹 Nitpick comments (3)
src/i18n/locales/en/settings.json (2)

48-49: 💤 Low value

capitalization inconsistency between webcam labels

line 48 uses "Webcam Size" (capital W) but line 49 uses "Mirror webcam" (lowercase w). kinda inconsistent but lowkey not a blocker since both are readable. might wanna decide on one style tho

🤖 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 `@src/i18n/locales/en/settings.json` around lines 48 - 49, The two i18n entries
are inconsistent in capitalization—"webcamSize" value is "Webcam Size" but
"mirrorWebcam" value is "Mirror webcam"; update the "mirrorWebcam" value to
"Mirror Webcam" to match Title Case used by "webcamSize" (and audit other locale
files for the same keys to keep translations consistent across languages).

3-3: 💤 Low value

unrelated localization change detected

this line modifies zoom.previewHold which isn't part of the webcam mirror feature. same with line 116's jpgOnly change. these look like cleanup/improvements but weren't mentioned in the pr summary. not blocking but worth noting for commit hygiene

🤖 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 `@src/i18n/locales/en/settings.json` at line 3, This change modifies unrelated
localization keys ("previewHold" under zoom/zoom.previewHold and "jpgOnly"
elsewhere in settings.json) that are not part of the webcam mirror feature;
revert those localization edits or move them into a separate commit/PR and
update the PR description accordingly so this branch only contains webcam mirror
changes, referencing the keys "previewHold" and "jpgOnly" when making the revert
or split.
src/components/video-editor/SettingsPanel.tsx (1)

443-444: ⚡ Quick win

nit: keep webcamMirrored default aligned with shared defaults

Line 443 uses a literal false; lowkey risky for drift if DEFAULT_WEBCAM_MIRRORED changes later. Prefer the shared constant for SSOT consistency.

♻️ Proposed tweak
 import {
+	DEFAULT_WEBCAM_MIRRORED,
 	MAX_ZOOM_SCALE,
 	MIN_ZOOM_SCALE,
 	ROTATION_3D_PRESET_ORDER,
 	SPEED_OPTIONS,
 	ZOOM_DEPTH_SCALES,
 } from "./types";
@@
-	webcamMirrored = false,
+	webcamMirrored = DEFAULT_WEBCAM_MIRRORED,
🤖 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 `@src/components/video-editor/SettingsPanel.tsx` around lines 443 - 444, The
prop default for webcamMirrored in the SettingsPanel component should use the
shared constant instead of a hardcoded false; replace the literal default
(webcamMirrored = false) with the shared DEFAULT_WEBCAM_MIRRORED and ensure
DEFAULT_WEBCAM_MIRRORED is imported from the central defaults module so the
SettingsPanel (and its prop signature referencing webcamMirrored and
onWebcamMirroredChange) stays single-source-of-truth.
🤖 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.

Nitpick comments:
In `@src/components/video-editor/SettingsPanel.tsx`:
- Around line 443-444: The prop default for webcamMirrored in the SettingsPanel
component should use the shared constant instead of a hardcoded false; replace
the literal default (webcamMirrored = false) with the shared
DEFAULT_WEBCAM_MIRRORED and ensure DEFAULT_WEBCAM_MIRRORED is imported from the
central defaults module so the SettingsPanel (and its prop signature referencing
webcamMirrored and onWebcamMirroredChange) stays single-source-of-truth.

In `@src/i18n/locales/en/settings.json`:
- Around line 48-49: The two i18n entries are inconsistent in
capitalization—"webcamSize" value is "Webcam Size" but "mirrorWebcam" value is
"Mirror webcam"; update the "mirrorWebcam" value to "Mirror Webcam" to match
Title Case used by "webcamSize" (and audit other locale files for the same keys
to keep translations consistent across languages).
- Line 3: This change modifies unrelated localization keys ("previewHold" under
zoom/zoom.previewHold and "jpgOnly" elsewhere in settings.json) that are not
part of the webcam mirror feature; revert those localization edits or move them
into a separate commit/PR and update the PR description accordingly so this
branch only contains webcam mirror changes, referencing the keys "previewHold"
and "jpgOnly" when making the revert or split.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8f5111de-6ac6-43ad-9450-4393b2c9d557

📥 Commits

Reviewing files that changed from the base of the PR and between e5f023c and 2cf09a8.

📒 Files selected for processing (24)
  • src/components/video-editor/SettingsPanel.tsx
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/VideoPlayback.tsx
  • src/components/video-editor/projectPersistence.test.ts
  • src/components/video-editor/projectPersistence.ts
  • src/components/video-editor/types.ts
  • src/hooks/useEditorHistory.ts
  • src/i18n/locales/ar/settings.json
  • src/i18n/locales/en/settings.json
  • src/i18n/locales/es/settings.json
  • src/i18n/locales/fr/settings.json
  • src/i18n/locales/it/settings.json
  • src/i18n/locales/ja-JP/settings.json
  • src/i18n/locales/ko-KR/settings.json
  • src/i18n/locales/ru/settings.json
  • src/i18n/locales/tr/settings.json
  • src/i18n/locales/vi/settings.json
  • src/i18n/locales/zh-CN/settings.json
  • src/i18n/locales/zh-TW/settings.json
  • src/lib/exporter/frameRenderer.test.ts
  • src/lib/exporter/frameRenderer.ts
  • src/lib/exporter/gifExporter.ts
  • src/lib/exporter/videoExporter.ts
  • src/lib/exporter/webcamFrameDrawing.ts
✅ Files skipped from review due to trivial changes (7)
  • src/i18n/locales/ru/settings.json
  • src/i18n/locales/ar/settings.json
  • src/i18n/locales/es/settings.json
  • src/i18n/locales/fr/settings.json
  • src/i18n/locales/vi/settings.json
  • src/i18n/locales/tr/settings.json
  • src/i18n/locales/it/settings.json

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]: Flip webcam video (horizontal / mirroring)

1 participant