Add webcam mirror toggle#633
Conversation
📝 WalkthroughWalkthroughPR 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. ChangesWebcam Mirroring Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ 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
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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 |
There was a problem hiding this comment.
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
📒 Files selected for processing (12)
src/components/video-editor/SettingsPanel.tsxsrc/components/video-editor/VideoEditor.tsxsrc/components/video-editor/VideoPlayback.tsxsrc/components/video-editor/projectPersistence.test.tssrc/components/video-editor/projectPersistence.tssrc/components/video-editor/types.tssrc/hooks/useEditorHistory.tssrc/lib/exporter/frameRenderer.test.tssrc/lib/exporter/frameRenderer.tssrc/lib/exporter/gifExporter.tssrc/lib/exporter/videoExporter.tssrc/lib/exporter/webcamFrameDrawing.ts
e5f023c to
2cf09a8
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/i18n/locales/en/settings.json (2)
48-49: 💤 Low valuecapitalization 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 valueunrelated localization change detected
this line modifies
zoom.previewHoldwhich isn't part of the webcam mirror feature. same with line 116'sjpgOnlychange. 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 winnit: keep
webcamMirroreddefault aligned with shared defaultsLine 443 uses a literal
false; lowkey risky for drift ifDEFAULT_WEBCAM_MIRROREDchanges 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
📒 Files selected for processing (24)
src/components/video-editor/SettingsPanel.tsxsrc/components/video-editor/VideoEditor.tsxsrc/components/video-editor/VideoPlayback.tsxsrc/components/video-editor/projectPersistence.test.tssrc/components/video-editor/projectPersistence.tssrc/components/video-editor/types.tssrc/hooks/useEditorHistory.tssrc/i18n/locales/ar/settings.jsonsrc/i18n/locales/en/settings.jsonsrc/i18n/locales/es/settings.jsonsrc/i18n/locales/fr/settings.jsonsrc/i18n/locales/it/settings.jsonsrc/i18n/locales/ja-JP/settings.jsonsrc/i18n/locales/ko-KR/settings.jsonsrc/i18n/locales/ru/settings.jsonsrc/i18n/locales/tr/settings.jsonsrc/i18n/locales/vi/settings.jsonsrc/i18n/locales/zh-CN/settings.jsonsrc/i18n/locales/zh-TW/settings.jsonsrc/lib/exporter/frameRenderer.test.tssrc/lib/exporter/frameRenderer.tssrc/lib/exporter/gifExporter.tssrc/lib/exporter/videoExporter.tssrc/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
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:
One note: full
npm run lintstill 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
Tests
Localization