Ramble-FE / hooks / useLocalMedia.native.ts
useLocalMedia.native.ts
Raw
import { useCallback, useEffect, useRef, useState } from "react";
import { Alert } from "react-native";
import { mediaDevices, MediaStream } from "react-native-webrtc";

export const useLocalMedia = (isAuthenticated: boolean) => {
    const mediaStreamRef = useRef<MediaStream | null>(null);
    
    const [state, setState] = useState({
        isMediaReady: false,
        isFrontCamera: true,
        isMuted: false,
    });

    const initializeMedia = useCallback(async (isFront: boolean) => {
        await mediaDevices.getUserMedia({
            audio: true,
            video: {
                width: { min: 360, ideal: 540, max: 960 },
                height: { min: 480, ideal: 720, max: 1280 },
                frameRate: { ideal: 30, max: 30 },
                facingMode: isFront ? 'user' : 'environment',
            },
        }).then((stream) => {
            mediaStreamRef.current = stream;
            setState((prev) => ({
                ...prev,
                isMediaReady: true,
                isFrontCamera: isFront,
            }));
        }).catch((error) => {
            console.error('스트림 시작 실패:', error);
            setState((prev) => ({ ...prev, isMediaReady: false }));
            Alert.alert(
                '미디어 접근 실패',
                '카메라와 마이크 권한을 확인해주세요.',
                [{ text: '확인' }]
            );
        });
    }, []);

    useEffect(() => {
        if (!isAuthenticated) {
            // 인증되지 않은 경우 미디어 스트림 해제
            if (mediaStreamRef.current) {
                mediaStreamRef.current.getTracks().forEach(track => track.stop());
                mediaStreamRef.current = null;
                setState((prev) => ({ ...prev, isMediaReady: false }));
            }
            return;
        }

        initializeMedia(true);

        return () => {
            if (mediaStreamRef.current) {
                mediaStreamRef.current.getTracks().forEach(track => track.stop());
                mediaStreamRef.current = null;
                setState((prev) => ({ ...prev, isMediaReady: false }));
            }
        };
    }, [isAuthenticated, initializeMedia]);

    const toggleMute = useCallback(() => {
        if (!mediaStreamRef.current) return;

        const audioTrack = mediaStreamRef.current.getAudioTracks()[0];
        if (audioTrack) {
            audioTrack.enabled = !audioTrack.enabled;
            setState((prev) => ({ ...prev, isMuted: !audioTrack.enabled }));
        }
    }, []);

    const switchCamera = useCallback(() => {
        if (!mediaStreamRef.current) return;

        mediaStreamRef.current.getTracks().forEach(track => track.stop());
        mediaStreamRef.current = null;

        initializeMedia(!state.isFrontCamera)
    }, [state.isFrontCamera, initializeMedia]);

    return {
        // 상태
        ...state,

        // 미디어 스트림
        mediaStream: mediaStreamRef.current,

        // 미디어 액션
        toggleMute,
        switchCamera,
    };
};