Conversation
Adds a user-toggleable mirror (horizontal flip) for the self-view video. Previously, the self-view was always mirrored via scaleX(-1). Now users can toggle mirroring on/off, and the preference persists in localStorage. The toggle is available in two places: - Waiting Room: a badge-style Flip icon button in the upper-right corner of the video tile (aligned with the Background Effects badge) - Conference Room: a toggle menu item in the camera device dropdown, always visible on all browsers (not gated by media processor support), following the same pattern as Advanced Noise Suppression in the audio menu Key design decisions: - Default: mirrored (true) — preserves existing behaviour - Inverted transform logic: SDK mirrors via .OT_mirrored; when mirror is ON we set transform:none, when OFF we apply scaleX(-1) to cancel it - objectFit changed from contain to cover across all three video components - Preference stored as localStorage key mirrorSelfView - i18n keys added for en, es, es-MX, it locales - Fixed pre-existing no-floating-promises lint error in useSuspenseUntilAppConfigReady Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add mirrorSelfView: true to user.spec.tsx expected defaultSettings - Add UserProvider wrapper to BackgroundVideoContainer.spec.tsx (component now uses useUserContext) - Update DeviceSettingsMenu.spec.tsx: add providers.user and userContext to RenderOptions, use queryAllByTestId for dropdown-separator (two separators now rendered) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove providers.appConfig (does not exist in current codebase) - Use providers.user only for MirrorSelfViewToggle context - Restore env.partialUpdate for ALLOW_BACKGROUND_EFFECTS test - Remove appConfigContext from RenderOptions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ainer - Replace transform:'none' with removeProperty/'' so SDK's .OT_mirrored CSS (scale(-1,1) on .OT_video-element) is not inadvertently overridden when mirror is ON - Use scaleX(1) when mirror is OFF to correctly cancel SDK's scale(-1,1) - Remove unused isSMViewport hook and dep from BackgroundVideoContainer effect Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…line The react-hooks/immutability rule fires on direct property assignments (`element.style.transform = 'scaleX(1)'`) but not on method calls (`removeProperty`) or ternary assignments. The disable comments were placed on the wrong lines — moved to sit immediately above the assignment that actually triggers the rule, and removed the now-unused disable in BackgroundVideoContainer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
vcr:deploy |
There was a problem hiding this comment.
Pull request overview
Adds a user-controlled “Mirror Self View” preference (default ON) persisted in localStorage, and wires it into waiting-room preview + in-call publisher rendering, along with UI controls in both rooms.
Changes:
- Add
MIRROR_SELF_VIEWstorage key and newmirrorSelfViewdefault setting inUserContext. - Introduce waiting-room icon button and meeting-room device-menu toggle to update/persist mirroring.
- Apply mirror/object-fit behavior to preview publisher, in-call publisher, and background-effects preview; refactor parts of the device menu styling to Tailwind/Vera tokens.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/utils/storage.ts | Adds MIRROR_SELF_VIEW key for persistence. |
| frontend/src/Context/user.tsx | Loads mirrorSelfView from storage (default true) into UserContext. |
| frontend/src/Context/tests/user.spec.tsx | Updates expected defaults to include mirrorSelfView. |
| frontend/src/Context/PublisherProvider/usePublisherQuality/usePublisherQuality.spec.tsx | Updates mocked UserContextType with mirrorSelfView. |
| frontend/src/components/WaitingRoom/VideoContainerButton/VideoContainerButton.tsx | Adds className support and moves sizing/padding toward Tailwind utilities. |
| frontend/src/components/WaitingRoom/VideoContainer/VideoContainer.tsx | Applies object-fit: cover and conditional mirroring to the waiting-room preview; adds the mirror button to the tile. |
| frontend/src/components/WaitingRoom/MirrorSelfViewButton/index.tsx | Exposes the new waiting-room mirror toggle button. |
| frontend/src/components/WaitingRoom/MirrorSelfViewButton/MirrorSelfViewButton.tsx | New waiting-room mirror toggle UI + persistence via UserContext and storage. |
| frontend/src/components/Publisher/Publisher.tsx | Applies object-fit: cover and conditional mirroring to the in-call publisher video element. |
| frontend/src/components/BackgroundEffects/BackgroundVideoContainer/BackgroundVideoContainer.tsx | Applies conditional mirroring + object-fit: cover for background-effects preview. |
| frontend/src/components/BackgroundEffects/BackgroundVideoContainer/BackgroundVideoContainer.spec.tsx | Wraps tests with UserProvider to satisfy new UserContext dependency. |
| frontend/src/components/MeetingRoom/MirrorSelfViewToggle/MirrorSelfViewToggle.tsx | New menu-item toggle for mirroring in the camera device dropdown. |
| frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.tsx | Adds the mirror toggle to the video menu and refactors Popper/Paper styling to Tailwind classes. |
| frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx | Updates test expectations and ensures UserContext is provided. |
| frontend/src/locales/en.json | Adds devices.video.mirrorSelfView string. |
| frontend/src/locales/de.json | Adds devices.video.mirrorSelfView string. |
| frontend/src/locales/es.json | Adds devices.video.mirrorSelfView string. |
| frontend/src/locales/es-MX.json | Adds devices.video.mirrorSelfView string. |
| frontend/src/locales/it.json | Adds devices.video.mirrorSelfView string. |
You can also share your feedback on Copilot code review. Take the survey.
frontend/src/components/WaitingRoom/VideoContainerButton/VideoContainerButton.tsx
Outdated
Show resolved
Hide resolved
frontend/src/components/WaitingRoom/MirrorSelfViewButton/MirrorSelfViewButton.tsx
Outdated
Show resolved
Hide resolved
frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
Outdated
Show resolved
Hide resolved
| const isSdkMirroring = publisherVideoElement.classList.contains('OT_mirrored'); | ||
| // The SDK mirrors the preview publisher via .OT_mirrored (scale(-1, 1) on .OT_video-element). | ||
| // When mirror is ON, prefer the SDK class; fall back to an inline mirror if the class is absent. | ||
| // When mirror is OFF, set scaleX(1) to override and cancel the SDK's mirror. | ||
| if (mirrorSelfView) { | ||
| if (isSdkMirroring) { | ||
| publisherVideoElement.style.removeProperty('transform'); | ||
| } else { | ||
| // eslint-disable-next-line react-hooks/immutability | ||
| publisherVideoElement.style.transform = 'scaleX(-1)'; | ||
| } | ||
| } else { | ||
| publisherVideoElement.style.transform = 'scaleX(1)'; | ||
| } |
There was a problem hiding this comment.
@copilot apply changes based on this feedback
|
vcr:deploy |
✅ Deployed to VCRURL: https://neru-ca37991c-vonage-video-react-app-vera-pr-414.euw1.runtime.vonage.cloud Commit: |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@czoli1976 I've opened a new pull request, #415, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
|
@VZaphod I am dropping it, lack of consensus |


