From 6f09eb36029e9aa3c8f5182d59d467b0bf5bbaf2 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Thu, 13 Feb 2025 16:16:05 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8(frontend)=20add=20warning=20for=20?= =?UTF-8?q?full=20screen=20capture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following user feedback about infinite loops risks, add warning overlay when users attempt to share their entire screen. The warning explains the risk and suggests sharing a specific tab instead, providing options to stop sharing or dismiss the warning while respecting user preferences for future sessions. --- .../components/FullScreenShareWarning.tsx | 121 ++++++++++++++++++ .../livekit/components/ParticipantTile.tsx | 2 + src/frontend/src/locales/de/rooms.json | 5 + src/frontend/src/locales/en/rooms.json | 5 + src/frontend/src/locales/fr/rooms.json | 5 + .../src/stores/ScreenSharePreferences.ts | 9 ++ 6 files changed, 147 insertions(+) create mode 100644 src/frontend/src/features/rooms/livekit/components/FullScreenShareWarning.tsx create mode 100644 src/frontend/src/stores/ScreenSharePreferences.ts diff --git a/src/frontend/src/features/rooms/livekit/components/FullScreenShareWarning.tsx b/src/frontend/src/features/rooms/livekit/components/FullScreenShareWarning.tsx new file mode 100644 index 00000000..f82d070b --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/FullScreenShareWarning.tsx @@ -0,0 +1,121 @@ +import { css } from '@/styled-system/css' +import { Button, Text } from '@/primitives' +import { useMemo, useRef } from 'react' +import { ScreenSharePreferenceStore } from '@/stores/ScreenSharePreferences' +import { useSnapshot } from 'valtio' +import { useLocalParticipant } from '@livekit/components-react' +import { useSize } from '../hooks/useResizeObserver' +import { TrackReferenceOrPlaceholder } from '@livekit/components-core' +import { useTranslation } from 'react-i18next' + +export const FullScreenShareWarning = ({ + trackReference, +}: { + trackReference: TrackReferenceOrPlaceholder +}) => { + const { t } = useTranslation('rooms', { keyPrefix: 'fullScreenWarning' }) + + const warningContainerRef = useRef(null) + const { width: containerWidth } = useSize(warningContainerRef) + const { localParticipant } = useLocalParticipant() + const screenSharePreferences = useSnapshot(ScreenSharePreferenceStore) + + const isFullScreenCapture = useMemo(() => { + const trackLabel = + trackReference.publication?.track?.mediaStreamTrack?.label + return trackLabel?.includes('screen') + }, [trackReference]) + + const shouldShowWarning = + screenSharePreferences.enabled && isFullScreenCapture + + const handleStopScreenShare = async () => { + if (!localParticipant.isScreenShareEnabled) return + await localParticipant.setScreenShareEnabled(false, {}, {}) + } + + const handleDismissWarning = () => { + ScreenSharePreferenceStore.enabled = false + } + + if (!shouldShowWarning) return null + + return ( +
+ {(!containerWidth || containerWidth >= 300) && ( +
+
+ + {t('message')} + +
+ + +
+
+
+ )} +
+ ) +} diff --git a/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx b/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx index c745c00d..4fbfce9c 100644 --- a/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx +++ b/src/frontend/src/features/rooms/livekit/components/ParticipantTile.tsx @@ -28,6 +28,7 @@ import { HStack } from '@/styled-system/jsx' import { MutedMicIndicator } from './MutedMicIndicator' import { ParticipantPlaceholder } from './ParticipantPlaceholder' import { ParticipantTileFocus } from './ParticipantTileFocus' +import { FullScreenShareWarning } from './FullScreenShareWarning' export function TrackRefContextIfNeeded( props: React.PropsWithChildren<{ @@ -100,6 +101,7 @@ export const ParticipantTile: (
+ {children ?? ( <> {isTrackReference(trackReference) && diff --git a/src/frontend/src/locales/de/rooms.json b/src/frontend/src/locales/de/rooms.json index 675e7959..43cfdf77 100644 --- a/src/frontend/src/locales/de/rooms.json +++ b/src/frontend/src/locales/de/rooms.json @@ -199,5 +199,10 @@ "effects": "", "muteParticipant": "", "fullScreen": "" + }, + "fullScreenWarning": { + "message": "", + "stop": "", + "ignore": "" } } diff --git a/src/frontend/src/locales/en/rooms.json b/src/frontend/src/locales/en/rooms.json index e250336a..de50372a 100644 --- a/src/frontend/src/locales/en/rooms.json +++ b/src/frontend/src/locales/en/rooms.json @@ -198,5 +198,10 @@ "effects": "Apply visual effects", "muteParticipant": "Mute {{name}}", "fullScreen": "Full screen" + }, + "fullScreenWarning": { + "message": "To avoid infinite loop display, do not share your entire screen or browser window. Instead, share a tab or another window.", + "stop": "Stop presenting", + "ignore": "Ignore" } } diff --git a/src/frontend/src/locales/fr/rooms.json b/src/frontend/src/locales/fr/rooms.json index 80434bf2..a56bd267 100644 --- a/src/frontend/src/locales/fr/rooms.json +++ b/src/frontend/src/locales/fr/rooms.json @@ -198,5 +198,10 @@ "effects": "Appliquer des effets", "muteParticipant": "Couper le micro de {{name}}", "fullScreen": "Plein écran" + }, + "fullScreenWarning": { + "message": "Pour éviter l'affichage en boucle infinie, ne partagez pas l'intégralité de votre écran ni de votre fenêtre de navigateur. Partagez plutôt un onglet ou une autre fenêtre.", + "stop": "Arrêter la présentation", + "ignore": "Ignorer" } } diff --git a/src/frontend/src/stores/ScreenSharePreferences.ts b/src/frontend/src/stores/ScreenSharePreferences.ts new file mode 100644 index 00000000..1c2bba23 --- /dev/null +++ b/src/frontend/src/stores/ScreenSharePreferences.ts @@ -0,0 +1,9 @@ +import { proxy } from 'valtio' + +type State = { + enabled: boolean +} + +export const ScreenSharePreferenceStore = proxy({ + enabled: true, +})