@cometchat/skills 3.1.0 → 4.1.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/README.md +75 -17
- package/bin/install.js +523 -43
- package/package.json +17 -8
- package/skills/cometchat/SKILL.md +850 -109
- package/skills/cometchat-android-v5/SKILL.md +120 -0
- package/skills/cometchat-android-v5-components/SKILL.md +430 -0
- package/skills/cometchat-android-v5-core/SKILL.md +468 -0
- package/skills/cometchat-android-v5-customization/SKILL.md +305 -0
- package/skills/cometchat-android-v5-extensions/SKILL.md +124 -0
- package/skills/cometchat-android-v5-features/SKILL.md +130 -0
- package/skills/cometchat-android-v5-placement/SKILL.md +276 -0
- package/skills/cometchat-android-v5-production/SKILL.md +94 -0
- package/skills/cometchat-android-v5-push/SKILL.md +620 -0
- package/skills/cometchat-android-v5-testing/SKILL.md +187 -0
- package/skills/cometchat-android-v5-theming/SKILL.md +166 -0
- package/skills/cometchat-android-v5-troubleshooting/SKILL.md +73 -0
- package/skills/cometchat-android-v6/SKILL.md +107 -0
- package/skills/cometchat-android-v6-builder-settings/SKILL.md +145 -0
- package/skills/cometchat-android-v6-compose-components/SKILL.md +202 -0
- package/skills/cometchat-android-v6-compose-customization/SKILL.md +280 -0
- package/skills/cometchat-android-v6-compose-placement/SKILL.md +213 -0
- package/skills/cometchat-android-v6-compose-theming/SKILL.md +224 -0
- package/skills/cometchat-android-v6-core/SKILL.md +354 -0
- package/skills/cometchat-android-v6-events/SKILL.md +212 -0
- package/skills/cometchat-android-v6-extensions/SKILL.md +191 -0
- package/skills/cometchat-android-v6-features/SKILL.md +130 -0
- package/skills/cometchat-android-v6-kotlin-components/SKILL.md +197 -0
- package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +268 -0
- package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +248 -0
- package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +202 -0
- package/skills/cometchat-android-v6-production/SKILL.md +187 -0
- package/skills/cometchat-android-v6-push/SKILL.md +274 -0
- package/skills/cometchat-android-v6-testing/SKILL.md +279 -0
- package/skills/cometchat-android-v6-troubleshooting/SKILL.md +249 -0
- package/skills/cometchat-angular-components/SKILL.md +706 -0
- package/skills/cometchat-angular-core/SKILL.md +444 -0
- package/skills/cometchat-angular-customization/SKILL.md +424 -0
- package/skills/cometchat-angular-features/SKILL.md +447 -0
- package/skills/cometchat-angular-patterns/SKILL.md +447 -0
- package/skills/cometchat-angular-placement/SKILL.md +685 -0
- package/skills/cometchat-angular-production/SKILL.md +415 -0
- package/skills/cometchat-angular-theming/SKILL.md +365 -0
- package/skills/cometchat-angular-troubleshooting/SKILL.md +329 -0
- package/skills/cometchat-astro-patterns/SKILL.md +3 -3
- package/skills/cometchat-components/SKILL.md +2 -0
- package/skills/cometchat-core/SKILL.md +11 -6
- package/skills/cometchat-customization/references/component-catalog.md +1 -1
- package/skills/cometchat-features/SKILL.md +176 -108
- package/skills/cometchat-flutter-v5/SKILL.md +167 -0
- package/skills/cometchat-flutter-v5-calls/SKILL.md +192 -0
- package/skills/cometchat-flutter-v5-conversations/SKILL.md +117 -0
- package/skills/cometchat-flutter-v5-core/SKILL.md +221 -0
- package/skills/cometchat-flutter-v5-customization/SKILL.md +227 -0
- package/skills/cometchat-flutter-v5-events/SKILL.md +155 -0
- package/skills/cometchat-flutter-v5-messages/SKILL.md +258 -0
- package/skills/cometchat-flutter-v5-production/SKILL.md +207 -0
- package/skills/cometchat-flutter-v5-push/SKILL.md +284 -0
- package/skills/cometchat-flutter-v5-theming/SKILL.md +160 -0
- package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +129 -0
- package/skills/cometchat-flutter-v5-users-groups/SKILL.md +151 -0
- package/skills/cometchat-flutter-v6/SKILL.md +445 -0
- package/skills/cometchat-flutter-v6-calls/SKILL.md +333 -0
- package/skills/cometchat-flutter-v6-components/SKILL.md +365 -0
- package/skills/cometchat-flutter-v6-conversations/SKILL.md +210 -0
- package/skills/cometchat-flutter-v6-core/SKILL.md +305 -0
- package/skills/cometchat-flutter-v6-customization/SKILL.md +666 -0
- package/skills/cometchat-flutter-v6-events/SKILL.md +216 -0
- package/skills/cometchat-flutter-v6-features/SKILL.md +406 -0
- package/skills/cometchat-flutter-v6-messages/SKILL.md +333 -0
- package/skills/cometchat-flutter-v6-migration/SKILL.md +381 -0
- package/skills/cometchat-flutter-v6-placement/SKILL.md +398 -0
- package/skills/cometchat-flutter-v6-production/SKILL.md +632 -0
- package/skills/cometchat-flutter-v6-theming/SKILL.md +260 -0
- package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +726 -0
- package/skills/cometchat-flutter-v6-users-groups/SKILL.md +216 -0
- package/skills/cometchat-ios/SKILL.md +323 -0
- package/skills/cometchat-ios-components/SKILL.md +651 -0
- package/skills/cometchat-ios-core/SKILL.md +822 -0
- package/skills/cometchat-ios-customization/SKILL.md +825 -0
- package/skills/cometchat-ios-features/SKILL.md +725 -0
- package/skills/cometchat-ios-placement/SKILL.md +750 -0
- package/skills/cometchat-ios-production/SKILL.md +730 -0
- package/skills/cometchat-ios-push/SKILL.md +582 -0
- package/skills/cometchat-ios-theming/SKILL.md +631 -0
- package/skills/cometchat-ios-troubleshooting/SKILL.md +983 -0
- package/skills/cometchat-native-bare-patterns/SKILL.md +470 -0
- package/skills/cometchat-native-components/SKILL.md +594 -0
- package/skills/cometchat-native-core/SKILL.md +407 -0
- package/skills/cometchat-native-customization/SKILL.md +594 -0
- package/skills/cometchat-native-expo-patterns/SKILL.md +485 -0
- package/skills/cometchat-native-features/SKILL.md +608 -0
- package/skills/cometchat-native-placement/SKILL.md +500 -0
- package/skills/cometchat-native-production/SKILL.md +694 -0
- package/skills/cometchat-native-push/SKILL.md +593 -0
- package/skills/cometchat-native-testing/SKILL.md +583 -0
- package/skills/cometchat-native-theming/SKILL.md +656 -0
- package/skills/cometchat-native-troubleshooting/SKILL.md +433 -0
- package/skills/cometchat-nextjs-patterns/SKILL.md +5 -5
- package/skills/cometchat-placement/SKILL.md +28 -0
- package/skills/cometchat-react-patterns/SKILL.md +55 -7
- package/skills/cometchat-react-router-patterns/SKILL.md +23 -21
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cometchat-ios-core
|
|
3
|
+
description: "Shared rules for CometChat iOS UI Kit v5. Always loaded alongside placement skills. Read this first."
|
|
4
|
+
license: "MIT"
|
|
5
|
+
compatibility: "iOS 13+; Swift 5.0+; CometChatUIKitSwift ^5; CometChatSDK ^4"
|
|
6
|
+
allowed-tools: "executeBash, readFile, fileSearch, listDirectory"
|
|
7
|
+
metadata:
|
|
8
|
+
author: "CometChat"
|
|
9
|
+
version: "3.0.0"
|
|
10
|
+
tags: "chat cometchat ios swift core rules initialization patterns"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
This is the foundational skill for every CometChat iOS UI Kit v5 integration. It teaches HOW CometChat works on iOS — initialization, login, the manager pattern, and anti-patterns — so you can write project-appropriate code instead of relying on templates.
|
|
16
|
+
|
|
17
|
+
**Read this skill first, before any placement or component skill.**
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. Installation
|
|
22
|
+
|
|
23
|
+
### 0. First — confirm a dependency manifest exists (or create one)
|
|
24
|
+
|
|
25
|
+
A freshly-created Xcode project (`File → New → App` from the GUI) ships **no `Podfile`, no `Package.swift`, and no Swift Package Manager refs in `*.xcodeproj/project.pbxproj`**. Before touching any of the integration code below, you MUST establish a dependency-management mechanism — otherwise `import CometChatUIKitSwift` will hit `Unable to resolve module dependency: 'CometChatSDK'` at the first build attempt and the entire integration is dead on arrival.
|
|
26
|
+
|
|
27
|
+
**Detection:**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
ls Podfile Package.swift 2>/dev/null
|
|
31
|
+
grep -l "XCRemoteSwiftPackageReference\|repositoryURL.*cometchat" *.xcodeproj/project.pbxproj 2>/dev/null
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If all three return empty → **fresh Xcode project, no dep manager**. Pick one and set it up before continuing:
|
|
35
|
+
|
|
36
|
+
**Option A — CocoaPods (most common, easiest to script):**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cd <project-root>
|
|
40
|
+
cat > Podfile <<'POD'
|
|
41
|
+
platform :ios, '13.0'
|
|
42
|
+
use_frameworks!
|
|
43
|
+
|
|
44
|
+
target 'YourAppTargetName' do
|
|
45
|
+
pod 'CometChatUIKitSwift', '~> 5.1'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
post_install do |installer|
|
|
49
|
+
installer.pods_project.targets.each do |target|
|
|
50
|
+
target.build_configurations.each do |config|
|
|
51
|
+
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
POD
|
|
56
|
+
pod install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
After `pod install`, work from `YourApp.xcworkspace` (NOT `.xcodeproj`) — CocoaPods rewires the workspace to include the Pods project.
|
|
60
|
+
|
|
61
|
+
**Option B — Swift Package Manager (no Podfile, no `.xcworkspace`):**
|
|
62
|
+
|
|
63
|
+
The user must add the package via Xcode's GUI (the SPM dependency lives in `*.xcodeproj/project.pbxproj` and there's no clean CLI tooling to edit that file safely). Print these instructions verbatim:
|
|
64
|
+
|
|
65
|
+
> 1. Open `<YourApp>.xcodeproj` in Xcode
|
|
66
|
+
> 2. **File → Add Package Dependencies…**
|
|
67
|
+
> 3. Paste URL: `https://github.com/cometchat/cometchat-uikit-ios`
|
|
68
|
+
> 4. **Add Package** → keep "Up to Next Major Version" defaults → **Add Package** again
|
|
69
|
+
> 5. Confirm `CometChatUIKitSwift` appears under your app target's *Frameworks, Libraries, and Embedded Content*
|
|
70
|
+
|
|
71
|
+
**Then verify the package landed:**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
grep -E "cometchat-uikit-ios|CometChatUIKitSwift" *.xcodeproj/project.pbxproj | head -2
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If grep returns matches, the SPM dep is in. If it doesn't, the user didn't complete step 4 in Xcode — surface that explicitly and stop until they have.
|
|
78
|
+
|
|
79
|
+
**HARD STOP if neither option is in place.** Do not write `import CometChatUIKitSwift` into any Swift file until either `pod install` completes successfully or the SPM grep above returns matches. Skipping this step produces an integration that compiles only after the user does extra setup work — a worse outcome than asking them up-front.
|
|
80
|
+
|
|
81
|
+
### CocoaPods (full reference — only if you skipped Option A above)
|
|
82
|
+
|
|
83
|
+
Add to your `Podfile`:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
platform :ios, '13.0'
|
|
87
|
+
use_frameworks!
|
|
88
|
+
|
|
89
|
+
target 'YourApp' do
|
|
90
|
+
pod 'CometChatUIKitSwift', '~> 5.1'
|
|
91
|
+
end
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Then run:
|
|
95
|
+
```bash
|
|
96
|
+
pod install
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Important: Disable User Script Sandboxing (Xcode 15+)**
|
|
100
|
+
|
|
101
|
+
After running `pod install`, you must disable user script sandboxing in your project's Build Settings:
|
|
102
|
+
|
|
103
|
+
1. Open your `.xcworkspace` file
|
|
104
|
+
2. Select your app target
|
|
105
|
+
3. Go to **Build Settings**
|
|
106
|
+
4. Search for "User Script Sandboxing"
|
|
107
|
+
5. Set **ENABLE_USER_SCRIPT_SANDBOXING** to **No**
|
|
108
|
+
|
|
109
|
+
Or add this to your `Podfile` to do it automatically:
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
post_install do |installer|
|
|
113
|
+
installer.pods_project.targets.each do |target|
|
|
114
|
+
target.build_configurations.each do |config|
|
|
115
|
+
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Swift Package Manager
|
|
122
|
+
|
|
123
|
+
Add the package URL in Xcode (File → Add Package Dependencies):
|
|
124
|
+
|
|
125
|
+
**CometChat UI Kit (includes SDK):**
|
|
126
|
+
```
|
|
127
|
+
https://github.com/cometchat/cometchat-uikit-ios
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**CometChat SDK only (if needed separately):**
|
|
131
|
+
```
|
|
132
|
+
https://github.com/cometchat/chat-sdk-ios
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**CometChat Calls SDK (for voice/video calls):**
|
|
136
|
+
```
|
|
137
|
+
https://github.com/cometchat/cometchat-calls-sdk-ios
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Or add to `Package.swift`:
|
|
141
|
+
```swift
|
|
142
|
+
dependencies: [
|
|
143
|
+
.package(url: "https://github.com/cometchat/cometchat-uikit-ios", from: "5.0.0"),
|
|
144
|
+
// Optional: Add calls SDK for voice/video
|
|
145
|
+
// .package(url: "https://github.com/cometchat/cometchat-calls-sdk-ios", from: "4.0.0")
|
|
146
|
+
]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### GitHub Repositories
|
|
150
|
+
|
|
151
|
+
| Package | Repository | Description |
|
|
152
|
+
|---------|------------|-------------|
|
|
153
|
+
| UI Kit | https://github.com/cometchat/cometchat-uikit-ios | Ready-to-use UI components |
|
|
154
|
+
| Chat SDK | https://github.com/cometchat/chat-sdk-ios | Core messaging SDK |
|
|
155
|
+
| Calls SDK | https://github.com/cometchat/cometchat-calls-sdk-ios | Voice & video calling |
|
|
156
|
+
| Sample App | https://github.com/cometchat/cometchat-sample-app-ios | Sample implementation |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 2. Initialization
|
|
161
|
+
|
|
162
|
+
CometChat must be initialized exactly once before any UI component is used. Initialization is asynchronous and must complete fully before mounting any `CometChat*` view controller.
|
|
163
|
+
|
|
164
|
+
### UIKitSettings Builder
|
|
165
|
+
|
|
166
|
+
```swift
|
|
167
|
+
import CometChatUIKitSwift
|
|
168
|
+
|
|
169
|
+
let uiKitSettings = UIKitSettings()
|
|
170
|
+
.set(appID: "YOUR_APP_ID")
|
|
171
|
+
.set(authKey: "YOUR_AUTH_KEY") // Required for dev mode
|
|
172
|
+
.set(region: "us") // "us", "eu", or "in"
|
|
173
|
+
.subscribePresenceForAllUsers() // Enable online/offline indicators
|
|
174
|
+
.build()
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Init must happen once
|
|
178
|
+
|
|
179
|
+
Use a singleton manager to prevent double-init:
|
|
180
|
+
|
|
181
|
+
```swift
|
|
182
|
+
import CometChatUIKitSwift
|
|
183
|
+
import CometChatSDK
|
|
184
|
+
|
|
185
|
+
final class CometChatManager {
|
|
186
|
+
static let shared = CometChatManager()
|
|
187
|
+
|
|
188
|
+
private var isInitialized = false
|
|
189
|
+
private var initializationError: Error?
|
|
190
|
+
|
|
191
|
+
private init() {}
|
|
192
|
+
|
|
193
|
+
func initialize(
|
|
194
|
+
appID: String,
|
|
195
|
+
authKey: String,
|
|
196
|
+
region: String,
|
|
197
|
+
completion: @escaping (Result<Bool, Error>) -> Void
|
|
198
|
+
) {
|
|
199
|
+
guard !isInitialized else {
|
|
200
|
+
completion(.success(true))
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let uiKitSettings = UIKitSettings()
|
|
205
|
+
.set(appID: appID)
|
|
206
|
+
.set(authKey: authKey)
|
|
207
|
+
.set(region: region)
|
|
208
|
+
.subscribePresenceForAllUsers()
|
|
209
|
+
.build()
|
|
210
|
+
|
|
211
|
+
CometChatUIKit(uiKitSettings: uiKitSettings) { result in
|
|
212
|
+
switch result {
|
|
213
|
+
case .success(let success):
|
|
214
|
+
self.isInitialized = success
|
|
215
|
+
completion(.success(success))
|
|
216
|
+
case .failure(let error):
|
|
217
|
+
self.initializationError = error
|
|
218
|
+
completion(.failure(error))
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Init in AppDelegate (UIKit apps)
|
|
226
|
+
|
|
227
|
+
```swift
|
|
228
|
+
import UIKit
|
|
229
|
+
import CometChatUIKitSwift
|
|
230
|
+
|
|
231
|
+
@main
|
|
232
|
+
class AppDelegate: UIResponder, UIApplicationDelegate {
|
|
233
|
+
|
|
234
|
+
func application(
|
|
235
|
+
_ application: UIApplication,
|
|
236
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
237
|
+
) -> Bool {
|
|
238
|
+
|
|
239
|
+
CometChatManager.shared.initialize(
|
|
240
|
+
appID: "YOUR_APP_ID",
|
|
241
|
+
authKey: "YOUR_AUTH_KEY",
|
|
242
|
+
region: "us"
|
|
243
|
+
) { result in
|
|
244
|
+
switch result {
|
|
245
|
+
case .success:
|
|
246
|
+
print("CometChat initialized successfully")
|
|
247
|
+
case .failure(let error):
|
|
248
|
+
print("CometChat initialization failed: \(error)")
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return true
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Init in App struct (SwiftUI apps)
|
|
258
|
+
|
|
259
|
+
```swift
|
|
260
|
+
import SwiftUI
|
|
261
|
+
import CometChatUIKitSwift
|
|
262
|
+
|
|
263
|
+
@main
|
|
264
|
+
struct YourApp: App {
|
|
265
|
+
|
|
266
|
+
init() {
|
|
267
|
+
CometChatManager.shared.initialize(
|
|
268
|
+
appID: "YOUR_APP_ID",
|
|
269
|
+
authKey: "YOUR_AUTH_KEY",
|
|
270
|
+
region: "us"
|
|
271
|
+
) { result in
|
|
272
|
+
switch result {
|
|
273
|
+
case .success:
|
|
274
|
+
print("CometChat initialized successfully")
|
|
275
|
+
case .failure(let error):
|
|
276
|
+
print("CometChat initialization failed: \(error)")
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
var body: some Scene {
|
|
282
|
+
WindowGroup {
|
|
283
|
+
ContentView()
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 3. Login
|
|
292
|
+
|
|
293
|
+
### Development mode
|
|
294
|
+
|
|
295
|
+
Use `CometChatUIKit.login(uid:)` with a test UID. Every new CometChat app comes with five pre-created test users: `cometchat-uid-1` through `cometchat-uid-5`.
|
|
296
|
+
|
|
297
|
+
**Important:** The login callback uses `.success` and `.onError` cases, NOT Swift's standard `Result` type.
|
|
298
|
+
|
|
299
|
+
```swift
|
|
300
|
+
CometChatUIKit.login(uid: "cometchat-uid-1") { result in
|
|
301
|
+
switch result {
|
|
302
|
+
case .success(let user):
|
|
303
|
+
print("Logged in as: \(user.name ?? "")")
|
|
304
|
+
// Proceed to chat UI
|
|
305
|
+
case .onError(let error):
|
|
306
|
+
print("Login failed: \(error.errorDescription)")
|
|
307
|
+
@unknown default:
|
|
308
|
+
break
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Production mode
|
|
314
|
+
|
|
315
|
+
Use `CometChatUIKit.login(authToken:)` with a token obtained from your backend:
|
|
316
|
+
|
|
317
|
+
```swift
|
|
318
|
+
CometChatUIKit.login(authToken: authToken) { result in
|
|
319
|
+
switch result {
|
|
320
|
+
case .success(let user):
|
|
321
|
+
print("Logged in as: \(user.name ?? "")")
|
|
322
|
+
case .onError(let error):
|
|
323
|
+
print("Login failed: \(error.errorDescription)")
|
|
324
|
+
@unknown default:
|
|
325
|
+
break
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Getting the current logged-in user
|
|
331
|
+
|
|
332
|
+
```swift
|
|
333
|
+
// Synchronous — use when you know init is complete
|
|
334
|
+
if let currentUser = CometChatUIKit.getLoggedInUser() {
|
|
335
|
+
print("Logged in as: \(currentUser.name ?? "")")
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Logout
|
|
340
|
+
|
|
341
|
+
```swift
|
|
342
|
+
if let currentUser = CometChat.getLoggedInUser() {
|
|
343
|
+
CometChatUIKit.logout(user: currentUser) { result in
|
|
344
|
+
switch result {
|
|
345
|
+
case .success:
|
|
346
|
+
print("Logged out successfully")
|
|
347
|
+
case .onError(let error):
|
|
348
|
+
print("Logout failed: \(error.errorDescription)")
|
|
349
|
+
@unknown default:
|
|
350
|
+
break
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## 3.1 Error Handling
|
|
359
|
+
|
|
360
|
+
CometChat uses `CometChatException` for errors. **Important:** Use `errorDescription` property, NOT `localizedDescription`.
|
|
361
|
+
|
|
362
|
+
### CometChatException Properties
|
|
363
|
+
|
|
364
|
+
```swift
|
|
365
|
+
// CometChatException has these properties:
|
|
366
|
+
error.errorCode // String - error code like "ERR_UID_NOT_FOUND"
|
|
367
|
+
error.errorDescription // String - human-readable description
|
|
368
|
+
error.details // [String: Any]? - additional details
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Correct Error Handling
|
|
372
|
+
|
|
373
|
+
```swift
|
|
374
|
+
CometChatUIKit.login(uid: "user-123") { result in
|
|
375
|
+
switch result {
|
|
376
|
+
case .success(let user):
|
|
377
|
+
print("Logged in: \(user.name ?? "")")
|
|
378
|
+
case .onError(let error):
|
|
379
|
+
print("Error: \(error.errorDescription)")
|
|
380
|
+
print("Code: \(error.errorCode)")
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Error Handling in Closures
|
|
386
|
+
|
|
387
|
+
```swift
|
|
388
|
+
// For onError closures where error might be optional:
|
|
389
|
+
CometChat.getUser(UID: "user-123") { user in
|
|
390
|
+
print("User: \(user?.name ?? "")")
|
|
391
|
+
} onError: { error in
|
|
392
|
+
// error is CometChatException? (optional)
|
|
393
|
+
print("Error: \(error?.errorDescription ?? "Unknown error")")
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// For ApiStatus enum results:
|
|
397
|
+
CometChatUIKit.create(user: newUser) { result in
|
|
398
|
+
switch result {
|
|
399
|
+
case .success(let user):
|
|
400
|
+
print("Created: \(user.name ?? "")")
|
|
401
|
+
case .onError(let error):
|
|
402
|
+
// error is CometChatException (non-optional)
|
|
403
|
+
print("Error: \(error.errorDescription)")
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Common Error Codes
|
|
409
|
+
|
|
410
|
+
| Code | Description |
|
|
411
|
+
|---|---|
|
|
412
|
+
| `ERR_UID_NOT_FOUND` | User doesn't exist |
|
|
413
|
+
| `ERR_ALREADY_LOGGED_IN` | User already logged in |
|
|
414
|
+
| `ERR_NOT_LOGGED_IN` | No active session |
|
|
415
|
+
| `AUTH_ERR_AUTH_TOKEN_NOT_FOUND` | Invalid auth token |
|
|
416
|
+
| `ERR_INVALID_APP_ID` | Wrong App ID |
|
|
417
|
+
| `ERR_INVALID_API_KEY` | Wrong API/Auth Key |
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## 4. Credentials Management
|
|
422
|
+
|
|
423
|
+
### Using a Constants file (Development)
|
|
424
|
+
|
|
425
|
+
```swift
|
|
426
|
+
// Constants.swift
|
|
427
|
+
struct CometChatConstants {
|
|
428
|
+
static let appID = "YOUR_APP_ID"
|
|
429
|
+
static let authKey = "YOUR_AUTH_KEY"
|
|
430
|
+
static let region = "us"
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Important:** Add `Constants.swift` to `.gitignore` for production apps.
|
|
435
|
+
|
|
436
|
+
### Using Info.plist
|
|
437
|
+
|
|
438
|
+
Add keys to your `Info.plist`:
|
|
439
|
+
```xml
|
|
440
|
+
<key>CometChatAppID</key>
|
|
441
|
+
<string>YOUR_APP_ID</string>
|
|
442
|
+
<key>CometChatAuthKey</key>
|
|
443
|
+
<string>YOUR_AUTH_KEY</string>
|
|
444
|
+
<key>CometChatRegion</key>
|
|
445
|
+
<string>us</string>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Read them in code:
|
|
449
|
+
```swift
|
|
450
|
+
guard let appID = Bundle.main.object(forInfoDictionaryKey: "CometChatAppID") as? String,
|
|
451
|
+
let authKey = Bundle.main.object(forInfoDictionaryKey: "CometChatAuthKey") as? String,
|
|
452
|
+
let region = Bundle.main.object(forInfoDictionaryKey: "CometChatRegion") as? String else {
|
|
453
|
+
fatalError("CometChat credentials not found in Info.plist")
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Using xcconfig files (Recommended for production)
|
|
458
|
+
|
|
459
|
+
Create `Debug.xcconfig` and `Release.xcconfig`:
|
|
460
|
+
```
|
|
461
|
+
// Debug.xcconfig
|
|
462
|
+
COMETCHAT_APP_ID = your_app_id
|
|
463
|
+
COMETCHAT_AUTH_KEY = your_auth_key
|
|
464
|
+
COMETCHAT_REGION = us
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Reference in `Info.plist`:
|
|
468
|
+
```xml
|
|
469
|
+
<key>CometChatAppID</key>
|
|
470
|
+
<string>$(COMETCHAT_APP_ID)</string>
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## 5. The Manager Pattern
|
|
476
|
+
|
|
477
|
+
The recommended pattern for iOS is a singleton manager that handles initialization, login state, and provides a clean API for the rest of the app.
|
|
478
|
+
|
|
479
|
+
### Complete CometChatManager
|
|
480
|
+
|
|
481
|
+
**Important:** `CometChatException` does NOT conform to Swift's `Error` protocol. Use `CometChatException` directly in your callbacks, not `Result<T, Error>`.
|
|
482
|
+
|
|
483
|
+
```swift
|
|
484
|
+
import Foundation
|
|
485
|
+
import CometChatUIKitSwift
|
|
486
|
+
import CometChatSDK
|
|
487
|
+
|
|
488
|
+
final class CometChatManager {
|
|
489
|
+
|
|
490
|
+
// MARK: - Singleton
|
|
491
|
+
static let shared = CometChatManager()
|
|
492
|
+
|
|
493
|
+
// MARK: - State
|
|
494
|
+
private(set) var isInitialized = false
|
|
495
|
+
private(set) var currentUser: User?
|
|
496
|
+
|
|
497
|
+
// MARK: - Callbacks
|
|
498
|
+
var onLoginStateChanged: ((User?) -> Void)?
|
|
499
|
+
|
|
500
|
+
private init() {}
|
|
501
|
+
|
|
502
|
+
// MARK: - Initialization
|
|
503
|
+
func initialize(
|
|
504
|
+
appID: String,
|
|
505
|
+
authKey: String,
|
|
506
|
+
region: String,
|
|
507
|
+
completion: @escaping (Bool, CometChatException?) -> Void
|
|
508
|
+
) {
|
|
509
|
+
guard !isInitialized else {
|
|
510
|
+
completion(true, nil)
|
|
511
|
+
return
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
let uiKitSettings = UIKitSettings()
|
|
515
|
+
.set(appID: appID)
|
|
516
|
+
.set(authKey: authKey)
|
|
517
|
+
.set(region: region)
|
|
518
|
+
.subscribePresenceForAllUsers()
|
|
519
|
+
.build()
|
|
520
|
+
|
|
521
|
+
CometChatUIKit.init(uiKitSettings: uiKitSettings) { [weak self] result in
|
|
522
|
+
DispatchQueue.main.async {
|
|
523
|
+
switch result {
|
|
524
|
+
case .success(let success):
|
|
525
|
+
self?.isInitialized = success
|
|
526
|
+
self?.currentUser = CometChatUIKit.getLoggedInUser()
|
|
527
|
+
completion(success, nil)
|
|
528
|
+
case .failure(let error):
|
|
529
|
+
completion(false, error as? CometChatException)
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// MARK: - Login with UID (Development)
|
|
536
|
+
func login(uid: String, completion: @escaping (User?, CometChatException?) -> Void) {
|
|
537
|
+
guard isInitialized else {
|
|
538
|
+
print("CometChat not initialized")
|
|
539
|
+
completion(nil, nil)
|
|
540
|
+
return
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if let user = currentUser {
|
|
544
|
+
completion(user, nil)
|
|
545
|
+
return
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
CometChatUIKit.login(uid: uid) { [weak self] result in
|
|
549
|
+
DispatchQueue.main.async {
|
|
550
|
+
switch result {
|
|
551
|
+
case .success(let user):
|
|
552
|
+
self?.currentUser = user
|
|
553
|
+
self?.onLoginStateChanged?(user)
|
|
554
|
+
completion(user, nil)
|
|
555
|
+
case .onError(let error):
|
|
556
|
+
completion(nil, error)
|
|
557
|
+
@unknown default:
|
|
558
|
+
completion(nil, nil)
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// MARK: - Login with Auth Token (Production)
|
|
565
|
+
func loginWithToken(_ authToken: String, completion: @escaping (User?, CometChatException?) -> Void) {
|
|
566
|
+
guard isInitialized else {
|
|
567
|
+
print("CometChat not initialized")
|
|
568
|
+
completion(nil, nil)
|
|
569
|
+
return
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
CometChatUIKit.login(authToken: authToken) { [weak self] result in
|
|
573
|
+
DispatchQueue.main.async {
|
|
574
|
+
switch result {
|
|
575
|
+
case .success(let user):
|
|
576
|
+
self?.currentUser = user
|
|
577
|
+
self?.onLoginStateChanged?(user)
|
|
578
|
+
completion(user, nil)
|
|
579
|
+
case .onError(let error):
|
|
580
|
+
completion(nil, error)
|
|
581
|
+
@unknown default:
|
|
582
|
+
completion(nil, nil)
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// MARK: - Logout
|
|
589
|
+
func logout(completion: @escaping (Bool, CometChatException?) -> Void) {
|
|
590
|
+
guard let user = currentUser else {
|
|
591
|
+
completion(true, nil)
|
|
592
|
+
return
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
CometChatUIKit.logout(user: user) { [weak self] result in
|
|
596
|
+
DispatchQueue.main.async {
|
|
597
|
+
switch result {
|
|
598
|
+
case .success:
|
|
599
|
+
self?.currentUser = nil
|
|
600
|
+
self?.onLoginStateChanged?(nil)
|
|
601
|
+
completion(true, nil)
|
|
602
|
+
case .onError(let error):
|
|
603
|
+
completion(false, error)
|
|
604
|
+
@unknown default:
|
|
605
|
+
completion(false, nil)
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Usage Example
|
|
614
|
+
|
|
615
|
+
```swift
|
|
616
|
+
// Initialize
|
|
617
|
+
CometChatManager.shared.initialize(
|
|
618
|
+
appID: "YOUR_APP_ID",
|
|
619
|
+
authKey: "YOUR_AUTH_KEY",
|
|
620
|
+
region: "us"
|
|
621
|
+
) { success, error in
|
|
622
|
+
if success {
|
|
623
|
+
print("Initialized successfully")
|
|
624
|
+
} else if let error = error {
|
|
625
|
+
print("Init failed: \(error.errorDescription)")
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Login
|
|
630
|
+
CometChatManager.shared.login(uid: "cometchat-uid-1") { user, error in
|
|
631
|
+
if let user = user {
|
|
632
|
+
print("Logged in as: \(user.name ?? "")")
|
|
633
|
+
// Show chat UI
|
|
634
|
+
} else if let error = error {
|
|
635
|
+
print("Login failed: \(error.errorDescription)")
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Logout
|
|
640
|
+
CometChatManager.shared.logout { success, error in
|
|
641
|
+
if success {
|
|
642
|
+
print("Logged out")
|
|
643
|
+
} else if let error = error {
|
|
644
|
+
print("Logout failed: \(error.errorDescription)")
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
## 6. Theming
|
|
652
|
+
|
|
653
|
+
### Global Theme Configuration
|
|
654
|
+
|
|
655
|
+
CometChat iOS UI Kit uses `CometChatTheme` for styling. Configure it before showing any UI:
|
|
656
|
+
|
|
657
|
+
```swift
|
|
658
|
+
// Set primary color
|
|
659
|
+
CometChatTheme.primaryColor = UIColor.systemBlue
|
|
660
|
+
|
|
661
|
+
// Set background colors
|
|
662
|
+
CometChatTheme.backgroundColor01 = UIColor.systemBackground
|
|
663
|
+
CometChatTheme.backgroundColor02 = UIColor.secondarySystemBackground
|
|
664
|
+
|
|
665
|
+
// Set text colors
|
|
666
|
+
CometChatTheme.textColorPrimary = UIColor.label
|
|
667
|
+
CometChatTheme.textColorSecondary = UIColor.secondaryLabel
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
### Component-Level Styling
|
|
671
|
+
|
|
672
|
+
Each component has a static `style` property:
|
|
673
|
+
|
|
674
|
+
```swift
|
|
675
|
+
// Conversations list style
|
|
676
|
+
CometChatConversations.style.backgroundColor = .systemBackground
|
|
677
|
+
CometChatConversations.style.titleColor = .label
|
|
678
|
+
|
|
679
|
+
// Message list style
|
|
680
|
+
CometChatMessageList.style.backgroundColor = .systemBackground
|
|
681
|
+
|
|
682
|
+
// Avatar style — cornerRadius is a CGFloat on a CometChatCornerStyle,
|
|
683
|
+
// NOT a `.circle` enum case. Use a value larger than half the avatar
|
|
684
|
+
// dimension for a circular look.
|
|
685
|
+
CometChatAvatar.style.backgroundColor = .systemGray5
|
|
686
|
+
CometChatAvatar.style.cornerRadius = CometChatCornerStyle(cornerRadius: 100)
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### Dark Mode Support
|
|
690
|
+
|
|
691
|
+
CometChat automatically supports dark mode when using system colors:
|
|
692
|
+
|
|
693
|
+
```swift
|
|
694
|
+
CometChatTheme.primaryColor = UIColor { traitCollection in
|
|
695
|
+
traitCollection.userInterfaceStyle == .dark
|
|
696
|
+
? UIColor.systemBlue
|
|
697
|
+
: UIColor.blue
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
---
|
|
702
|
+
|
|
703
|
+
## 7. Localization
|
|
704
|
+
|
|
705
|
+
CometChat iOS UI Kit supports 20+ languages out of the box. The language is automatically detected from the device settings.
|
|
706
|
+
|
|
707
|
+
### Supported Languages
|
|
708
|
+
|
|
709
|
+
Arabic, Chinese (Simplified), Chinese (Traditional), Dutch, English, French, German, Hindi, Hungarian, Japanese, Korean, Lithuanian, Malay, Portuguese, Russian, Spanish, Swedish, Turkish
|
|
710
|
+
|
|
711
|
+
### Setting locale
|
|
712
|
+
|
|
713
|
+
`CometChatLocalize` is a `Bundle` subclass that swaps the kit's `.lproj` lookup at runtime. The public API is locale-only:
|
|
714
|
+
|
|
715
|
+
```swift
|
|
716
|
+
CometChatLocalize.set(locale: .english) // enum value
|
|
717
|
+
CometChatLocalize.set(locale: "fr") // raw string
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
There is no `CometChatLocalize.set(key:value:)` for ad-hoc key overrides — to customize specific strings, override them in your app's `Localizable.strings` file (the kit reads through the standard bundle lookup chain).
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
724
|
+
## 8. Anti-patterns
|
|
725
|
+
|
|
726
|
+
These are specific things NOT to do. Each one causes real bugs.
|
|
727
|
+
|
|
728
|
+
1. **Do NOT call `CometChatUIKit.init()` multiple times.** Init should happen once in AppDelegate or App init. Multiple init calls cause undefined behavior.
|
|
729
|
+
|
|
730
|
+
2. **Do NOT show CometChat UI before init completes.** Components assume the SDK is initialized. Showing UI before init finishes causes crashes.
|
|
731
|
+
|
|
732
|
+
3. **Do NOT hardcode Auth Key in production code.** The auth key is a secret. Use environment variables or xcconfig files. Use auth tokens in production.
|
|
733
|
+
|
|
734
|
+
4. **Do NOT ignore the completion handler.** Init and login are async. Always handle the completion to know when it's safe to proceed.
|
|
735
|
+
|
|
736
|
+
5. **Do NOT create multiple instances of CometChatManager.** Use the singleton pattern. Multiple managers cause state inconsistencies.
|
|
737
|
+
|
|
738
|
+
6. **Do NOT call login while another login is in progress.** Check `currentUser` first. Concurrent login calls cause errors.
|
|
739
|
+
|
|
740
|
+
7. **Do NOT forget to handle logout.** When your app's user logs out, call `CometChatManager.shared.logout()` to clear the CometChat session.
|
|
741
|
+
|
|
742
|
+
8. **Do NOT ignore memory management.** CometChat view controllers should be properly deallocated. Avoid retain cycles with closures.
|
|
743
|
+
|
|
744
|
+
9. **Do NOT block the main thread.** All CometChat callbacks are on the main thread. Don't do heavy work in callbacks.
|
|
745
|
+
|
|
746
|
+
10. **Do NOT invent component names.** CometChat exports specific components with specific names. Check the `cometchat-ios-components` skill before writing any code.
|
|
747
|
+
|
|
748
|
+
---
|
|
749
|
+
|
|
750
|
+
## 9. SDK Types Reference
|
|
751
|
+
|
|
752
|
+
Common types from `CometChatSDK`:
|
|
753
|
+
|
|
754
|
+
```swift
|
|
755
|
+
import CometChatSDK
|
|
756
|
+
|
|
757
|
+
// User — represents a chat user
|
|
758
|
+
let user: User
|
|
759
|
+
|
|
760
|
+
// Group — represents a chat group
|
|
761
|
+
let group: Group
|
|
762
|
+
|
|
763
|
+
// Conversation — wraps User or Group
|
|
764
|
+
let conversation: Conversation
|
|
765
|
+
|
|
766
|
+
// BaseMessage — base class for all messages
|
|
767
|
+
let message: BaseMessage
|
|
768
|
+
|
|
769
|
+
// TextMessage — a text message
|
|
770
|
+
let textMessage: TextMessage
|
|
771
|
+
|
|
772
|
+
// MediaMessage — image, video, audio, file
|
|
773
|
+
let mediaMessage: MediaMessage
|
|
774
|
+
|
|
775
|
+
// CustomMessage — custom data message
|
|
776
|
+
let customMessage: CustomMessage
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Getting entities
|
|
780
|
+
|
|
781
|
+
```swift
|
|
782
|
+
// Get a user by UID
|
|
783
|
+
CometChat.getUser(UID: "user-uid") { user in
|
|
784
|
+
print("User: \(user?.name ?? "")")
|
|
785
|
+
} onError: { error in
|
|
786
|
+
print("Error: \(error?.errorDescription ?? "")")
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Get a group by GUID
|
|
790
|
+
CometChat.getGroup(GUID: "group-guid") { group in
|
|
791
|
+
print("Group: \(group?.name ?? "")")
|
|
792
|
+
} onError: { error in
|
|
793
|
+
print("Error: \(error?.errorDescription ?? "")")
|
|
794
|
+
}
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
---
|
|
798
|
+
|
|
799
|
+
## 10. Package Dependencies
|
|
800
|
+
|
|
801
|
+
Every CometChat iOS integration requires:
|
|
802
|
+
|
|
803
|
+
```ruby
|
|
804
|
+
# Podfile
|
|
805
|
+
pod 'CometChatUIKitSwift', '~> 5.1'
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
This automatically includes:
|
|
809
|
+
- `CometChatSDK` — Core SDK with types and methods
|
|
810
|
+
- UI components and views
|
|
811
|
+
- Localization resources
|
|
812
|
+
- Asset bundles
|
|
813
|
+
|
|
814
|
+
### Optional: Calling SDK
|
|
815
|
+
|
|
816
|
+
For voice/video calls, add:
|
|
817
|
+
|
|
818
|
+
```ruby
|
|
819
|
+
pod 'CometChatCallsSDK', '~> 4.0'
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
The UI Kit automatically detects and enables calling features when the Calls SDK is present.
|