Twilioapp/src/screens/CallScreen.web.tsx

300 lines
7.8 KiB
TypeScript
Raw Normal View History

import { FC, useState } from 'react';
const CallScreen: FC = () => {
const [callStatus, setCallStatus] = useState<'idle' | 'calling' | 'connected'>('idle');
const [selectedLanguage, setSelectedLanguage] = useState('zh-en');
const handleStartCall = () => {
setCallStatus('calling');
// 模拟连接过程
setTimeout(() => {
setCallStatus('connected');
}, 2000);
};
const handleEndCall = () => {
setCallStatus('idle');
};
const languageOptions = [
{ value: 'zh-en', label: '中文 ⇄ 英文' },
{ value: 'zh-es', label: '中文 ⇄ 西班牙文' },
{ value: 'zh-fr', label: '中文 ⇄ 法文' },
{ value: 'zh-ja', label: '中文 ⇄ 日文' },
{ value: 'zh-ko', label: '中文 ⇄ 韩文' },
];
return (
<div style={styles.container}>
<div style={styles.content}>
{/* 语言选择 */}
<div style={styles.section}>
<h3 style={styles.sectionTitle}></h3>
<select
value={selectedLanguage}
onChange={(e) => setSelectedLanguage(e.target.value)}
style={styles.languageSelect}
>
{languageOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</div>
{/* 通话状态 */}
<div style={styles.callContainer}>
{callStatus === 'idle' && (
<div style={styles.idleState}>
<div style={styles.callIcon}>📞</div>
<h2 style={styles.statusText}></h2>
<p style={styles.statusSubtext}></p>
<button style={styles.startButton} onClick={handleStartCall}>
</button>
</div>
)}
{callStatus === 'calling' && (
<div style={styles.callingState}>
<div style={styles.pulsingIcon}>📞</div>
<h2 style={styles.statusText}>...</h2>
<p style={styles.statusSubtext}></p>
<div style={styles.loadingDots}>
<span></span>
<span></span>
<span></span>
</div>
</div>
)}
{callStatus === 'connected' && (
<div style={styles.connectedState}>
<div style={styles.connectedIcon}></div>
<h2 style={styles.statusText}></h2>
<p style={styles.statusSubtext}></p>
{/* 通话控制 */}
<div style={styles.callControls}>
<button style={styles.muteButton}>🔇</button>
<button style={styles.endButton} onClick={handleEndCall}>
</button>
<button style={styles.speakerButton}>🔊</button>
</div>
{/* 通话信息 */}
<div style={styles.callInfo}>
<div style={styles.infoItem}>
<span style={styles.infoLabel}></span>
<span style={styles.infoValue}>00:45</span>
</div>
<div style={styles.infoItem}>
<span style={styles.infoLabel}></span>
<span style={styles.infoValue}></span>
</div>
</div>
</div>
)}
</div>
{/* 快速操作 */}
<div style={styles.section}>
<h3 style={styles.sectionTitle}></h3>
<div style={styles.quickActions}>
<button style={styles.actionButton}>
<span style={styles.actionIcon}>📝</span>
<span style={styles.actionLabel}></span>
</button>
<button style={styles.actionButton}>
<span style={styles.actionIcon}>📧</span>
<span style={styles.actionLabel}></span>
</button>
<button style={styles.actionButton}>
<span style={styles.actionIcon}>📋</span>
<span style={styles.actionLabel}></span>
</button>
</div>
</div>
</div>
</div>
);
};
const styles = {
container: {
display: 'flex',
flexDirection: 'column' as const,
height: '100%',
backgroundColor: '#f5f5f5',
},
content: {
flex: 1,
padding: '16px',
paddingBottom: '100px',
},
section: {
marginBottom: '24px',
},
sectionTitle: {
fontSize: '18px',
fontWeight: 'bold',
color: '#333',
margin: '0 0 16px 0',
},
languageSelect: {
width: '100%',
padding: '12px',
fontSize: '16px',
border: '1px solid #d9d9d9',
borderRadius: '8px',
backgroundColor: '#fff',
},
callContainer: {
display: 'flex',
flexDirection: 'column' as const,
alignItems: 'center',
justifyContent: 'center',
minHeight: '300px',
backgroundColor: '#fff',
borderRadius: '16px',
padding: '32px',
marginBottom: '24px',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
},
idleState: {
textAlign: 'center' as const,
},
callingState: {
textAlign: 'center' as const,
},
connectedState: {
textAlign: 'center' as const,
width: '100%',
},
callIcon: {
fontSize: '64px',
marginBottom: '16px',
},
pulsingIcon: {
fontSize: '64px',
marginBottom: '16px',
animation: 'pulse 1.5s ease-in-out infinite alternate',
},
connectedIcon: {
fontSize: '64px',
marginBottom: '16px',
},
statusText: {
fontSize: '24px',
fontWeight: 'bold',
color: '#333',
margin: '0 0 8px 0',
},
statusSubtext: {
fontSize: '16px',
color: '#666',
margin: '0 0 24px 0',
},
startButton: {
backgroundColor: '#52c41a',
color: '#fff',
border: 'none',
borderRadius: '50px',
padding: '16px 32px',
fontSize: '18px',
fontWeight: 'bold',
cursor: 'pointer',
transition: 'background-color 0.3s ease',
},
loadingDots: {
display: 'flex',
gap: '8px',
justifyContent: 'center',
},
callControls: {
display: 'flex',
gap: '16px',
justifyContent: 'center',
margin: '24px 0',
},
muteButton: {
backgroundColor: '#1890ff',
color: '#fff',
border: 'none',
borderRadius: '50%',
width: '56px',
height: '56px',
fontSize: '20px',
cursor: 'pointer',
},
endButton: {
backgroundColor: '#ff4d4f',
color: '#fff',
border: 'none',
borderRadius: '50px',
padding: '16px 24px',
fontSize: '16px',
fontWeight: 'bold',
cursor: 'pointer',
},
speakerButton: {
backgroundColor: '#1890ff',
color: '#fff',
border: 'none',
borderRadius: '50%',
width: '56px',
height: '56px',
fontSize: '20px',
cursor: 'pointer',
},
callInfo: {
display: 'flex',
justifyContent: 'space-around',
width: '100%',
marginTop: '24px',
},
infoItem: {
display: 'flex',
flexDirection: 'column' as const,
alignItems: 'center',
},
infoLabel: {
fontSize: '14px',
color: '#666',
marginBottom: '4px',
},
infoValue: {
fontSize: '16px',
fontWeight: 'bold',
color: '#333',
},
quickActions: {
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gap: '12px',
},
actionButton: {
display: 'flex',
flexDirection: 'column' as const,
alignItems: 'center',
padding: '16px 8px',
backgroundColor: '#fff',
border: 'none',
borderRadius: '12px',
cursor: 'pointer',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
},
actionIcon: {
fontSize: '24px',
marginBottom: '8px',
},
actionLabel: {
fontSize: '12px',
color: '#666',
textAlign: 'center' as const,
},
};
export default CallScreen;