From 2f1585eaa8ce4b6fbe24eedbb4fcde641f7b776c Mon Sep 17 00:00:00 2001 From: today-is-first Date: Mon, 2 Dec 2024 18:53:05 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20DropBox=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/lobbyPage/DropBox.tsx | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 packages/frontend/src/components/lobbyPage/DropBox.tsx diff --git a/packages/frontend/src/components/lobbyPage/DropBox.tsx b/packages/frontend/src/components/lobbyPage/DropBox.tsx new file mode 100644 index 0000000..4324fd6 --- /dev/null +++ b/packages/frontend/src/components/lobbyPage/DropBox.tsx @@ -0,0 +1,87 @@ +import { useState, useRef, useEffect } from 'react'; +import ArrowDownIcon from '@/assets/images/DropBoxArrowDown.svg?react'; +import ArrowUpIcon from '@/assets/images/DropBoxArrowUp.svg?react'; +import { changeMediaDevice } from '@/utils/videoStreamUtils'; +import { useLocalStreamStore } from '@/store/localStreamStore'; + +interface IDropBoxProps { + title: string; + type: 'video' | 'audio'; +} + +function DropBox({ title, type }: IDropBoxProps) { + const [isOpen, setIsOpen] = useState(false); + const dropBoxRef = useRef(null); + const videoDevices = useLocalStreamStore((state) => state.videoDevices); + const audioInputDevices = useLocalStreamStore((state) => state.audioInputDevices); + const currentVideoDevice = useLocalStreamStore((state) => state.currentVideoDevice); + const currentAudioDevice = useLocalStreamStore((state) => state.currentAudioDevice); + const targetMedia = type === 'video' ? currentVideoDevice : currentAudioDevice; + const targetMediaList = type === 'video' ? videoDevices : audioInputDevices; + const targetMediaLabel = targetMedia?.label || targetMediaList?.[0]?.label; + + function handleClick() { + if (!targetMediaList?.length) return; + setIsOpen(!isOpen); + } + + function handleDeviceChange(device: MediaDeviceInfo) { + if (device.kind === 'videoinput') { + changeMediaDevice({ videoDeviceId: device.deviceId, audioDeviceId: '' }); + } else { + changeMediaDevice({ videoDeviceId: '', audioDeviceId: device.deviceId }); + } + } + + useEffect(() => { + function handleOutsideClick(event: MouseEvent) { + if (dropBoxRef.current && !dropBoxRef.current.contains(event.target as Node)) { + setIsOpen(false); + } + } + + document.addEventListener('mousedown', handleOutsideClick); + return () => { + document.removeEventListener('mousedown', handleOutsideClick); + }; + }, []); + + return ( +
+ {title} +
+
+ {targetMediaList?.length ? ( + targetMediaLabel + ) : ( + 장치가 없습니다 + )} + {isOpen ? : } +
+ {isOpen && ( +
+ {targetMediaList?.map((device) => { + if (device.deviceId.includes('communications')) return null; + return ( +
handleDeviceChange(device)} + > + {targetMediaLabel === device.label && } + {device.label} +
+ ); + })} +
+ )} +
+
+ ); +} + +export default DropBox;