import { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, Alert, StyleSheet } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import { useRouter } from 'expo-router';
import { useTranslation } from 'react-i18next';
import { useCallStore } from '../stores/call';
import { UserAvatar } from '../components/UserAvatar';
function fmtDuration(ms: number) {
const s = Math.floor(ms / 1000);
const m = Math.floor(s / 60);
return `${m}:${String(s % 60).padStart(2, '0')}`;
}
export default function CallScreen() {
const { t } = useTranslation();
const router = useRouter();
const status = useCallStore((s) => s.status);
const peer = useCallStore((s) => s.peer);
const muted = useCallStore((s) => s.muted);
const speaker = useCallStore((s) => s.speaker);
const startedAt = useCallStore((s) => s.startedAt);
const endReason = useCallStore((s) => s.endReason);
const acceptCall = useCallStore((s) => s.acceptCall);
const declineCall = useCallStore((s) => s.declineCall);
const hangup = useCallStore((s) => s.hangup);
const toggleMute = useCallStore((s) => s.toggleMute);
const toggleSpeaker = useCallStore((s) => s.toggleSpeaker);
const clear = useCallStore((s) => s._clear);
const [elapsed, setElapsed] = useState(0);
// Kein aktiver Call → Screen schließen.
useEffect(() => {
if (status === 'idle') router.back();
}, [status, router]);
// Call beendet → kurz "beendet" zeigen, dann schließen + aufräumen.
useEffect(() => {
if (status !== 'ended') return;
const tm = setTimeout(() => {
clear();
router.back();
}, 1300);
return () => clearTimeout(tm);
}, [status, clear, router]);
// Gesprächsdauer-Timer.
useEffect(() => {
if (status !== 'connected' || !startedAt) return;
const id = setInterval(() => setElapsed(Date.now() - startedAt), 1000);
return () => clearInterval(id);
}, [status, startedAt]);
async function onAccept() {
try {
await acceptCall();
} catch (e: any) {
if (e?.message === 'webrtc_unavailable') {
Alert.alert(t('call.title'), t('call.needs_rebuild'));
}
hangup('failed');
}
}
const subtitle =
status === 'outgoing'
? t('call.calling')
: status === 'incoming'
? t('call.incoming')
: status === 'connecting'
? t('call.connecting')
: status === 'connected'
? fmtDuration(elapsed)
: status === 'ended'
? endReason === 'declined'
? t('call.declined')
: endReason === 'unanswered'
? t('call.no_answer')
: endReason === 'failed'
? t('call.failed')
: t('call.ended')
: '';
return (
{/* Oben: Avatar + Name + Status */}
{peer?.nickname ?? '…'}
{subtitle}
{/* Unten: Aktions-Buttons */}
{status === 'incoming' ? (
) : status === 'ended' ? null : (
{(status === 'connected' || status === 'connecting') && (
)}
{(status === 'connected' || status === 'connecting' || status === 'outgoing') && (
)}
hangup('ended')} label={t('call.hang_up')} />
)}
);
}
function CircleBtn({
color,
iconColor = '#fff',
icon,
rotate,
onPress,
label,
}: {
color: string;
iconColor?: string;
icon: keyof typeof Ionicons.glyphMap;
rotate?: boolean;
onPress: () => void;
label: string;
}) {
return (
{label}
);
}