Hi team! 👋
Resolves VIDSOL-619
Checklist
develop(notmain).Known Issue.docs/KNOWN_ISSUES.md?Issues.What is this PR doing?
Adds a Mirror Self View toggle so users can choose whether their preview is mirrored. Default is ON (mirrored) and
persisted in localStorage.
Where it appears:
Mirror behavior:
scaleX(-1) inline.
Styling refactor:
Manual test notes remain the same; ensure toggles update immediately and persist on refresh across browsers.
Mirror logic:
mirrorSelfViewtrue(default)none— the SDK's.OT_mirroredclass handles the flipfalsescaleX(-1)— cancels the SDK mirrorChanges:
storage.ts— AddedMIRROR_SELF_VIEWkeyuser.tsx— AddedmirrorSelfView: booleantoUserContext/UserProvider, loaded fromlocalStorageMirrorSelfViewButton.tsx(new) — Waiting room icon buttonMirrorSelfViewToggle.tsx(new) — Conference room toggle menu itemVideoContainer.tsx— Replaced static Tailwindchild:-scale-x-100with reactiveuseEffect; addedMirrorSelfViewButtonPublisher.tsx— Dynamic transform viauseEffect;objectFit: coverBackgroundVideoContainer.tsx— Dynamic transform +objectFit: coveren.json,es.json,es-MX.json,it.json— Addeddevices.video.mirrorSelfViewi18n keyuser.spec.tsx,BackgroundVideoContainer.spec.tsx,DeviceSettingsMenu.spec.tsx— Updated testsHow should this be manually tested?
Waiting room:
Conference room:
Tested on macOS Tahoe 26.3 (arm64):
Instructions for Testing
Setup:
22.
Waiting room:
- ON → video mirrored. OFF → unmirrored.
Meeting room:
- ON → mirrored; OFF → unmirrored.
Fallback:
Cross-browser:
Persistence:
Regression: