Ramble-FE / app / index.native.tsx
index.native.tsx
Raw
import { VideoStream, VoiceChatOverlay } from "@/components";
import { useAuth, useStompClient, useWebRTC } from "@/hooks";
import { useLocalMedia } from "@/hooks/useLocalMedia.native";
import { useState } from 'react';
import { LayoutChangeEvent, StyleSheet, View } from 'react-native';
import { Directions, Gesture, GestureDetector } from 'react-native-gesture-handler';
import { runOnJS } from 'react-native-reanimated';
import { SafeAreaProvider } from "react-native-safe-area-context";

export default function Index() {
    const { isAuthenticated } = useAuth();

    const { mediaStream: localStream, isMediaReady, isMuted, isFrontCamera, toggleMute, switchCamera } = useLocalMedia(isAuthenticated);
    const { client: stompClient, isConnected: isStompConnected } = useStompClient(isAuthenticated);
    const isWebRTCReady = isAuthenticated && isMediaReady && isStompConnected;

    const { remoteStream, isConnected: isWebRTCConnected, startCall, endCall } = useWebRTC({
        enabled: isWebRTCReady,
        localStream: localStream as any,
        stompClient: stompClient ?? null,
    });

    // 화면 방향에 따라 레이아웃 조정
    const [dims, setDims] = useState({ width: 0, height: 0 });
    const isPortrait = dims.height >= dims.width;

    // 레이아웃 변경 이벤트 핸들러
    const onLayout = (e: LayoutChangeEvent) => {
        const { width, height } = e.nativeEvent.layout;
        setDims({ width, height });
    };

    // 메시지 전송 핸들러 (향후 채팅 기능용)
    const handleSend = (message: string) => {
        if (message.trim()) {
            console.log('메시지 전송:', message);
            // TODO: 채팅 메시지 전송 로직 구현
        }
    };

    const safeStartCall = () => startCall().catch((e) => console.warn('startCall 실패:', e));

    const flingLeft = Gesture.Fling()
    .direction(Directions.LEFT)
    .onEnd(() => {
        'worklet';
        if (!isWebRTCConnected) {
            console.log('통화 시작');
            runOnJS(safeStartCall)();
        }
    });

    const flingRight = Gesture.Fling()
    .direction(Directions.RIGHT)
    .onEnd(() => {
        'worklet';
        if (isWebRTCConnected) {
            console.log('통화 종료');
            runOnJS(endCall)();
        }
    });

    return (
        <SafeAreaProvider>
            <View
                style={[
                    styles.container, 
                    { flexDirection: isPortrait ? 'column' : 'row' },
                ]}
                onLayout={onLayout}
            >
                {/* 상대방 화면 */}
                <GestureDetector gesture={Gesture.Simultaneous(flingLeft, flingRight)}>
                    <VideoStream
                        stream={remoteStream as any}
                        style={styles.video}
                    />
                </GestureDetector>

                {/* 내 화면 */}
                 <VideoStream
                    stream={localStream as any}
                    style={styles.video}
                    isMirrored={isFrontCamera}
                />
            </View>

            <VoiceChatOverlay
                isMuted={isMuted}
                isConnected={isWebRTCConnected}
                toggleMute={toggleMute}
                toggleVideo={switchCamera}
                onSend={handleSend}
            />
        </SafeAreaProvider>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    video: {
        flex: 1,
    },
});