From adb99cc5d9899ba9dd064c28a4188736e3a194ee Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Thu, 7 Aug 2025 12:39:20 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20refactor=20prejo?= =?UTF-8?q?in=20layout=20for=20better=20extensibility?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major refactoring of prejoin interface to improve user onboarding and camera/microphone permission handling: * Create extensible hint message system for easier addition of permission-related guidance. * Design flexible layout structure to accommodate future camera/mic options and component selection features. * Establish foundation for comprehensive prejoin redesign In upcoming commits, UX will be enhanced to a smoother user experience when joining calls and requesting media permissions. --- .../src/features/rooms/components/Join.tsx | 324 +++++++++++------- 1 file changed, 194 insertions(+), 130 deletions(-) diff --git a/src/frontend/src/features/rooms/components/Join.tsx b/src/frontend/src/features/rooms/components/Join.tsx index 2a7ff4bb..782fe106 100644 --- a/src/frontend/src/features/rooms/components/Join.tsx +++ b/src/frontend/src/features/rooms/components/Join.tsx @@ -8,7 +8,7 @@ import { H } from '@/primitives/H' import { SelectToggleDevice } from '../livekit/components/controls/SelectToggleDevice' import { Field } from '@/primitives/Field' import { Button, Dialog, Text, Form } from '@/primitives' -import { HStack, VStack } from '@/styled-system/jsx' +import { VStack } from '@/styled-system/jsx' import { Heading } from 'react-aria-components' import { RiImageCircleAiFill } from '@remixicon/react' import { @@ -71,36 +71,14 @@ const Effects = ({ -
- -
-
+ + ) } @@ -160,12 +138,14 @@ export const Join = ({ ) const videoEl = useRef(null) + const isVideoInitiated = useRef(false) useEffect(() => { const videoElement = videoEl.current as HTMLVideoElement | null const handleVideoLoaded = () => { if (videoElement) { + isVideoInitiated.current = true videoElement.style.opacity = '1' } } @@ -240,6 +220,20 @@ export const Join = ({ enterRoom() } + const hintMessage = useMemo(() => { + if (!videoEnabled) { + return 'cameraDisabled' + } + + if (!isVideoInitiated.current) { + return 'cameraStarting' + } + + if (videoTrack && videoEnabled) { + return '' + } + }, [videoTrack, videoEnabled]) + const renderWaitingState = () => { switch (status) { case ApiLobbyStatus.TIMEOUT: @@ -322,146 +316,216 @@ export const Join = ({
- {videoTrack && videoEnabled ? ( - // eslint-disable-next-line jsx-a11y/media-has-caption -
+
+
+
+ saveAudioInputEnabled(enabled)} + onDeviceError={(error) => console.error(error)} + onActiveDeviceChange={(deviceId) => + saveAudioInputDeviceId(deviceId ?? '') + } + variant="tertiary" + /> +
+
+ saveVideoInputEnabled(enabled)} + onDeviceError={(error) => console.error(error)} + onActiveDeviceChange={(deviceId) => + saveVideoInputDeviceId(deviceId ?? '') + } + variant="tertiary" + /> +
- - saveAudioInputEnabled(enabled)} - onDeviceError={(error) => console.error(error)} - onActiveDeviceChange={(deviceId) => - saveAudioInputDeviceId(deviceId ?? '') - } - variant="tertiary" - /> - saveVideoInputEnabled(enabled)} - onDeviceError={(error) => console.error(error)} - onActiveDeviceChange={(deviceId) => - saveVideoInputDeviceId(deviceId ?? '') - } - variant="tertiary" - /> - -
-
- {renderWaitingState()}
+
+ {renderWaitingState()} +
)