mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-14 09:20:28 +00:00
123 lines
5.8 KiB
Markdown
123 lines
5.8 KiB
Markdown
# Audio / Video Call
|
|
|
|
> **Related spec:** [spec/services/calls.md](../../spec/services/calls.md)
|
|
|
|
## Purpose
|
|
|
|
Make and receive end-to-end encrypted audio and video calls over WebRTC. Supports CallKit integration for native iOS call UI, picture-in-picture for video calls, audio device selection, and collapsible call overlay.
|
|
|
|
## Route / Navigation
|
|
|
|
- **Entry point (outgoing)**: Tap audio or video call button in `ChatInfoView` action buttons or `ChatView` toolbar
|
|
- **Entry point (incoming)**: `IncomingCallView` banner appears at top of screen; or native CallKit UI if enabled
|
|
- **Presented by**: `ActiveCallView` is overlaid on the main app view when `chatModel.activeCall` is set
|
|
- **Collapsible**: Call view can be collapsed via `chatModel.activeCallViewIsCollapsed` to return to chat while call continues
|
|
- **Dismiss**: Call ends when user taps end button or remote party disconnects
|
|
|
|
## Page Sections
|
|
|
|
### Incoming Call Banner (`IncomingCallView`)
|
|
|
|
Displayed as an overlay banner when `CallController.activeCallInvitation` is set:
|
|
|
|
| Element | Description |
|
|
|---|---|
|
|
| Profile avatar | User profile image (shown when multiple profiles exist) |
|
|
| Call type icon | `video.fill` (green) for video calls, `phone.fill` (green) for audio |
|
|
| Call type text | "Audio call" or "Video call" with caller info |
|
|
| Caller profile | `ProfilePreview` showing caller name and image |
|
|
| Reject button | Red `phone.down.fill` icon -- ends the invitation |
|
|
| Ignore button | Neutral `multiply` icon -- dismisses the banner without rejecting |
|
|
| Accept button | Green `checkmark` icon -- accepts the call; if another call is active, ends it first |
|
|
|
|
Sound: Ringtone plays via `SoundPlayer.startRingtone()` while banner is visible (unless call view is already showing).
|
|
|
|
### Active Call View (`ActiveCallView`)
|
|
|
|
Full-screen overlay with black background:
|
|
|
|
| Element | Description |
|
|
|---|---|
|
|
| Remote video | Full-screen `CallViewRemote` showing remote party's camera feed; tap toggles between `scaleAspectFill` and `scaleAspectFit` |
|
|
| Local video preview | Small floating `CallViewLocal` in top-right corner (30% width); shows local camera with rounded corners |
|
|
| Call overlay | `ActiveCallOverlay` with call controls (hidden when PiP is active for video calls) |
|
|
| Screen keep-on | `AppDelegate.keepScreenOn(true)` prevents screen dimming during calls |
|
|
|
|
### Call Controls (`ActiveCallOverlay`)
|
|
|
|
Bottom bar of the active call:
|
|
|
|
| Control | Description |
|
|
|---|---|
|
|
| Mute toggle | Microphone on/off |
|
|
| Speaker toggle | Speaker/receiver switch |
|
|
| Camera switch | Front/back camera toggle (video calls) |
|
|
| Video toggle | Enable/disable video during call |
|
|
| End call | Red phone-down button to terminate |
|
|
| Audio device picker | `AudioDevicePicker` / `CallAudioDeviceManager` for selecting output (receiver, speaker, Bluetooth, AirPods) |
|
|
|
|
### Picture-in-Picture (PiP)
|
|
|
|
- When `pipShown == true` and call has video, the call overlay is hidden
|
|
- PiP window shows the remote video feed
|
|
- User can interact with the app normally while call continues
|
|
|
|
### CallKit Integration
|
|
|
|
Managed by `CallController`:
|
|
|
|
| Feature | Description |
|
|
|---|---|
|
|
| Native incoming call UI | iOS system call screen for incoming calls (when CallKit is enabled) |
|
|
| Call history | Optionally shown in Phone app recents (`DEFAULT_CALL_KIT_CALLS_IN_RECENTS`) |
|
|
| System audio routing | CallKit manages audio session configuration |
|
|
| Lock screen answering | Call can be answered from lock screen via system UI |
|
|
|
|
When CallKit is not used, the app falls back to `IncomingCallView` banner.
|
|
|
|
### WebRTC Client
|
|
|
|
| Component | Description |
|
|
|---|---|
|
|
| `WebRTCClient` | Manages peer connection, ICE candidates, media tracks |
|
|
| `WebRTC.swift` | Bridge between native code and WebRTC JavaScript via `WKWebView` |
|
|
| `CallViewRenderers` | `CallViewLocal` and `CallViewRemote` SwiftUI wrappers for video renderers |
|
|
|
|
## Loading / Error States
|
|
|
|
| State | Behavior |
|
|
|---|---|
|
|
| Permissions required | Prompts for microphone (and camera for video) permissions on first call |
|
|
| Connecting | Call overlay shows connecting state; `SoundPlayer` plays connecting tone |
|
|
| WebRTC client creation | `createWebRTCClient()` called on appear and when `canConnectCall` changes |
|
|
| Call ended | `CallSoundsPlayer.vibrate(long: true)` on disconnect if was connected; audio session reset to `.soloAmbient` |
|
|
| Call failed | Call dismissed; WebRTC client cleaned up |
|
|
| No call invitation | `IncomingCallView` body is empty when no active invitation |
|
|
|
|
## Audio Session Management
|
|
|
|
- During call: Audio session configured for voice chat
|
|
- Camera permissions: `AVFoundation.AVCaptureDevice` authorization checked
|
|
- Audio device management: `CallAudioDeviceManager` handles routing changes and device enumeration
|
|
- Post-call cleanup: Audio session reverted to `.soloAmbient`
|
|
|
|
## Related Specs
|
|
|
|
- `spec/services/calls.md` -- Call service specification
|
|
- [Chat](chat.md) -- Call buttons in chat navigation bar
|
|
- [Contact Info](contact-info.md) -- Call buttons in contact info action row
|
|
- [Settings](settings.md) -- Call settings (CallKit, ICE servers, relay policy)
|
|
|
|
## Source Files
|
|
|
|
- `Shared/Views/Call/ActiveCallView.swift` -- Main active call view with video renderers and overlay
|
|
- `Shared/Views/Call/IncomingCallView.swift` -- Incoming call notification banner
|
|
- `Shared/Views/Call/CallController.swift` -- CallKit integration and call lifecycle management
|
|
- `Shared/Views/Call/CallManager.swift` -- Call state management and CXProvider delegate
|
|
- `Shared/Views/Call/CallAudioDeviceManager.swift` -- Audio device enumeration and routing
|
|
- `Shared/Views/Call/AudioDevicePicker.swift` -- Audio output device picker UI
|
|
- `Shared/Views/Call/WebRTC.swift` -- WebRTC signaling bridge via WKWebView
|
|
- `Shared/Views/Call/WebRTCClient.swift` -- WebRTC peer connection management
|
|
- `Shared/Views/Call/CallViewRenderers.swift` -- SwiftUI wrappers for local and remote video views
|
|
- `Shared/Views/Call/SoundPlayer.swift` -- Ringtone and call sound playback
|