diff --git a/www/atoms/local.ts b/www/atoms/local.ts index 201dde2..ec5ab90 100644 --- a/www/atoms/local.ts +++ b/www/atoms/local.ts @@ -16,6 +16,8 @@ export type Local = | { status: "requestingDevices"; name: string; + audioEnabled: boolean; + videoEnabled: boolean; } | { status: "connecting"; @@ -42,22 +44,31 @@ export const localState = atom({ const setAudioVideoEnabled = (audioEnabled: boolean, videoEnabled: boolean) => (local: Local): Local => { - assert(local.status === "connecting" || local.status === "connected"); + assert( + local.status === "requestingDevices" || + local.status === "connecting" || + local.status === "connected" + ); return { ...local, audioEnabled, videoEnabled }; }; -const setConnecting = +const setConnecting = (local: Local): Local => { + assert(local.status === "requestingDevices"); + return { ...local, status: "connecting" }; +}; + +const setRequestingDevices = (audioEnabled: boolean, videoEnabled: boolean) => (local: Local): Local => { - assert(local.status === "requestingDevices"); - return { ...local, status: "connecting", audioEnabled, videoEnabled }; + assert(local.status === "requestingPermissions"); + return { + ...local, + status: "requestingDevices", + audioEnabled, + videoEnabled, + }; }; -const setRequestingDevices = (local: Local): Local => { - assert(local.status === "requestingPermissions"); - return { ...local, status: "requestingDevices" }; -}; - const setRequestingPermissions = (name: string) => (local: Local): Local => { diff --git a/www/components/room/controls.tsx b/www/components/room/controls.tsx index 7142863..88074d6 100644 --- a/www/components/room/controls.tsx +++ b/www/components/room/controls.tsx @@ -36,24 +36,21 @@ function Control(props: ControlProps) { ); } -export default function Controls() { - const router = useRouter(); +function TrackControl(track: "video" | "audio") { const [local, setLocal] = useRecoilState(localState); const peers = useRecoilValue(peersState); const stream = mapGet(streamMap, LocalStreamKey); - assert(local.status === "connecting" || local.status === "connected"); + assert( + local.status === "requestingDevices" || + local.status === "connecting" || + local.status === "connected" + ); const { audioEnabled, videoEnabled } = getVideoAudioEnabled(stream); + const enabled = track === "audio" ? audioEnabled : videoEnabled; - const handleLeave = React.useCallback(() => { - router.push( - `/goodbye?left=${router.query.roomCode}/${router.query.roomName}`, - "/goodbye" - ); - }, [router]); - - const handleToggleAudio = React.useCallback(() => { + const handleToggle = React.useCallback(() => { peers.forEach((peer) => { const channel = rtcDataChannelMap.get(peer.sid); @@ -61,69 +58,71 @@ export default function Controls() { sendMessage(channel, { type: "peer-state", name: local.name, - audioEnabled: !audioEnabled, - videoEnabled, + audioEnabled: track === "audio" ? !audioEnabled : audioEnabled, + videoEnabled: track === "video" ? !videoEnabled : videoEnabled, }); } }); - const audioTracks = stream?.getAudioTracks(); + const tracks = + track === "audio" ? stream?.getAudioTracks() : stream?.getVideoTracks(); - if (audioTracks !== undefined && audioTracks.length > 0) { - audioTracks[0].enabled = !audioEnabled; + if (tracks !== undefined && tracks.length > 0) { + tracks[0].enabled = !enabled; } - setLocal(localActions.setAudioVideoEnabled(!audioEnabled, videoEnabled)); + setLocal( + localActions.setAudioVideoEnabled( + track === "audio" ? !audioEnabled : audioEnabled, + track === "video" ? !videoEnabled : videoEnabled + ) + ); }, [audioEnabled, local.name, peers, setLocal, stream, videoEnabled]); - const handleToggleVideo = React.useCallback(() => { - peers.forEach((peer) => { - const channel = rtcDataChannelMap.get(peer.sid); + const iconClassName = classNames("absolute", { + "text-slate-800": !enabled, + }); - if (channel !== undefined) { - sendMessage(channel, { - type: "peer-state", - name: local.name, - audioEnabled, - videoEnabled: !videoEnabled, - }); - } - }); + return ( + +