// Call UI components — Discord-style, matched to Clean-Rail aesthetic
const CALL_PARTICIPANTS = [
{ id: 'dennis', name: 'dennis', initial: 'D', color: 'teal', speaking: false, muted: false, video: false, me: true, e2ee: true },
{ id: 'max', name: 'Max', initial: 'M', color: 'teal', speaking: true, muted: false, video: true, sharing: true, e2ee: true },
{ id: 'lena', name: 'Lena', initial: 'L', color: 'amber', speaking: false, muted: true, video: false, e2ee: true },
{ id: 'tom', name: 'Tom', initial: 'T', color: 'violet', speaking: false, muted: false, video: false, e2ee: true },
{ id: 'nico', name: 'nico', initial: 'N', color: 'teal', speaking: true, muted: false, video: false, e2ee: true },
];
const ParticipantTile = ({ p, focused, onClick, small }) => (
{p.video || p.sharing ? (
{p.sharing ? (
{p.name} teilt Bildschirm
) : (
)}
) : (
)}
{p.me && }
{p.name}{p.me ? ' (du)' : ''}
{p.e2ee && }
{p.muted && }
{p.sharing && }
);
const CallControls = ({ muted, onToggleMute, sharing, onToggleShare, video, onToggleVideo, onHangup, compact }) => (
);
const IncomingCallScreen = ({ chat, onAccept, onDecline }) => (
Eingehender Anruf
{chat.name}
E2E verschlüsselt · Voice Call
);
const ActiveCallScreen = ({ participants, mode, setMode, focused, setFocused, onHangup, callState, setCallState }) => {
const speaker = participants.find(p => p.id === focused) || participants.find(p => p.sharing) || participants[0];
const others = participants.filter(p => p.id !== speaker.id);
const sharingParticipant = participants.find(p => p.sharing);
return (
Die Squad
·
{callState.duration}
E2E verschlüsselt
{mode === 'grid' && (
{participants.map(p => (
{ setFocused(p.id); setMode('focus'); }} />
))}
)}
{mode === 'focus' && (
{others.map(p => (
setFocused(p.id)} />
))}
)}
{mode === 'fullscreen' && (
{others.slice(0,4).map(p => (
setFocused(p.id)} />
))}
Esc zum Verlassen
)}
setCallState(s => ({...s, muted: !s.muted}))}
sharing={callState.sharing}
onToggleShare={() => setCallState(s => ({...s, sharing: !s.sharing}))}
video={callState.video}
onToggleVideo={() => setCallState(s => ({...s, video: !s.video}))}
onHangup={onHangup}
/>
);
};
const PipCall = ({ onExpand, onHangup, participants }) => {
const speaker = participants.find(p => p.sharing) || participants.find(p => p.speaking) || participants[0];
return (
{speaker.sharing ? (
) : (
)}
Die Squad · {participants.length}
Live · tippe zum Öffnen
);
};
Object.assign(window, { CALL_PARTICIPANTS, ParticipantTile, CallControls, IncomingCallScreen, ActiveCallScreen, PipCall });