@cometchat/skills 4.3.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bin/install.js +27 -0
- package/package.json +14 -1
- package/skills/cometchat/SKILL.md +233 -69
- package/skills/cometchat/references/asking-questions.md +48 -0
- package/skills/cometchat-a11y/SKILL.md +3 -2
- package/skills/cometchat-android-v5/SKILL.md +2 -1
- package/skills/cometchat-android-v5-calls/SKILL.md +36 -22
- package/skills/cometchat-android-v5-calls/references/README.md +1 -1
- package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +7 -5
- package/skills/cometchat-android-v5-calls/references/audio-controls.md +4 -4
- package/skills/cometchat-android-v5-calls/references/call-layouts.md +33 -25
- package/skills/cometchat-android-v5-calls/references/call-session.md +2 -2
- package/skills/cometchat-android-v5-calls/references/custom-ui.md +5 -5
- package/skills/cometchat-android-v5-calls/references/event-listeners.md +2 -2
- package/skills/cometchat-android-v5-calls/references/idle-timeout.md +20 -14
- package/skills/cometchat-android-v5-calls/references/in-call-chat.md +1 -1
- package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +43 -27
- package/skills/cometchat-android-v5-calls/references/participant-management.md +3 -3
- package/skills/cometchat-android-v5-calls/references/raise-hand.md +25 -19
- package/skills/cometchat-android-v5-calls/references/recording.md +2 -2
- package/skills/cometchat-android-v5-calls/references/ringing-integration.md +1 -1
- package/skills/cometchat-android-v5-calls/references/screen-sharing.md +5 -9
- package/skills/cometchat-android-v5-calls/references/session-settings.md +3 -3
- package/skills/cometchat-android-v5-calls/references/setup.md +1 -1
- package/skills/cometchat-android-v5-calls/references/share-invite.md +9 -4
- package/skills/cometchat-android-v5-calls/references/video-controls.md +4 -4
- package/skills/cometchat-android-v5-calls/references/voip-calling.md +2 -2
- package/skills/cometchat-android-v5-components/SKILL.md +4 -3
- package/skills/cometchat-android-v5-core/SKILL.md +5 -3
- package/skills/cometchat-android-v5-customization/SKILL.md +171 -7
- package/skills/cometchat-android-v5-extensions/SKILL.md +7 -4
- package/skills/cometchat-android-v5-features/SKILL.md +5 -4
- package/skills/cometchat-android-v5-placement/SKILL.md +2 -1
- package/skills/cometchat-android-v5-production/SKILL.md +2 -1
- package/skills/cometchat-android-v5-push/SKILL.md +2 -3
- package/skills/cometchat-android-v5-testing/SKILL.md +2 -1
- package/skills/cometchat-android-v5-theming/SKILL.md +2 -1
- package/skills/cometchat-android-v5-troubleshooting/SKILL.md +3 -2
- package/skills/cometchat-android-v6/SKILL.md +2 -1
- package/skills/cometchat-android-v6-builder-settings/SKILL.md +11 -7
- package/skills/cometchat-android-v6-calls/SKILL.md +79 -18
- package/skills/cometchat-android-v6-calls/references/advanced-features.md +87 -0
- package/skills/cometchat-android-v6-calls/references/call-layouts.md +24 -15
- package/skills/cometchat-android-v6-calls/references/call-session.md +2 -2
- package/skills/cometchat-android-v6-calls/references/device-management.md +17 -16
- package/skills/cometchat-android-v6-calls/references/idle-timeout.md +7 -4
- package/skills/cometchat-android-v6-calls/references/in-call-chat.md +13 -8
- package/skills/cometchat-android-v6-calls/references/raise-hand.md +6 -4
- package/skills/cometchat-android-v6-compose-components/SKILL.md +52 -29
- package/skills/cometchat-android-v6-compose-customization/SKILL.md +156 -1
- package/skills/cometchat-android-v6-compose-placement/SKILL.md +129 -40
- package/skills/cometchat-android-v6-compose-theming/SKILL.md +27 -1
- package/skills/cometchat-android-v6-core/SKILL.md +208 -28
- package/skills/cometchat-android-v6-events/SKILL.md +4 -1
- package/skills/cometchat-android-v6-extensions/SKILL.md +2 -1
- package/skills/cometchat-android-v6-features/SKILL.md +26 -2
- package/skills/cometchat-android-v6-kotlin-components/SKILL.md +31 -1
- package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +172 -1
- package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +20 -5
- package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +36 -5
- package/skills/cometchat-android-v6-migration/SKILL.md +44 -42
- package/skills/cometchat-android-v6-production/SKILL.md +6 -3
- package/skills/cometchat-android-v6-push/SKILL.md +43 -2
- package/skills/cometchat-android-v6-testing/SKILL.md +11 -8
- package/skills/cometchat-android-v6-troubleshooting/SKILL.md +26 -5
- package/skills/cometchat-angular-calls/SKILL.md +256 -389
- package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +3 -2
- package/skills/cometchat-angular-calls/references/call-layouts.md +29 -12
- package/skills/cometchat-angular-calls/references/call-session.md +2 -2
- package/skills/cometchat-angular-calls/references/custom-ui.md +18 -10
- package/skills/cometchat-angular-calls/references/device-management.md +53 -34
- package/skills/cometchat-angular-calls/references/group-calls.md +45 -24
- package/skills/cometchat-angular-calls/references/idle-timeout.md +31 -15
- package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +7 -6
- package/skills/cometchat-angular-calls/references/raise-hand.md +9 -4
- package/skills/cometchat-angular-calls/references/recording-screen-share.md +32 -39
- package/skills/cometchat-angular-calls/references/ringing-integration.md +3 -1
- package/skills/cometchat-angular-calls/references/share-invite.md +11 -5
- package/skills/cometchat-angular-calls/references/virtual-background.md +29 -0
- package/skills/cometchat-angular-components/SKILL.md +149 -620
- package/skills/cometchat-angular-core/SKILL.md +232 -312
- package/skills/cometchat-angular-customization/SKILL.md +415 -223
- package/skills/cometchat-angular-features/SKILL.md +216 -334
- package/skills/cometchat-angular-patterns/SKILL.md +168 -359
- package/skills/cometchat-angular-placement/SKILL.md +189 -560
- package/skills/cometchat-angular-production/SKILL.md +241 -92
- package/skills/cometchat-angular-push/SKILL.md +280 -294
- package/skills/cometchat-angular-testing/SKILL.md +430 -158
- package/skills/cometchat-angular-theming/SKILL.md +190 -265
- package/skills/cometchat-angular-troubleshooting/SKILL.md +192 -157
- package/skills/cometchat-astro-patterns/SKILL.md +2 -1
- package/skills/cometchat-calls/SKILL.md +25 -19
- package/skills/cometchat-calls/references/use-case-broadcast.md +15 -10
- package/skills/cometchat-calls/references/use-case-marketplace.md +2 -3
- package/skills/cometchat-calls/references/use-case-support.md +3 -4
- package/skills/cometchat-calls/references/use-case-team.md +23 -12
- package/skills/cometchat-calls/references/use-case-telehealth.md +3 -4
- package/skills/cometchat-components/SKILL.md +163 -25
- package/skills/cometchat-core/SKILL.md +255 -19
- package/skills/cometchat-customization/SKILL.md +50 -25
- package/skills/cometchat-features/SKILL.md +313 -34
- package/skills/cometchat-flutter-v5/SKILL.md +10 -4
- package/skills/cometchat-flutter-v5-calls/SKILL.md +188 -158
- package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +48 -24
- package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +20 -15
- package/skills/cometchat-flutter-v5-calls/references/call-session.md +100 -145
- package/skills/cometchat-flutter-v5-calls/references/device-management.md +12 -8
- package/skills/cometchat-flutter-v5-calls/references/group-calls.md +30 -36
- package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +15 -13
- package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +12 -9
- package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +115 -65
- package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +41 -30
- package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +17 -14
- package/skills/cometchat-flutter-v5-calls/references/share-invite.md +8 -2
- package/skills/cometchat-flutter-v5-conversations/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-core/SKILL.md +5 -4
- package/skills/cometchat-flutter-v5-customization/SKILL.md +136 -5
- package/skills/cometchat-flutter-v5-events/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-messages/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-production/SKILL.md +15 -6
- package/skills/cometchat-flutter-v5-push/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-testing/SKILL.md +17 -6
- package/skills/cometchat-flutter-v5-theming/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +7 -6
- package/skills/cometchat-flutter-v5-users-groups/SKILL.md +3 -2
- package/skills/cometchat-flutter-v6/SKILL.md +17 -16
- package/skills/cometchat-flutter-v6-calls/SKILL.md +72 -57
- package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +5 -3
- package/skills/cometchat-flutter-v6-calls/references/advanced-features.md +89 -0
- package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +15 -12
- package/skills/cometchat-flutter-v6-calls/references/call-session.md +2 -2
- package/skills/cometchat-flutter-v6-calls/references/device-management.md +9 -3
- package/skills/cometchat-flutter-v6-calls/references/group-calls.md +10 -10
- package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +15 -7
- package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +6 -3
- package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +23 -16
- package/skills/cometchat-flutter-v6-components/SKILL.md +32 -11
- package/skills/cometchat-flutter-v6-conversations/SKILL.md +39 -11
- package/skills/cometchat-flutter-v6-core/SKILL.md +182 -21
- package/skills/cometchat-flutter-v6-customization/SKILL.md +97 -25
- package/skills/cometchat-flutter-v6-events/SKILL.md +3 -2
- package/skills/cometchat-flutter-v6-features/SKILL.md +15 -6
- package/skills/cometchat-flutter-v6-messages/SKILL.md +111 -60
- package/skills/cometchat-flutter-v6-migration/SKILL.md +18 -25
- package/skills/cometchat-flutter-v6-placement/SKILL.md +79 -50
- package/skills/cometchat-flutter-v6-production/SKILL.md +13 -12
- package/skills/cometchat-flutter-v6-push/SKILL.md +41 -19
- package/skills/cometchat-flutter-v6-testing/SKILL.md +4 -4
- package/skills/cometchat-flutter-v6-theming/SKILL.md +38 -5
- package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +182 -17
- package/skills/cometchat-flutter-v6-users-groups/SKILL.md +12 -4
- package/skills/cometchat-i18n/SKILL.md +139 -78
- package/skills/cometchat-ios/SKILL.md +4 -2
- package/skills/cometchat-ios-calls/SKILL.md +225 -95
- package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +11 -9
- package/skills/cometchat-ios-calls/references/audio-modes-and-controls.md +45 -0
- package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +6 -7
- package/skills/cometchat-ios-calls/references/call-layouts.md +31 -91
- package/skills/cometchat-ios-calls/references/call-session.md +51 -54
- package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +33 -29
- package/skills/cometchat-ios-calls/references/custom-ui.md +38 -38
- package/skills/cometchat-ios-calls/references/group-calls.md +33 -70
- package/skills/cometchat-ios-calls/references/idle-timeout.md +24 -25
- package/skills/cometchat-ios-calls/references/in-call-chat.md +19 -23
- package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +128 -70
- package/skills/cometchat-ios-calls/references/picture-in-picture.md +20 -20
- package/skills/cometchat-ios-calls/references/raise-hand.md +14 -227
- package/skills/cometchat-ios-calls/references/recording-screen-share.md +35 -122
- package/skills/cometchat-ios-calls/references/ringing-integration.md +17 -16
- package/skills/cometchat-ios-calls/references/share-invite.md +8 -12
- package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +4 -4
- package/skills/cometchat-ios-components/SKILL.md +200 -12
- package/skills/cometchat-ios-core/SKILL.md +173 -45
- package/skills/cometchat-ios-customization/SKILL.md +276 -110
- package/skills/cometchat-ios-features/SKILL.md +64 -36
- package/skills/cometchat-ios-placement/SKILL.md +15 -12
- package/skills/cometchat-ios-production/SKILL.md +12 -4
- package/skills/cometchat-ios-push/SKILL.md +53 -19
- package/skills/cometchat-ios-testing/SKILL.md +14 -9
- package/skills/cometchat-ios-theming/SKILL.md +39 -3
- package/skills/cometchat-ios-troubleshooting/SKILL.md +41 -21
- package/skills/cometchat-native-bare-patterns/SKILL.md +34 -17
- package/skills/cometchat-native-calls/SKILL.md +28 -16
- package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +2 -2
- package/skills/cometchat-native-calls/references/call-layouts.md +15 -14
- package/skills/cometchat-native-calls/references/call-session.md +2 -2
- package/skills/cometchat-native-calls/references/custom-ui.md +12 -8
- package/skills/cometchat-native-calls/references/device-management.md +53 -30
- package/skills/cometchat-native-calls/references/group-calls.md +35 -30
- package/skills/cometchat-native-calls/references/idle-timeout.md +6 -6
- package/skills/cometchat-native-calls/references/in-call-chat.md +10 -8
- package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +2 -2
- package/skills/cometchat-native-calls/references/raise-hand.md +15 -13
- package/skills/cometchat-native-calls/references/recording-screen-share.md +49 -170
- package/skills/cometchat-native-calls/references/share-invite.md +7 -5
- package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +4 -2
- package/skills/cometchat-native-components/SKILL.md +84 -52
- package/skills/cometchat-native-core/SKILL.md +101 -32
- package/skills/cometchat-native-customization/SKILL.md +150 -28
- package/skills/cometchat-native-expo-patterns/SKILL.md +57 -26
- package/skills/cometchat-native-features/SKILL.md +23 -16
- package/skills/cometchat-native-placement/SKILL.md +19 -10
- package/skills/cometchat-native-production/SKILL.md +9 -3
- package/skills/cometchat-native-push/SKILL.md +2 -1
- package/skills/cometchat-native-testing/SKILL.md +1 -2
- package/skills/cometchat-native-theming/SKILL.md +54 -29
- package/skills/cometchat-native-troubleshooting/SKILL.md +9 -3
- package/skills/cometchat-nextjs-patterns/SKILL.md +20 -6
- package/skills/cometchat-placement/SKILL.md +42 -3
- package/skills/cometchat-production/SKILL.md +12 -5
- package/skills/cometchat-react-calls/SKILL.md +220 -10
- package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +4 -3
- package/skills/cometchat-react-calls/references/call-layouts.md +5 -6
- package/skills/cometchat-react-calls/references/call-session.md +1 -1
- package/skills/cometchat-react-calls/references/custom-ui.md +61 -15
- package/skills/cometchat-react-calls/references/device-management.md +55 -51
- package/skills/cometchat-react-calls/references/group-calls.md +18 -23
- package/skills/cometchat-react-calls/references/idle-timeout.md +25 -12
- package/skills/cometchat-react-calls/references/in-call-chat.md +7 -7
- package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +9 -11
- package/skills/cometchat-react-calls/references/raise-hand.md +14 -14
- package/skills/cometchat-react-calls/references/recording-screen-share.md +39 -38
- package/skills/cometchat-react-calls/references/ringing-integration.md +2 -2
- package/skills/cometchat-react-calls/references/share-invite.md +4 -5
- package/skills/cometchat-react-calls/references/testing-calls-on-web.md +20 -2
- package/skills/cometchat-react-calls/references/virtual-background.md +32 -0
- package/skills/cometchat-react-patterns/SKILL.md +44 -4
- package/skills/cometchat-react-push/SKILL.md +258 -72
- package/skills/cometchat-react-router-patterns/SKILL.md +10 -4
- package/skills/cometchat-react-testing/SKILL.md +14 -5
- package/skills/cometchat-theming/SKILL.md +181 -18
- package/skills/cometchat-troubleshooting/SKILL.md +40 -20
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cometchat-ios-calls
|
|
3
|
-
description: CometChat Calls SDK v5 integration for native iOS (Swift; SwiftUI + UIKit hosting). Covers SDK install (SPM + CocoaPods), CometChatCalls init, dual-SDK ringing (Chat SDK initiateCall + Calls SDK
|
|
3
|
+
description: CometChat Calls SDK v5 integration for native iOS (Swift; SwiftUI + UIKit hosting). Covers SDK install (SPM + CocoaPods), CometChatCalls init, dual-SDK ringing (Chat SDK initiateCall + Calls SDK generateToken/startSession), CallKit + PushKit VoIP push, AVAudioSession routing, mixed-stack hosting (UIViewControllerRepresentable for SwiftUI), Info.plist permissions + Background Modes, and additive-vs-standalone modes.
|
|
4
4
|
license: "MIT"
|
|
5
5
|
compatibility: "Xcode 15+, Swift 5.9+, iOS 13+ deployment target; CometChatCallsSDK 5.x; CometChatSDK 4.x; CometChatUIKitSwift 5.x (additive mode)"
|
|
6
|
-
allowed-tools: "shell, file-read, file-search, file-list, ask-user"
|
|
7
6
|
metadata:
|
|
8
7
|
author: "CometChat"
|
|
9
8
|
version: "4.0.0"
|
|
@@ -22,66 +21,51 @@ Production-grade voice + video calling for native iOS. Loaded by `cometchat-call
|
|
|
22
21
|
- `cometchat-ios-core` — Chat SDK init, login, `Secrets.swift` / `.xcconfig` credential conventions, SwiftUI vs UIKit entry-point detection
|
|
23
22
|
|
|
24
23
|
**Ground truth:**
|
|
25
|
-
- SDK source —
|
|
26
|
-
- Sample app —
|
|
24
|
+
- SDK source — `calls-sdk-ios-5/sdk/`
|
|
25
|
+
- Sample app — `calls-sdk-ios-5/sample-apps/cometchat-calls-sample-app-ios/`
|
|
27
26
|
- `Package.swift` — `https://github.com/cometchat/calls-sdk-ios.git` (SPM)
|
|
28
27
|
- Public docs — https://www.cometchat.com/docs/calls/ios/overview
|
|
29
28
|
|
|
30
29
|
---
|
|
31
30
|
|
|
32
|
-
##
|
|
31
|
+
## iOS Calls SDK v5 resolution — verified working (re-checked 2026-06-04)
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
This affects every v5 tag (`5.0.0`, `5.0.0-beta.1` … `5.0.0-beta.3`). The `Package.swift` and `.podspec` both reference the same broken URL.
|
|
42
|
-
|
|
43
|
-
**Until upstream republishes the binary:**
|
|
44
|
-
- Customers on iOS should stay on **v4.2.x** of the Calls SDK (it has its own WebRTC dependency that's still hosted)
|
|
45
|
-
- If you must use v5 for parity with other platforms, contact CometChat support for a working binary or a private SPM fork
|
|
46
|
-
- This skill's v5 setup section assumes the binary is available — that assumption is currently invalid for iOS only
|
|
47
|
-
|
|
48
|
-
Tracking this so the next audit pass can verify when it's fixed. The vendor sample-apps at `~/Downloads/calls-sdk/calls-sdk-ios-5/sample-apps/` reference the same broken binary — they don't ship a workaround.
|
|
33
|
+
> An earlier draft of this skill warned that "the iOS Calls SDK v5 binary is broken / missing from Cloudsmith — stay on v4.2.x." **That warning was wrong and has been removed.** It was based on a hand-constructed URL (`…/raw/versions/124.0.4/CometChatWebRTC-124.0.4.xcframework.zip`) that 404s — but that is NOT the path the podspec/`Package.swift` actually fetches, so its 404 never proved anything. Verified 2026-06-04:
|
|
34
|
+
> - **Additive (UI Kit) path:** `CometChatCallsSDK` v5 ships **vendored inside `CometChatUIKitSwift`** — a clean `pod install` resolves `CometChatUIKitSwift (5.1.13)` (which bundles the v5 CallsSDK framework) with **no 404**. The audited `CometChatCallsSDK.swiftinterface` (v5 shape: `generateToken`/`startSession`, no `login`) came straight out of that resolved framework.
|
|
35
|
+
> - **Standalone path:** `CometChatCallsSDK` v5.0.0 is consumable via CocoaPods (e.g. the internal VoIP+APNs sample under Linear ENG-35167 builds against it).
|
|
36
|
+
>
|
|
37
|
+
> If you ever DO hit a missing-WebRTC binary on a direct standalone `pod 'CometChatCallsSDK'` install, treat it as an environment/registry hiccup and check the current podspec URL — it is not a known blanket failure, and there is no open vendor ticket for it.
|
|
49
38
|
|
|
50
39
|
---
|
|
51
40
|
|
|
52
41
|
## 1. The seven hard rules — iOS specialization
|
|
53
42
|
|
|
54
|
-
|
|
43
|
+
> ⚠️ **TOP PRIORITY (ENG-35710): Auth-token passing is the most-broken step on iOS Calls integrations.** Unlike Android / Flutter / JS, the **iOS Calls SDK 5.x has NO separate login step** — there is no `CometChatCalls.login(...)` and no `CometChatCalls.getLoggedInUser()` (those are phantom; verified absent from `CometChatCallsSDK`). Auth is supplied **per session** as the `authToken:` argument to `CometChatCalls.generateToken(authToken:sessionID:)`. Every tester who hit "calls don't work" on iOS traced back to that token: (a) the token was empty/nil → `generateToken` fails with **"auth token cannot be null"**; (b) a server-minted token expired between mint and `generateToken` (default ~30-minute TTL); (c) the client-side `apiKey` was passed instead of the user's auth token. Before scaffolding ANY iOS calls code, confirm the auth path (dev: read `CometChat.getUserAuthToken()`; production: fetch a fresh server-minted token) and feed it to `generateToken`. Mixing them is the canonical "ringing but never joins" iOS failure mode.
|
|
44
|
+
|
|
45
|
+
### 1.0 The iOS Calls SDK has NO separate login (v5)
|
|
55
46
|
|
|
56
|
-
|
|
47
|
+
Unlike the Android / Flutter / JS Calls SDKs, **`CometChatCalls` on iOS has no `login()` and no `getLoggedInUser()`** — those methods do not exist in `CometChatCallsSDK` 5.x. There is nothing to "log in" to. Once the Chat SDK session exists, you authorize each call session by passing an **auth token** to `generateToken(authToken:sessionID:)`, then `startSession(callToken:callSetting:view:)` with the returned call token (full flow in §1.1).
|
|
57
48
|
|
|
58
49
|
```swift
|
|
59
50
|
import CometChatSDK
|
|
60
51
|
import CometChatCallsSDK
|
|
61
52
|
|
|
53
|
+
// Chat SDK login is the ONLY login. (UI Kit users: CometChatUIKit.login already did this.)
|
|
62
54
|
CometChat.login(UID: uid, authKey: AUTH_KEY) { user in
|
|
63
|
-
// Chat SDK ready —
|
|
64
|
-
|
|
65
|
-
// both ready — incoming-call listener can be registered, calls can fire
|
|
66
|
-
} onError: { error in
|
|
67
|
-
// surface to user — common cause: typo in app id / auth key
|
|
68
|
-
}
|
|
55
|
+
// Chat SDK ready. No CometChatCalls.login() exists — do NOT call it.
|
|
56
|
+
// The incoming-call listener can be registered now; per-call auth happens via generateToken.
|
|
69
57
|
} onError: { error in
|
|
70
|
-
// chat login failed
|
|
58
|
+
// chat login failed
|
|
71
59
|
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
For production with server-minted tokens:
|
|
75
60
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
} onError: { error in /* … */ }
|
|
61
|
+
// Dev: the auth token for generateToken comes from the Chat SDK:
|
|
62
|
+
let authToken = CometChat.getUserAuthToken() // String? — pass to generateToken(authToken:)
|
|
63
|
+
// Production: fetch a fresh server-minted token from your backend instead.
|
|
80
64
|
```
|
|
81
65
|
|
|
82
66
|
**Surprises:**
|
|
83
|
-
-
|
|
84
|
-
-
|
|
67
|
+
- There is **no Calls-SDK session to persist** — the Chat SDK's Keychain session is the only persisted login. On app start just confirm `CometChat.getLoggedInUser() != nil`.
|
|
68
|
+
- `generateToken` / `startSession` errors hit the `onError` closure (not `do/try/catch`). The error type is `CometChatCallException` — has `errorDescription` and `errorCode`.
|
|
85
69
|
|
|
86
70
|
### 1.1 Dual-SDK contract
|
|
87
71
|
|
|
@@ -91,7 +75,7 @@ Chat SDK (`CometChatSDK`) initiates ringing; Calls SDK (`CometChatCallsSDK`) run
|
|
|
91
75
|
// ✓ RIGHT — initiate ringing (Chat SDK)
|
|
92
76
|
import CometChatSDK
|
|
93
77
|
|
|
94
|
-
let outgoing = Call(
|
|
78
|
+
let outgoing = Call(receiverId: receiverUid, callType: .video, receiverType: .user)
|
|
95
79
|
CometChat.initiateCall(call: outgoing, onSuccess: { initiated in
|
|
96
80
|
// initiated.sessionID is what the Calls SDK will join
|
|
97
81
|
}, onError: { error in
|
|
@@ -100,34 +84,113 @@ CometChat.initiateCall(call: outgoing, onSuccess: { initiated in
|
|
|
100
84
|
```
|
|
101
85
|
|
|
102
86
|
```swift
|
|
103
|
-
// ✓ RIGHT —
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// -
|
|
108
|
-
//
|
|
109
|
-
// -
|
|
87
|
+
// ✓ RIGHT — start the WebRTC session (Calls SDK 5.x) after acceptance.
|
|
88
|
+
// iOS Calls SDK 5.x is a TWO-STEP flow: generateToken → startSession.
|
|
89
|
+
// There is NO joinSession, NO CallSession singleton, and NO SessionSettingsBuilder
|
|
90
|
+
// in the 5.x SDK — those are phantom. The real builder is CallSettingsBuilder.
|
|
91
|
+
// - CallSettingsBuilder (NOT SessionSettingsBuilder) builds the CallSettings
|
|
92
|
+
// - generateToken(authToken:sessionID:) FIRST, then startSession(callToken:callSetting:view:)
|
|
93
|
+
// - Attach the event listener via CallSettingsBuilder.setDelegate(_:) (CallsEventsDelegate)
|
|
110
94
|
import CometChatCallsSDK
|
|
111
95
|
|
|
112
|
-
let settings =
|
|
113
|
-
.
|
|
114
|
-
.
|
|
115
|
-
.
|
|
96
|
+
let settings = CallSettingsBuilder()
|
|
97
|
+
.setStartVideoMuted(false)
|
|
98
|
+
.setStartAudioMuted(false)
|
|
99
|
+
.setDelegate(callListener) // any CallsEventsDelegate — onCallEnded, onUserJoined, …
|
|
116
100
|
.build()
|
|
117
101
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
102
|
+
// loggedInAuthToken: the current user's auth token — CometChat.getUserAuthToken()
|
|
103
|
+
// (User has NO .authToken property; getUserAuthToken() is the real accessor)
|
|
104
|
+
CometChatCalls.generateToken(authToken: loggedInAuthToken, sessionID: sessionID) { callToken in
|
|
105
|
+
guard let callToken = callToken else { return }
|
|
106
|
+
CometChatCalls.startSession(
|
|
107
|
+
callToken: callToken,
|
|
108
|
+
callSetting: settings,
|
|
109
|
+
view: callContainerView // UIView with measurable bounds
|
|
110
|
+
) { _ in
|
|
111
|
+
// session started — the call UI is rendered into callContainerView
|
|
112
|
+
} onError: { error in
|
|
113
|
+
print("startSession failed: \(error?.errorDescription ?? "unknown")")
|
|
114
|
+
}
|
|
126
115
|
} onError: { error in
|
|
127
|
-
print("
|
|
116
|
+
print("generateToken failed: \(error?.errorDescription ?? "unknown")")
|
|
128
117
|
}
|
|
129
118
|
```
|
|
130
119
|
|
|
120
|
+
### 1.1a End-to-end initiate→join sequence (ENG-35710)
|
|
121
|
+
|
|
122
|
+
After `CometChat.initiateCall` the caller's session is NOT auto-joined — the gap between *initiation* and *joining* is the second canonical iOS failure (after auth-token). Three events must fire in sequence; the caller side handles each in a different callback.
|
|
123
|
+
|
|
124
|
+
> **Corrected 2026-06-02 against `calls-sdk-ios/sample-apps/cometchat-calls-sample-app-ringing-ios/CometChatCallsRinging/AppState.swift:213`** — the listener protocol is **`CometChatCallDelegate`** (NOT `CometChatCallsListener` as earlier drafts said), and each callback takes TWO parameters (`Call?` + `CometChatException?`), NOT one. Earlier example would not compile.
|
|
125
|
+
|
|
126
|
+
```swift
|
|
127
|
+
// Step A: register the listener on app start (before any call fires)
|
|
128
|
+
// Listener ID is a String; listener instance is "self" or any class conforming
|
|
129
|
+
// to CometChatCallDelegate.
|
|
130
|
+
CometChat.addCallListener(callListenerID, self)
|
|
131
|
+
|
|
132
|
+
// Step B: conform to CometChatCallDelegate (NOT CometChatCallsListener)
|
|
133
|
+
extension YourClass: CometChatCallDelegate {
|
|
134
|
+
// Caller side: the OTHER party accepted — NOW join the session
|
|
135
|
+
func onOutgoingCallAccepted(acceptedCall: Call?, error: CometChatException?) {
|
|
136
|
+
if let error = error { /* surface */ return }
|
|
137
|
+
guard let call = acceptedCall, let sessionID = call.sessionID else { return }
|
|
138
|
+
startCallSession(sessionID: sessionID)
|
|
139
|
+
}
|
|
140
|
+
// Receiver side: incoming call rang — present accept UI; on accept, start the session
|
|
141
|
+
func onIncomingCallReceived(incomingCall: Call?, error: CometChatException?) {
|
|
142
|
+
if let error = error { /* surface */ return }
|
|
143
|
+
guard let call = incomingCall else { return }
|
|
144
|
+
presentIncomingCallUI(for: call) { accepted in
|
|
145
|
+
if accepted {
|
|
146
|
+
CometChat.acceptCall(sessionID: call.sessionID ?? "") { acceptedCall in
|
|
147
|
+
self.startCallSession(sessionID: acceptedCall?.sessionID ?? "")
|
|
148
|
+
} onError: { _ in /* surface */ }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
func onOutgoingCallRejected(rejectedCall: Call?, error: CometChatException?) { /* end UI, cleanup */ }
|
|
153
|
+
func onIncomingCallCancelled(canceledCall: Call?, error: CometChatException?) { /* dismiss incoming UI — label is canceledCall: (single L) */ }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Don't forget to remove the listener on teardown
|
|
157
|
+
// CometChat.removeCallListener(callListenerID)
|
|
158
|
+
|
|
159
|
+
// Step B: kick the call off (caller — your "Call" button taps this)
|
|
160
|
+
let outgoing = Call(receiverId: targetUid, callType: .video, receiverType: .user)
|
|
161
|
+
CometChat.initiateCall(call: outgoing, onSuccess: { initiated in
|
|
162
|
+
// initiated.sessionID is what the session will use — but DO NOT start the
|
|
163
|
+
// session here. Wait for onOutgoingCallAccepted on the listener. Starting before
|
|
164
|
+
// the remote accepts means you're alone in an empty session.
|
|
165
|
+
}, onError: { error in /* surface */ })
|
|
166
|
+
|
|
167
|
+
// Step C: start the session (caller in onOutgoingCallAccepted, receiver after acceptCall)
|
|
168
|
+
// 5.x flow: generateToken(authToken:sessionID:) → startSession(callToken:callSetting:view:)
|
|
169
|
+
func startCallSession(sessionID: String) {
|
|
170
|
+
let settings = CallSettingsBuilder()
|
|
171
|
+
.setStartVideoMuted(false)
|
|
172
|
+
.setStartAudioMuted(false)
|
|
173
|
+
.setDelegate(self) // self conforms to CallsEventsDelegate
|
|
174
|
+
.build()
|
|
175
|
+
CometChatCalls.generateToken(authToken: loggedInAuthToken, sessionID: sessionID) { callToken in
|
|
176
|
+
guard let callToken = callToken else { return }
|
|
177
|
+
CometChatCalls.startSession(
|
|
178
|
+
callToken: callToken,
|
|
179
|
+
callSetting: settings,
|
|
180
|
+
view: callContainerView // UIView WITH non-zero bounds (lay out first)
|
|
181
|
+
) { _ in
|
|
182
|
+
// session started
|
|
183
|
+
} onError: { error in
|
|
184
|
+
print("startSession failed: \(error?.errorDescription ?? "unknown")")
|
|
185
|
+
}
|
|
186
|
+
} onError: { error in
|
|
187
|
+
print("generateToken failed: \(error?.errorDescription ?? "unknown")")
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The shape: `initiateCall` → wait for `onOutgoingCallAccepted` on your `CometChatCallDelegate` → `generateToken` → `startSession`. Skipping the listener and starting inside `initiateCall`'s `onSuccess` is the "ringing but never joins" trap — you'll see the call connect on the wire but the receiver's accept never reaches your code.
|
|
193
|
+
|
|
131
194
|
### 1.2 CallKit + PushKit are mandatory
|
|
132
195
|
|
|
133
196
|
iOS will not deliver standard push notifications to a backgrounded/terminated app for an incoming call — the app would have to be foregrounded for it to ring. CallKit + PushKit is the only correct path:
|
|
@@ -168,13 +231,13 @@ Same rule as the chat dispatcher / `cometchat-ios-production`. Production calls
|
|
|
168
231
|
Releasing the camera + mic on iOS is straightforward; the gotcha is `AVAudioSession`:
|
|
169
232
|
|
|
170
233
|
```swift
|
|
171
|
-
import CometChatCallsSDK
|
|
234
|
+
import CometChatCallsSDK
|
|
172
235
|
|
|
173
236
|
func endCall() {
|
|
174
|
-
// v5:
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
|
|
237
|
+
// v5: end the session via the static CometChatCalls.endSession().
|
|
238
|
+
// There is NO CallSession singleton and NO leaveSession() in the 5.x SDK —
|
|
239
|
+
// all in-call control is via static funcs on CometChatCalls.
|
|
240
|
+
CometChatCalls.endSession()
|
|
178
241
|
callContainer.subviews.forEach { $0.removeFromSuperview() }
|
|
179
242
|
|
|
180
243
|
// CRITICAL: deactivate the audio session, otherwise the speaker stays
|
|
@@ -191,15 +254,17 @@ func endCall() {
|
|
|
191
254
|
}
|
|
192
255
|
```
|
|
193
256
|
|
|
194
|
-
|
|
257
|
+
In-call controls are **static funcs on `CometChatCalls`** (there is no `CallSession` type in the 5.x Calls SDK). Audio/video toggles take a `Bool`:
|
|
195
258
|
|
|
196
259
|
```swift
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
260
|
+
CometChatCalls.audioMuted(true) // mute mic; false = unmute
|
|
261
|
+
CometChatCalls.videoPaused(true) // pause video; false = resume
|
|
262
|
+
CometChatCalls.switchCamera()
|
|
263
|
+
CometChatCalls.enterPIPMode() // picture-in-picture; exitPIPMode() to leave
|
|
264
|
+
CometChatCalls.startRecording() // stopRecording() to end
|
|
265
|
+
// NOTE: the iOS Calls SDK 5.x has NO local screen-share initiation API
|
|
266
|
+
// (no startScreenShare/stopScreenShare) — iOS can only RECEIVE a remote
|
|
267
|
+
// participant's screen share, not start one.
|
|
203
268
|
```
|
|
204
269
|
|
|
205
270
|
Skipping the `setActive(false, options: .notifyOthersOnDeactivation)` is the canonical "music doesn't resume after the call" bug.
|
|
@@ -223,10 +288,68 @@ In standalone mode, you do NOT render an in-app incoming-call screen. CallKit's
|
|
|
223
288
|
|
|
224
289
|
1. Keep `PKPushRegistry` alive — register in `application(_:didFinishLaunchingWithOptions:)` (UIKit) or `App.init()` (SwiftUI's `@main`)
|
|
225
290
|
2. On VoIP payload → call `CXProvider.reportNewIncomingCall`
|
|
226
|
-
3. Implement `CXProviderDelegate` `provider(_:perform:)` for `CXAnswerCallAction` — this is where you finally call `CometChatCalls.
|
|
291
|
+
3. Implement `CXProviderDelegate` `provider(_:perform:)` for `CXAnswerCallAction` — this is where you finally call `CometChatCalls.generateToken` then `startSession`
|
|
227
292
|
|
|
228
293
|
In additive mode, the UI Kit's incoming-call view can be used for in-foreground rings; CallKit handles backgrounded/terminated rings.
|
|
229
294
|
|
|
295
|
+
### 1.7a Default incoming/outgoing UI fallback (ENG-35710)
|
|
296
|
+
|
|
297
|
+
Two iOS testers shipped without a foreground incoming/outgoing screen because the skill jumped straight to CallKit and never showed what to render when the app is already in-foreground. Result: a Call rings on the wire, but the user-facing app shows nothing — the call connects, the call drops, no feedback.
|
|
298
|
+
|
|
299
|
+
**If the developer hasn't asked for a custom incoming-call UI, wire the kit's defaults:**
|
|
300
|
+
|
|
301
|
+
```swift
|
|
302
|
+
// SwiftUI host
|
|
303
|
+
import SwiftUI
|
|
304
|
+
import UIKit
|
|
305
|
+
import CometChatUIKitSwift
|
|
306
|
+
|
|
307
|
+
// The kit ships call UI as UIViewControllers (CometChatIncomingCall / CometChatOutgoingCall /
|
|
308
|
+
// CometChatOngoingCall) — there are NO `…SwiftUI`-suffixed wrappers. Bridge with
|
|
309
|
+
// UIViewControllerRepresentable. Present the controller when your delegate fires (§1.1a);
|
|
310
|
+
// configure it via the kit's IncomingCallConfiguration rather than a constructor arg.
|
|
311
|
+
struct CometChatIncomingCallView: UIViewControllerRepresentable {
|
|
312
|
+
func makeUIViewController(context: Context) -> CometChatIncomingCall {
|
|
313
|
+
CometChatIncomingCall()
|
|
314
|
+
}
|
|
315
|
+
func updateUIViewController(_ vc: CometChatIncomingCall, context: Context) {}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
struct AppRootView: View {
|
|
319
|
+
@State private var hasIncomingCall = false
|
|
320
|
+
var body: some View {
|
|
321
|
+
ZStack {
|
|
322
|
+
ContentView() // your app's tabs / nav
|
|
323
|
+
if hasIncomingCall {
|
|
324
|
+
CometChatIncomingCallView()
|
|
325
|
+
.ignoresSafeArea()
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// flip `hasIncomingCall` from your CometChatCallDelegate.onIncomingCallReceived (see §1.1a)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
```swift
|
|
334
|
+
// UIKit host
|
|
335
|
+
class RootViewController: UIViewController {
|
|
336
|
+
override func viewDidLoad() {
|
|
337
|
+
super.viewDidLoad()
|
|
338
|
+
// Install the kit's incoming-call VC above all other view controllers
|
|
339
|
+
let incoming = CometChatIncomingCall()
|
|
340
|
+
addChild(incoming)
|
|
341
|
+
view.addSubview(incoming.view)
|
|
342
|
+
incoming.view.frame = view.bounds
|
|
343
|
+
incoming.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
344
|
+
incoming.didMove(toParent: self)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Mounting at the root (above your nav / tab structure) means foreground rings work app-wide — same idea as the web skill's "mount above the route boundary" rule. CallKit still handles backgrounded/terminated rings; the kit's incoming-call VC handles foreground rings. Together they're the complete foreground-and-background coverage.
|
|
350
|
+
|
|
351
|
+
If the developer DOES want a custom UI: tell them to (a) implement `CometChatCallDelegate.onIncomingCallReceived` to drive their own SwiftUI/UIKit screen, (b) call `CometChat.acceptCall` / `rejectCall` from that screen, and (c) on accept, follow the `generateToken` → `startSession` recipe in §1.1a. The kit's default UI is the recommended starting point because it already wires accept/reject/timer/profile-pic; replicating it from scratch is a 200-line side quest.
|
|
352
|
+
|
|
230
353
|
---
|
|
231
354
|
|
|
232
355
|
## 2. Setup
|
|
@@ -280,9 +403,11 @@ CometChat.init(appId: Secrets.cometchatAppID, appSettings: appSettings) { isInit
|
|
|
280
403
|
.setRegion(Secrets.cometchatRegion)
|
|
281
404
|
.build()
|
|
282
405
|
|
|
283
|
-
CometChatCalls.init(
|
|
406
|
+
CometChatCalls.init(callsAppSettings: callAppSettings, onSuccess: { _ in
|
|
284
407
|
// ready — register PushKit (rule 1.2) and CXProvider (rule 1.7) here
|
|
285
|
-
}
|
|
408
|
+
}, onError: { error in
|
|
409
|
+
print("CometChatCalls.init failed: \(error?.errorDescription ?? "")")
|
|
410
|
+
})
|
|
286
411
|
}
|
|
287
412
|
```
|
|
288
413
|
|
|
@@ -296,19 +421,19 @@ Credentials via `Secrets.swift` (gitignored) or `.xcconfig` Build Settings — s
|
|
|
296
421
|
|
|
297
422
|
| Type | Purpose |
|
|
298
423
|
|---|---|
|
|
299
|
-
| `CometChatCalls` | Top-level facade — init
|
|
300
|
-
| `CallSettingsBuilder` | Per-session config (
|
|
301
|
-
| `
|
|
302
|
-
| `CallType` | `.
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
424
|
+
| `CometChatCalls` | Top-level facade — `init`, `generateToken`, `startSession`, `endSession`, `audioMuted(_:)`, `videoPaused(_:)`, `switchCamera`, `enterPIPMode`/`exitPIPMode`, `startRecording`/`stopRecording`, `addCallEventListener` |
|
|
425
|
+
| `CallSettingsBuilder` | Per-session config (audio-only, presenter, hide buttons, start muted, `setDelegate`) → `.build()` returns `CallSettings` |
|
|
426
|
+
| `CallSettings` | The built per-session config passed to `startSession(callToken:callSetting:view:)` (there is no `CallSession` object in 5.x — `startSession` returns a session-id `String`) |
|
|
427
|
+
| `CallType` | `.video` / `.audio` / `.audioVideo` (swiftinterface:294-297) — there is NO `.voice` |
|
|
428
|
+
| `DisplayModes` (enum) | `.default` / `.single` / `.spotlight` (swiftinterface:175) — passed to `CallSettingsBuilder.setMode(_:)`. The current setter is `setMode(_ value: DisplayModes)` (swiftinterface:281); the `setMode(_ value: NSString)` string overload (swiftinterface:280) is DEPRECATED. There is no `LayoutMode`/`.tile`/`.sidebar` |
|
|
429
|
+
| `CallLogsRequest` + `CallLogsBuilder` | Paginated call history (note the plural — there is no `CallLogRequest`/`CallLogRequestBuilder`) |
|
|
430
|
+
| `CallsEventsDelegate` (protocol) | Lifecycle + media + participant + button events — set via `CallSettingsBuilder.setDelegate(_:)` or `CometChatCalls.addCallEventListener(observerId:delegate:)`. (NOT `CometChatCallsEventsListener` — that name doesn't exist.) |
|
|
306
431
|
|
|
307
432
|
### UI Kit views (additive mode — `CometChatUIKitSwift`)
|
|
308
433
|
|
|
309
434
|
| View / VC | Purpose |
|
|
310
435
|
|---|---|
|
|
311
|
-
| `
|
|
436
|
+
| `CometChatCallButtons` | Voice + video button row (standalone or in `CometChatMessageHeader`) |
|
|
312
437
|
| `CometChatIncomingCall` (UIViewController) | Foreground in-app ring UI |
|
|
313
438
|
| `CometChatOutgoingCall` (UIViewController) | Dialing UI |
|
|
314
439
|
| `CometChatOngoingCall` (UIViewController) | Active call UI hosting WebRTC |
|
|
@@ -333,11 +458,11 @@ When `product === "voice-video"` and there is no existing UI Kit.
|
|
|
333
458
|
|
|
334
459
|
### 4a. Standalone — Session mode (meeting-room UX, no ringing)
|
|
335
460
|
|
|
336
|
-
Calls SDK ONLY. NO Chat SDK, NO CallKit, NO PushKit. Matches
|
|
461
|
+
Calls SDK ONLY. NO Chat SDK, NO CallKit, NO PushKit. Matches `calls-sdk-ios-5/sample-apps/cometchat-calls-sample-app-ios/`. Scaffold:
|
|
337
462
|
|
|
338
|
-
1. **App entry** — `CometChatCalls.init(
|
|
463
|
+
1. **App entry** — `CometChatCalls.init(callsAppSettings:)` with a `CallAppSettingsBuilder().setAppId(...).setRegion(...).build()` ONLY. No `CometChat.init`, no `CometChat.login`, no PushKit, no CallKit.
|
|
339
464
|
2. **`JoinSessionView.swift`** — UID picker + "Start meeting" / "Join meeting" + state.
|
|
340
|
-
3. **`CallView.swift` + `CallContainerView: UIViewRepresentable`** —
|
|
465
|
+
3. **`CallView.swift` + `CallContainerView: UIViewRepresentable`** — `CometChatCalls.generateToken(authToken:sessionID:)` then `CometChatCalls.startSession(callToken:callSetting:view:)`. Coordinator conforms to `CallsEventsDelegate` (set via `CallSettingsBuilder.setDelegate`). See `references/call-session.md`.
|
|
341
466
|
4. **`Info.plist` patch** — Camera + microphone permissions ONLY. No `audio` or `voip` Background Modes needed.
|
|
342
467
|
5. **Universal Link routing** — meeting URL → CallView.
|
|
343
468
|
|
|
@@ -348,29 +473,33 @@ Calls SDK ONLY. NO Chat SDK, NO CallKit, NO PushKit. Matches `~/Downloads/calls-
|
|
|
348
473
|
Dual-SDK + CallKit + PushKit. Scaffold:
|
|
349
474
|
|
|
350
475
|
1. **App entry** — Chat SDK + Calls SDK init, PushKit + CallKit registration (rule 1.2, 1.7).
|
|
351
|
-
2. **`CallKitProviderDelegate.swift`** — `CXProviderDelegate` implementation. Routes `CXAnswerCallAction` → `CometChatCalls.
|
|
476
|
+
2. **`CallKitProviderDelegate.swift`** — `CXProviderDelegate` implementation. Routes `CXAnswerCallAction` → `CometChatCalls.generateToken` then `startSession(callToken:callSetting:view:)`. Routes `CXEndCallAction` → `CometChatCalls.endSession()` + `AVAudioSession` cleanup (rule 1.5).
|
|
352
477
|
3. **`PushRegistryDelegate.swift`** — `PKPushRegistryDelegate` listening on `.voIP`. On payload → `CXProvider.reportNewIncomingCall` immediately.
|
|
353
478
|
4. **`ProfileView.swift` (SwiftUI) or `ProfileViewController.swift` (UIKit)** — Hosts call buttons next to user info. Tap → `CometChat.initiateCall`.
|
|
354
479
|
5. **`OngoingCallView.swift`** — Custom view hosting the SDK's call surface via `UIViewRepresentable` bridging. Implements rule 1.5 teardown.
|
|
355
|
-
6. **`CallLogsView.swift`** — `/calls` equivalent — `
|
|
480
|
+
6. **`CallLogsView.swift`** — `/calls` equivalent — `CallLogsRequest.CallLogsBuilder`.
|
|
356
481
|
7. **`Info.plist` patch** — Background Modes (rule 1.3), permissions (rule 1.6).
|
|
357
482
|
8. **VoIP Services certificate setup** — manual step (Apple Developer portal + App Store Connect). The skill documents the steps; cannot automate.
|
|
358
483
|
|
|
359
484
|
## 5. Additive integration
|
|
360
485
|
|
|
361
|
-
When `cometchat-ios` is already integrated.
|
|
486
|
+
When `cometchat-ios` is already integrated.
|
|
487
|
+
|
|
488
|
+
> ✅ **Kit-default path FIRST (what the canonical `SampleApp` actually does).** `CometChatCallsSDK` is **vendored inside `CometChatUIKitSwift`** — no separate SPM/Pod add, and **no separate `CometChatCalls.init`**. The sample turns calling on with **`UIKitSettings…enable(inAppIncomingCall: true)`** at init (`SampleApp/SceneDelegate.swift`), then just drops in `CometChatCallButtons(...).set(user:)` (e.g. in the user-details screen) and a `CometChatCallLogs` tab — the kit handles `generateToken`/`startSession` and the incoming-call UI internally. You do NOT hand-write `CometChatCalls.init` + a manual `generateToken → startSession` flow on this path. (The manual two-step is the **standalone / custom-UI** path only — §1.1 / §4.)
|
|
489
|
+
|
|
490
|
+
The kit-default additive recipe:
|
|
491
|
+
1. Confirm `CometChatUIKitSwift` is present (CallsSDK is bundled — nothing extra to install).
|
|
492
|
+
2. Set **`.enable(inAppIncomingCall: true)`** on the `UIKitSettings` builder at init (the one calling switch).
|
|
493
|
+
3. Add Background Modes (`voip`, `remote-notification`, `audio`) + camera/mic permissions to `Info.plist`.
|
|
494
|
+
4. Drop in `CometChatCallButtons` (e.g. user-details / contact screen) — the kit also auto-renders them in `CometChatMessageHeader` when CallsSDK is present; add `CometChatCallLogs` as a tab/route.
|
|
495
|
+
5. (Optional) CallKit + PushKit for background VoIP (asks user — same opt-in as Android).
|
|
362
496
|
|
|
363
|
-
|
|
364
|
-
2. Adds `CometChatCalls.init(...)` to the existing `CometChat.init` success callback.
|
|
365
|
-
3. Adds Background Modes + permissions to `Info.plist`.
|
|
366
|
-
4. Wires `CometChatMessageHeader` call buttons (already rendered by the kit — just enable them).
|
|
367
|
-
5. Adds CallKit + PushKit (asks user — same opt-in as Android).
|
|
368
|
-
6. Adds `CallLogsView` as an additional tab/route.
|
|
497
|
+
Only reach for `CometChatCalls.init` + `generateToken`/`startSession` (§1.1) when building a **custom call surface** without the kit's call components.
|
|
369
498
|
|
|
370
499
|
## 6. Anti-patterns
|
|
371
500
|
|
|
372
501
|
1. **Skipping CallKit + PushKit** in standalone mode. The app cannot ring backgrounded/terminated devices any other way. App Store reviewers test this.
|
|
373
|
-
2. **Calling `CXProvider.reportNewIncomingCall` after async work.** Apple terminates the app process if the report happens more than ~5 seconds after PushKit delivery. Report immediately, then do the actual `
|
|
502
|
+
2. **Calling `CXProvider.reportNewIncomingCall` after async work.** Apple terminates the app process if the report happens more than ~5 seconds after PushKit delivery. Report immediately, then do the actual `generateToken` + `startSession` from inside `CXAnswerCallAction`.
|
|
374
503
|
3. **Forgetting `setActive(false, options: .notifyOthersOnDeactivation)`** on hangup. Music/phone-call audio sounds wrong until the next foreground. The "looks fine in dev, fails review" bug.
|
|
375
504
|
4. **Declaring `voip` in `UIBackgroundModes` without using PushKit.** Apple rejects.
|
|
376
505
|
5. **Mixing CallKit and an in-app incoming-call screen** in standalone mode. Causes double-rings and confused state. CallKit owns standalone rings; in-app UI is additive-mode only.
|
|
@@ -402,6 +531,7 @@ When `cometchat-ios` is already integrated. The skill:
|
|
|
402
531
|
|
|
403
532
|
## 8. Pointers
|
|
404
533
|
|
|
534
|
+
- `references/audio-modes-and-controls.md` — audio-route switching (speaker/earpiece/Bluetooth) + custom control panel (button-disable matrix)
|
|
405
535
|
- `cometchat-ios-core` — Chat SDK init, login, `Secrets.swift` conventions
|
|
406
536
|
- `cometchat-ios-components` — full UI Kit catalog (additive mode)
|
|
407
537
|
- `cometchat-ios-push` — APNs setup; some overlap with PushKit but distinct (PushKit is VoIP-only)
|
|
@@ -72,15 +72,17 @@ CometChatUIKit.init(uikitSettings: chatSettings) { result in
|
|
|
72
72
|
|
|
73
73
|
## Step 4 — Login
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
Log in with the Chat SDK only. **There is no `CometChatCalls.login` and no `CometChat.loginAsync`** — the Calls SDK has no separate login step; it authenticates per call session via `generateToken`.
|
|
76
76
|
|
|
77
77
|
```swift
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
CometChat.login(UID: uid, authKey: authKey, onSuccess: { user in
|
|
79
|
+
// logged in — that's it. Do NOT call CometChatCalls.login (doesn't exist).
|
|
80
|
+
// When a call starts, call CometChatCalls.generateToken(authToken:sessionID:)
|
|
81
|
+
// with CometChat.getUserAuthToken() (User has no `authToken` property).
|
|
82
|
+
}, onError: { error in /* surface */ })
|
|
81
83
|
```
|
|
82
84
|
|
|
83
|
-
If you use server-minted auth tokens (recommended),
|
|
85
|
+
If you use server-minted auth tokens (recommended), use the `CometChat.login(UID:authToken:...)` overload instead of `authKey`.
|
|
84
86
|
|
|
85
87
|
---
|
|
86
88
|
|
|
@@ -141,9 +143,9 @@ Init this handler from your `AppDelegate.didFinishLaunchingWithOptions`.
|
|
|
141
143
|
## Step 7 — Hangup teardown
|
|
142
144
|
|
|
143
145
|
```swift
|
|
144
|
-
func endCall(sessionId: String)
|
|
145
|
-
CometChatCalls.
|
|
146
|
-
|
|
146
|
+
func endCall(sessionId: String) {
|
|
147
|
+
CometChatCalls.endSession() // Calls SDK — EXISTS (not leaveSession)
|
|
148
|
+
CometChat.endCall(sessionID: sessionId, onSuccess: { _ in }, onError: { _ in })
|
|
147
149
|
callProvider.reportCall(with: callUUID, endedAt: nil, reason: .remoteEnded)
|
|
148
150
|
}
|
|
149
151
|
```
|
|
@@ -156,7 +158,7 @@ func endCall(sessionId: String) async {
|
|
|
156
158
|
- [ ] Background Modes capability + Info.plist UIBackgroundModes (audio + voip + remote-notification)
|
|
157
159
|
- [ ] NSCameraUsageDescription + NSMicrophoneUsageDescription
|
|
158
160
|
- [ ] Calls init runs AFTER chat init succeeds
|
|
159
|
-
- [ ] `CometChatCalls.login`
|
|
161
|
+
- [ ] NO `CometChatCalls.login` (doesn't exist) — Calls auth is per-session via `generateToken`
|
|
160
162
|
- [ ] `CometChatIncomingCall` mounted at root (SwiftUI overlay or UIKit window-root)
|
|
161
163
|
- [ ] PushKit registry initialized + reports to CallKit within 5s
|
|
162
164
|
- [ ] Hangup teardown ends both SDK + CallKit + chat-side call record
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# iOS — Audio Modes + Custom Control Panel
|
|
2
|
+
|
|
3
|
+
Verified against `CometChatCallsSDK` 5.x (`callssdk.swiftinterface`).
|
|
4
|
+
|
|
5
|
+
## 1. Audio modes (speaker / earpiece / Bluetooth)
|
|
6
|
+
|
|
7
|
+
The SDK reports the available audio routes via the `CallsEventsDelegate` as typed `CallAudioMode` objects (swiftinterface:133 — `mode: String`, `isSelected: Bool`), and lets you switch programmatically by passing a `CallAudioMode`.
|
|
8
|
+
|
|
9
|
+
```swift
|
|
10
|
+
import CometChatCallsSDK
|
|
11
|
+
|
|
12
|
+
// Observe available routes + current selection (typed form).
|
|
13
|
+
// swiftinterface:44 onAudioModeChanged(mode: [CallAudioMode])
|
|
14
|
+
func onAudioModeChanged(mode: [CallAudioMode]) {
|
|
15
|
+
self.audioRoutes = mode // each has .mode (e.g. "SPEAKER") and .isSelected
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Switch route with a typed CallAudioMode — the current setter.
|
|
19
|
+
// swiftinterface:234 CometChatCalls.setAudioMode(_ audioMode: CallAudioMode)
|
|
20
|
+
CometChatCalls.setAudioMode(CallAudioMode(mode: "SPEAKER", isSelected: true))
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Note the kit's default in-call UI already shows an audio-mode button; you only need the above for a **custom** control surface (or to drive routing yourself).
|
|
24
|
+
|
|
25
|
+
Verified against `CometChatCallsSDK` swiftinterface: the typed `CallsEventsDelegate.onAudioModeChanged(mode: [CallAudioMode])` (swiftinterface:44) and `CometChatCalls.setAudioMode(_ audioMode: CallAudioMode)` (swiftinterface:234) are the CURRENT API. The string forms — `onAudioModeChanged(audioModeList: NSArray)` (swiftinterface:43) and `setAudioMode(mode: String)` (swiftinterface:235) — are DEPRECATED.
|
|
26
|
+
|
|
27
|
+
## 2. Custom control panel (hide built-in buttons)
|
|
28
|
+
|
|
29
|
+
There is no separate "panel" object — you compose a custom control bar by **disabling the kit's default buttons** on the `CallSettingsBuilder`, then rendering your own controls (wired to `audioMuted(_:)`, `videoPaused(_:)`, `switchCamera()`, `endSession()`, etc. from the main skill):
|
|
30
|
+
|
|
31
|
+
```swift
|
|
32
|
+
let settings = CallSettingsBuilder()
|
|
33
|
+
.setEndCallButtonDisable(true)
|
|
34
|
+
.setMuteAudioButtonDisable(true)
|
|
35
|
+
.setPauseVideoButtonDisable(true)
|
|
36
|
+
.setSwitchCameraButtonDisable(true)
|
|
37
|
+
.setAudioModeButtonDisable(true)
|
|
38
|
+
.setShowRecordingButton(false)
|
|
39
|
+
.build()
|
|
40
|
+
// then overlay your own SwiftUI/UIKit control bar on the call container
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Verified (on `CallSettingsBuilder`): `setEndCallButtonDisable`, `setMuteAudioButtonDisable`, `setPauseVideoButtonDisable`, `setSwitchCameraButtonDisable`, `setAudioModeButtonDisable`, `setShowRecordingButton` — all `(Bool) -> Self`.
|
|
44
|
+
|
|
45
|
+
> **Not supported on iOS** (no SDK symbol — do not author): Virtual Background, and local screen-share **initiation** (receive-only). See the main skill's resolution note.
|
|
@@ -43,8 +43,7 @@ func configureForCall(isVideo: Bool) throws {
|
|
|
43
43
|
|
|
44
44
|
```swift
|
|
45
45
|
func endCall() {
|
|
46
|
-
|
|
47
|
-
CometChatCallsSDK.CallSession.shared.leaveSession()
|
|
46
|
+
CometChatCalls.endSession() // EXISTS on the static facade in v5
|
|
48
47
|
|
|
49
48
|
do {
|
|
50
49
|
try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
|
|
@@ -132,14 +131,14 @@ extension CallManager: CXProviderDelegate {
|
|
|
132
131
|
options: [.allowBluetooth, .defaultToSpeaker]
|
|
133
132
|
)
|
|
134
133
|
|
|
135
|
-
// Store sessionId; defer
|
|
134
|
+
// Store sessionId; defer startSession to didActivate
|
|
136
135
|
self.pendingActivation = pendingSessionIds[action.callUUID]
|
|
137
136
|
action.fulfill()
|
|
138
137
|
}
|
|
139
138
|
}
|
|
140
139
|
```
|
|
141
140
|
|
|
142
|
-
CallKit calls `setActive(true)` for you when it's done with its lock-screen UI. You call `
|
|
141
|
+
CallKit calls `setActive(true)` for you when it's done with its lock-screen UI. You call `startSession` (after `generateToken`) from `didActivate`.
|
|
143
142
|
|
|
144
143
|
For non-CallKit-driven calls (outgoing from inside the app), you do `setActive(true)` yourself.
|
|
145
144
|
|
|
@@ -152,7 +151,7 @@ For non-CallKit-driven calls (outgoing from inside the app), you do `setActive(t
|
|
|
152
151
|
| Music doesn't resume after call | Missing `.notifyOthersOnDeactivation` | Add to `setActive(false, ...)` call |
|
|
153
152
|
| Voice call sounds quiet, like through phone receiver | Missing `.defaultToSpeaker` option | Add to `setCategory` options |
|
|
154
153
|
| Bluetooth headphones not used during call | Missing `.allowBluetooth` option | Add to `setCategory` options |
|
|
155
|
-
| CXAnswerCallAction races with `setActive(true)` | Manual `setActive(true)` in answer handler | Defer `
|
|
154
|
+
| CXAnswerCallAction races with `setActive(true)` | Manual `setActive(true)` in answer handler | Defer `startSession` to `didActivate` |
|
|
156
155
|
| Echo / feedback during voice call | Wrong `mode` (e.g. `.default` instead of `.voiceChat`) | Use `.voiceChat` or `.videoChat` |
|
|
157
156
|
| Call audio works in foreground but cuts in background | UIBackgroundModes missing `audio` | Add `audio` to `Info.plist` UIBackgroundModes |
|
|
158
157
|
|
|
@@ -175,10 +174,10 @@ NotificationCenter.default.addObserver(
|
|
|
175
174
|
switch type {
|
|
176
175
|
case .began:
|
|
177
176
|
// Phone call started — pause our call's audio (CallKit may auto-handle this for you)
|
|
178
|
-
CometChatCalls.
|
|
177
|
+
CometChatCalls.audioMuted(true) // NOT muteAudio
|
|
179
178
|
case .ended:
|
|
180
179
|
// Phone call ended — resume
|
|
181
|
-
CometChatCalls.
|
|
180
|
+
CometChatCalls.audioMuted(false)
|
|
182
181
|
try? AVAudioSession.sharedInstance().setActive(true)
|
|
183
182
|
@unknown default:
|
|
184
183
|
break
|