import React from 'react'; import Navigation from '../lib/navigation.js'; const navigate = view => Navigation.navigateTo(view); export const CALL_EXPERIENCE_VIEWS = [ 'call-history', 'call-incoming', 'audio-call-ringing', 'audio-call-active', 'audio-call-muted', 'audio-call-speaker', 'video-call-ringing', 'video-call-camera-off', 'video-call-active', 'video-call-peer-camera-off', 'call-minimized' ]; const PEER = {name: '安妮', avatar: 'img/bkg/p09.jpg'}; const CALL_RECORDS = [ {id: 1, type: 'video', direction: 'outgoing', state: 'cancelled', label: '已取消', time: '今天 10:24'}, {id: 2, type: 'audio', direction: 'incoming', state: 'declined', label: '已拒绝', time: '昨天 21:03'}, {id: 3, type: 'video', direction: 'incoming', state: 'missed', label: '未接听', time: '昨天 18:42'}, {id: 4, type: 'audio', direction: 'outgoing', state: 'busy', label: '对方忙线', time: '星期一 15:10'}, {id: 5, type: 'audio', direction: 'outgoing', state: 'finished', label: '通话时长 12:36', time: '8月20日'} ]; function Icon({children}) { return ; } function Toast({message, onDone}) { React.useEffect(() => { if (!message) return undefined; const timer = window.setTimeout(onDone, 1800); return () => window.clearTimeout(timer); }, [message, onDone]); return message ?
{message}
: null; } function CallAvatar({small = false}) { return ; } function CallHeader({onMinimize, light = false}) { return
端到端加密通话
; } function Control({icon, label, active, danger, onClick}) { return ; } function CallHistory() { return

安妮

最近通话

{CALL_RECORDS.map(item => )}
; } function IncomingCall({onToast}) { return
navigate('call-minimized')} />

{PEER.name}

邀请你进行视频通话

{onToast('已拒绝视频通话'); window.setTimeout(() => navigate('call-history'), 600);}} /> navigate('video-call-active')} />
; } function formatDuration(seconds) { const mins = Math.floor(seconds / 60).toString().padStart(2, '0'); return `${mins}:${(seconds % 60).toString().padStart(2, '0')}`; } function AudioCall({view, onToast}) { const ringing = view === 'audio-call-ringing'; const [seconds, setSeconds] = React.useState(ringing ? 0 : 68); const [mic, setMic] = React.useState(view !== 'audio-call-muted'); const [speaker, setSpeaker] = React.useState(view === 'audio-call-speaker'); React.useEffect(() => { if (ringing) return undefined; const timer = window.setInterval(() => setSeconds(value => value + 1), 1000); return () => window.clearInterval(timer); }, [ringing]); const hangup = () => {onToast(ringing ? '已取消呼叫' : `通话结束 ${formatDuration(seconds)}`); window.setTimeout(() => navigate('call-history'), 650);}; return
navigate('call-minimized')} />

{PEER.name}

{ringing ? '正在等待对方接听…' : formatDuration(seconds)}

{!ringing ? 网络良好 : }
{ringing ?
:
{setMic(!mic); onToast(mic ? '麦克风已关闭' : '麦克风已开启');}} /> {setSpeaker(!speaker); onToast(speaker ? '已切换到听筒' : '扬声器已开启');}} />
}
; } function VideoBackdrop({cameraOff, peerOff}) { if (peerOff) return
对方摄像头已关闭语音通话仍在继续
; if (cameraOff) return
摄像头已关闭
; return 视频通话画面; } function VideoCall({view, onToast}) { const ringing = view === 'video-call-ringing' || view === 'video-call-camera-off'; const [camera, setCamera] = React.useState(view !== 'video-call-camera-off'); const [mic, setMic] = React.useState(true); const [seconds, setSeconds] = React.useState(ringing ? 0 : 128); const peerOff = view === 'video-call-peer-camera-off'; React.useEffect(() => { if (ringing) return undefined; const timer = window.setInterval(() => setSeconds(value => value + 1), 1000); return () => window.clearInterval(timer); }, [ringing]); const hangup = () => {onToast(ringing ? '已取消视频呼叫' : `视频通话结束 ${formatDuration(seconds)}`); window.setTimeout(() => navigate('call-history'), 650);}; return
navigate('call-minimized')} />

{PEER.name}

{ringing ? '正在等待对方接听…' : formatDuration(seconds)}

{!ringing ? : null}
onToast('已切换摄像头')} /> {setCamera(!camera); onToast(camera ? '摄像头已关闭' : '摄像头已开启');}} />{!ringing ? setMic(!mic)} /> : null}
; } function MinimizedCall({onToast}) { const [position, setPosition] = React.useState(() => ({x: Math.max(16, window.innerWidth - 134), y: 168})); const drag = React.useRef(null); const onPointerDown = event => {drag.current = {x: event.clientX - position.x, y: event.clientY - position.y}; event.currentTarget.setPointerCapture(event.pointerId);}; const onPointerMove = event => {if (!drag.current) return; setPosition({x: Math.max(8, Math.min(window.innerWidth - 132, event.clientX - drag.current.x)), y: Math.max(70, Math.min(window.innerHeight - 190, event.clientY - drag.current.y))});}; return
安妮在线

今天 10:24

下午的评审材料我已经发到群里了。
; } export default function CallExperienceView({view}) { const [toast, setToast] = React.useState(''); let content; if (view === 'call-history') content = ; else if (view === 'call-incoming') content = ; else if (view.startsWith('audio-call')) content = ; else if (view === 'call-minimized') content = ; else content = ; return <>{content} setToast('')} />; }