Ramble-FE / components / VideoStream / index.tsx
index.tsx
Raw
import { MaterialIcons } from "@expo/vector-icons";
import React, { useEffect, useRef } from "react";
import { StyleSheet, Text, View } from "react-native";

interface VideoStreamProps {
    stream: MediaStream | null;
    isMirrored?: boolean;
    isMuted?: boolean;
    style?: any;
}

export default function VideoStream({
    stream,
    isMirrored = false,
    isMuted = false,
    style,
}: VideoStreamProps) {
    const videoRef = useRef<HTMLVideoElement>(null);

    useEffect(() => {
        const video = videoRef.current; 
        if (!video) return;  

        if (stream) {
            video.srcObject = stream;
            video.onloadedmetadata = () => {
                video.play()
                    .catch((e) => console.error("비디오 재생 실패:", e));
            };
        } else {
            try { video.pause(); } catch {}
            video.srcObject = null;
            video.onloadedmetadata = null;
        }

        return () => {
            try { video.pause(); } catch {}
            video.srcObject = null;
            video.onloadedmetadata = null;
        };

    }, [stream]);

    return (
        <View style={[styles.video, style]}>
            <video
                ref={videoRef}
                autoPlay
                muted={isMuted}
                playsInline
                style={{
                    width: "100%",
                    height: "100%",
                    objectFit: "cover" as const,
                    transform: isMirrored ? "scaleX(-1)" : "none",
                }}
            />

            {!stream && (
                <View style={styles.unConnectedVideo}>
                    <MaterialIcons name="tv-off" size={100} color="lightgray" />
                    <Text style={styles.text}>The video is turned off.</Text>
                </View>
            )}     
        </View>
    );
}

const styles = StyleSheet.create({
    video: {
        flex: 1,
        overflow: "hidden",
        position: "relative",
    },
    unConnectedVideo: {
        ...StyleSheet.absoluteFillObject,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#333',
    },
    text: {
        marginTop: 10,
        fontSize: 16,
        color: '#888',
        fontWeight: '500',
    },
});