@cometchat/skills 3.0.0 → 4.0.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.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -17
  3. package/bin/install.js +389 -43
  4. package/package.json +19 -9
  5. package/skills/cometchat/SKILL.md +1066 -265
  6. package/skills/cometchat-android-v5/SKILL.md +120 -0
  7. package/skills/cometchat-android-v5-components/SKILL.md +430 -0
  8. package/skills/cometchat-android-v5-core/SKILL.md +468 -0
  9. package/skills/cometchat-android-v5-customization/SKILL.md +305 -0
  10. package/skills/cometchat-android-v5-extensions/SKILL.md +124 -0
  11. package/skills/cometchat-android-v5-features/SKILL.md +130 -0
  12. package/skills/cometchat-android-v5-placement/SKILL.md +276 -0
  13. package/skills/cometchat-android-v5-production/SKILL.md +94 -0
  14. package/skills/cometchat-android-v5-push/SKILL.md +620 -0
  15. package/skills/cometchat-android-v5-testing/SKILL.md +187 -0
  16. package/skills/cometchat-android-v5-theming/SKILL.md +166 -0
  17. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +73 -0
  18. package/skills/cometchat-android-v6/SKILL.md +107 -0
  19. package/skills/cometchat-android-v6-builder-settings/SKILL.md +145 -0
  20. package/skills/cometchat-android-v6-compose-components/SKILL.md +202 -0
  21. package/skills/cometchat-android-v6-compose-customization/SKILL.md +280 -0
  22. package/skills/cometchat-android-v6-compose-placement/SKILL.md +213 -0
  23. package/skills/cometchat-android-v6-compose-theming/SKILL.md +224 -0
  24. package/skills/cometchat-android-v6-core/SKILL.md +354 -0
  25. package/skills/cometchat-android-v6-events/SKILL.md +212 -0
  26. package/skills/cometchat-android-v6-extensions/SKILL.md +191 -0
  27. package/skills/cometchat-android-v6-features/SKILL.md +130 -0
  28. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +197 -0
  29. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +268 -0
  30. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +248 -0
  31. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +202 -0
  32. package/skills/cometchat-android-v6-production/SKILL.md +187 -0
  33. package/skills/cometchat-android-v6-push/SKILL.md +274 -0
  34. package/skills/cometchat-android-v6-testing/SKILL.md +279 -0
  35. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +249 -0
  36. package/skills/cometchat-angular-components/SKILL.md +706 -0
  37. package/skills/cometchat-angular-core/SKILL.md +444 -0
  38. package/skills/cometchat-angular-customization/SKILL.md +424 -0
  39. package/skills/cometchat-angular-features/SKILL.md +447 -0
  40. package/skills/cometchat-angular-patterns/SKILL.md +447 -0
  41. package/skills/cometchat-angular-placement/SKILL.md +685 -0
  42. package/skills/cometchat-angular-production/SKILL.md +415 -0
  43. package/skills/cometchat-angular-theming/SKILL.md +365 -0
  44. package/skills/cometchat-angular-troubleshooting/SKILL.md +329 -0
  45. package/skills/cometchat-astro-patterns/SKILL.md +3 -3
  46. package/skills/cometchat-components/SKILL.md +11 -0
  47. package/skills/cometchat-core/SKILL.md +11 -6
  48. package/skills/cometchat-customization/references/component-catalog.md +1 -1
  49. package/skills/cometchat-features/SKILL.md +176 -108
  50. package/skills/cometchat-flutter-v5/SKILL.md +167 -0
  51. package/skills/cometchat-flutter-v5-calls/SKILL.md +192 -0
  52. package/skills/cometchat-flutter-v5-conversations/SKILL.md +117 -0
  53. package/skills/cometchat-flutter-v5-core/SKILL.md +221 -0
  54. package/skills/cometchat-flutter-v5-customization/SKILL.md +227 -0
  55. package/skills/cometchat-flutter-v5-events/SKILL.md +155 -0
  56. package/skills/cometchat-flutter-v5-messages/SKILL.md +258 -0
  57. package/skills/cometchat-flutter-v5-production/SKILL.md +207 -0
  58. package/skills/cometchat-flutter-v5-push/SKILL.md +284 -0
  59. package/skills/cometchat-flutter-v5-theming/SKILL.md +160 -0
  60. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +129 -0
  61. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +151 -0
  62. package/skills/cometchat-flutter-v6/SKILL.md +445 -0
  63. package/skills/cometchat-flutter-v6-calls/SKILL.md +333 -0
  64. package/skills/cometchat-flutter-v6-components/SKILL.md +365 -0
  65. package/skills/cometchat-flutter-v6-conversations/SKILL.md +210 -0
  66. package/skills/cometchat-flutter-v6-core/SKILL.md +305 -0
  67. package/skills/cometchat-flutter-v6-customization/SKILL.md +666 -0
  68. package/skills/cometchat-flutter-v6-events/SKILL.md +216 -0
  69. package/skills/cometchat-flutter-v6-features/SKILL.md +406 -0
  70. package/skills/cometchat-flutter-v6-messages/SKILL.md +333 -0
  71. package/skills/cometchat-flutter-v6-migration/SKILL.md +381 -0
  72. package/skills/cometchat-flutter-v6-placement/SKILL.md +398 -0
  73. package/skills/cometchat-flutter-v6-production/SKILL.md +632 -0
  74. package/skills/cometchat-flutter-v6-theming/SKILL.md +260 -0
  75. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +726 -0
  76. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +216 -0
  77. package/skills/cometchat-ios/SKILL.md +323 -0
  78. package/skills/cometchat-ios-components/SKILL.md +651 -0
  79. package/skills/cometchat-ios-core/SKILL.md +822 -0
  80. package/skills/cometchat-ios-customization/SKILL.md +825 -0
  81. package/skills/cometchat-ios-features/SKILL.md +725 -0
  82. package/skills/cometchat-ios-placement/SKILL.md +750 -0
  83. package/skills/cometchat-ios-production/SKILL.md +730 -0
  84. package/skills/cometchat-ios-push/SKILL.md +582 -0
  85. package/skills/cometchat-ios-theming/SKILL.md +631 -0
  86. package/skills/cometchat-ios-troubleshooting/SKILL.md +983 -0
  87. package/skills/cometchat-native-bare-patterns/SKILL.md +470 -0
  88. package/skills/cometchat-native-components/SKILL.md +594 -0
  89. package/skills/cometchat-native-core/SKILL.md +407 -0
  90. package/skills/cometchat-native-customization/SKILL.md +594 -0
  91. package/skills/cometchat-native-expo-patterns/SKILL.md +485 -0
  92. package/skills/cometchat-native-features/SKILL.md +608 -0
  93. package/skills/cometchat-native-placement/SKILL.md +500 -0
  94. package/skills/cometchat-native-production/SKILL.md +694 -0
  95. package/skills/cometchat-native-push/SKILL.md +593 -0
  96. package/skills/cometchat-native-testing/SKILL.md +583 -0
  97. package/skills/cometchat-native-theming/SKILL.md +656 -0
  98. package/skills/cometchat-native-troubleshooting/SKILL.md +433 -0
  99. package/skills/cometchat-nextjs-patterns/SKILL.md +5 -5
  100. package/skills/cometchat-production/SKILL.md +60 -0
  101. package/skills/cometchat-react-router-patterns/SKILL.md +23 -21
@@ -0,0 +1,207 @@
1
+ ---
2
+ name: cometchat-flutter-v5-production
3
+ description: "Use when preparing a CometChat Flutter UIKit v5 app for production. Covers auth tokens, ProGuard, environment config, security hardening."
4
+ license: "MIT"
5
+ compatibility: "cometchat_chat_uikit ^5.2.14; cometchat_calls_uikit ^5.0.15"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.0.0"
10
+ tags: "cometchat flutter v5 production security auth tokens proguard environment"
11
+ ---
12
+
13
+ # CometChat Flutter UIKit v5 — Production
14
+
15
+ Hardening a CometChat Flutter app for production deployment.
16
+
17
+ ## Auth Tokens vs Auth Key
18
+
19
+ **Development:** `CometChatUIKit.login(uid)` uses `authKey` from `UIKitSettingsBuilder`. This is convenient but insecure — the authKey is embedded in the app binary.
20
+
21
+ **Production:** Use server-minted auth tokens via `CometChatUIKit.loginWithAuthToken(authToken)`:
22
+
23
+ ```dart
24
+ // 1. Your backend generates an auth token via CometChat REST API
25
+ // POST https://{appId}.api-{region}.cometchat.io/v3/users/{uid}/auth_tokens
26
+ // Header: apiKey: YOUR_API_KEY
27
+
28
+ // 2. Your Flutter app receives the token and logs in
29
+ CometChatUIKit.loginWithAuthToken(authToken,
30
+ onSuccess: (user) { ... },
31
+ onError: (e) { ... },
32
+ );
33
+ ```
34
+
35
+ This keeps the API key on your server, never in the client.
36
+
37
+ ## Environment Configuration
38
+
39
+ Store credentials outside source code:
40
+
41
+ ```dart
42
+ class AppCredentials {
43
+ static String _appId = '';
44
+ static String _authKey = '';
45
+ static String _region = '';
46
+
47
+ // Load from SharedPreferences, environment, or remote config
48
+ static String get appId => _appId.isEmpty
49
+ ? SharedPreferencesClass.getString('appId')
50
+ : _appId;
51
+
52
+ static Future<void> setAppId(String value) async {
53
+ await SharedPreferencesClass.setString('appId', value);
54
+ _appId = value;
55
+ }
56
+ }
57
+ ```
58
+
59
+ The master app supports QR code scanning to load credentials dynamically (`CometChatQRScreen`).
60
+
61
+ ## Android Build Requirements
62
+
63
+ ### gradle.properties
64
+
65
+ ```properties
66
+ android.useAndroidX=true
67
+ android.enableJetifier=true
68
+ ```
69
+
70
+ ### minSdk 26
71
+
72
+ ```groovy
73
+ // android/app/build.gradle
74
+ defaultConfig {
75
+ minSdk 26 // Required by cometchat_calls_sdk
76
+ }
77
+ ```
78
+
79
+ ### ProGuard / R8 Keep Rules
80
+
81
+ Create `android/app/proguard-rules.pro`:
82
+
83
+ ```
84
+ -keep class com.cometchat.** { *; }
85
+ -keep interface com.cometchat.** { *; }
86
+ -dontwarn com.cometchat.calls.**
87
+ ```
88
+
89
+ Reference in `build.gradle`:
90
+
91
+ ```groovy
92
+ buildTypes {
93
+ release {
94
+ minifyEnabled true
95
+ shrinkResources true
96
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Signing
102
+
103
+ ```groovy
104
+ signingConfigs {
105
+ release {
106
+ storeFile file('your_keystore.jks')
107
+ storePassword 'STORE_PASSWORD'
108
+ keyAlias 'KEY_ALIAS'
109
+ keyPassword 'KEY_PASSWORD'
110
+ }
111
+ }
112
+ ```
113
+
114
+ ## iOS Build Requirements
115
+
116
+ ### Info.plist Permissions
117
+
118
+ ```xml
119
+ <key>NSCameraUsageDescription</key>
120
+ <string>Camera access for video calls and photo sharing</string>
121
+ <key>NSMicrophoneUsageDescription</key>
122
+ <string>Microphone access for voice and video calls</string>
123
+ <key>NSPhotoLibraryUsageDescription</key>
124
+ <string>Photo library access for sharing images</string>
125
+ ```
126
+
127
+ ### Background Modes (for VoIP)
128
+
129
+ Enable in Xcode: Background Modes → Voice over IP, Remote notifications, Background fetch.
130
+
131
+ ### Podfile
132
+
133
+ Ensure minimum iOS deployment target matches CometChat requirements.
134
+
135
+ ## Firebase Setup
136
+
137
+ ```dart
138
+ // In main(), before runApp:
139
+ await Firebase.initializeApp(
140
+ options: DefaultFirebaseOptions.currentPlatform,
141
+ );
142
+ ```
143
+
144
+ ### Crashlytics
145
+
146
+ ```dart
147
+ FlutterError.onError = (errorDetails) {
148
+ FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
149
+ };
150
+ PlatformDispatcher.instance.onError = (error, stack) {
151
+ FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
152
+ return true;
153
+ };
154
+ ```
155
+
156
+ ## Push Notification Provider IDs
157
+
158
+ Configure provider IDs for FCM and APNs in the CometChat dashboard:
159
+
160
+ ```dart
161
+ static String get fcmProviderId => 'your-fcm-provider-id';
162
+ static String get apnProviderId => 'your-apn-provider-id';
163
+ ```
164
+
165
+ These must match what's configured in the CometChat dashboard under Notifications → Push Notifications.
166
+
167
+ ## Demo Meta Info
168
+
169
+ For internal tracking (optional):
170
+
171
+ ```dart
172
+ CometChat.setDemoMetaInfo(jsonObject: {
173
+ "name": "flutter-sample-app",
174
+ "type": "sample",
175
+ "version": "5.2.11",
176
+ "platform": "flutter",
177
+ });
178
+ ```
179
+
180
+ ## Logout Flow
181
+
182
+ ```dart
183
+ // 1. Unregister push tokens
184
+ PNRegistry.unregisterPNService();
185
+
186
+ // 2. Sign out from Firebase/Google (if applicable)
187
+ await FirebaseAuth.instance.signOut();
188
+ await GoogleSignIn().signOut();
189
+
190
+ // 3. Logout from CometChat
191
+ await CometChatUIKit.logout(
192
+ onSuccess: (_) { /* navigate to login */ },
193
+ onError: (e) { /* show error */ },
194
+ );
195
+ ```
196
+
197
+ ## Checklist — Production
198
+
199
+ - [ ] Auth tokens minted server-side, not authKey in client
200
+ - [ ] Credentials not hardcoded in source (use SharedPreferences or remote config)
201
+ - [ ] ProGuard rules added for release builds
202
+ - [ ] minSdk 26 set
203
+ - [ ] iOS permissions in Info.plist
204
+ - [ ] Firebase Crashlytics configured
205
+ - [ ] Push notification provider IDs match CometChat dashboard
206
+ - [ ] Logout unregisters push tokens before CometChat logout
207
+ - [ ] Signing config set for release builds
@@ -0,0 +1,284 @@
1
+ ---
2
+ name: cometchat-flutter-v5-push
3
+ description: "Use when implementing push notifications with CometChat Flutter UIKit v5. Covers FCM (Android), APNs (iOS), VoIP calls, token lifecycle, local notifications, and tap-to-navigate."
4
+ license: "MIT"
5
+ compatibility: "cometchat_chat_uikit ^5.2.14; cometchat_calls_uikit ^5.0.15; firebase_messaging; flutter_local_notifications; flutter_callkit_incoming"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.0.0"
10
+ tags: "cometchat flutter v5 push notifications fcm apns voip callkit firebase"
11
+ ---
12
+
13
+ # CometChat Flutter UIKit v5 — Push Notifications
14
+
15
+ Push notification setup for Android (FCM) and iOS (APNs + VoIP).
16
+
17
+ ## Dependencies
18
+
19
+ ```yaml
20
+ dependencies:
21
+ firebase_core: ^3.9.0
22
+ firebase_messaging: ^15.1.6
23
+ flutter_local_notifications: ^18.0.0
24
+ flutter_callkit_incoming: # for VoIP call notifications
25
+ app_badge_plus: ^1.2.6 # badge count
26
+ ```
27
+
28
+ ## Architecture Overview
29
+
30
+ ```
31
+ notifications/
32
+ ├── models/
33
+ │ ├── payload.dart # PayloadData model for parsing FCM data
34
+ │ ├── call_action.dart # CallAction enum (initiated, cancelled, unanswered)
35
+ │ ├── call_type.dart # CallType enum (audio, video)
36
+ │ └── notification_message_type.dart # Message type constants
37
+ ├── services/
38
+ │ ├── android_notification_service/
39
+ │ │ ├── firebase_services.dart # FCM init, listeners, token management
40
+ │ │ ├── local_notification_handler.dart # Local notification display + tap handling
41
+ │ │ ├── voip_notification_handler.dart # VoIP call display, accept, decline
42
+ │ │ └── notification_launch_handler.dart # Terminated state launch handling
43
+ │ ├── iOS_notification_service/
44
+ │ │ └── apns_services.dart # APNs connector, VoIP token, CallKit
45
+ │ └── cometchat_service/
46
+ │ └── cometchat_services.dart # PNRegistry (token registration/unregistration)
47
+ ```
48
+
49
+ ## Token Registration — `CometChatNotifications.registerPushToken`
50
+
51
+ The kit's only public push surface is `CometChatNotifications.registerPushToken(platform, {providerId, fcmToken, deviceToken, voipToken, onSuccess, onError})` (and `unregisterPushToken({onSuccess, onError})`). The sample app wraps this in an extension named `PNRegistry on CometChatService` (see `sample_app_push_notifications/lib/notifications/services/cometchat_service/cometchat_services.dart`) that picks the right provider ID + platform constant for FCM-Android / FCM-iOS / APNs / APNs-VoIP. **Copy that helper into your project, or call `CometChatNotifications.registerPushToken` directly** — `PNRegistry` is a sample-app extension, not importable from any cometchat package.
52
+
53
+ ```dart
54
+ // Direct kit API:
55
+ import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
56
+
57
+ await CometChatNotifications.registerPushToken(
58
+ PushPlatforms.FCM_FLUTTER_ANDROID, // platform — first positional arg
59
+ providerId: fcmProviderId, // dashboard FCM provider ID
60
+ fcmToken: token, // use fcmToken / deviceToken / voipToken depending on platform
61
+ onSuccess: (response) => debugPrint('registered: $response'),
62
+ onError: (e) => debugPrint('register failed: $e'),
63
+ );
64
+
65
+ // On logout:
66
+ await CometChatNotifications.unregisterPushToken(
67
+ onSuccess: (_) {},
68
+ onError: (e) => debugPrint('unregister failed: $e'),
69
+ );
70
+ ```
71
+
72
+ ```dart
73
+ // Or use the sample-app PNRegistry helper after copying it into your project:
74
+ PNRegistry.registerPNService(token, true, false); // (token, isFcm, isVoip)
75
+ PNRegistry.unregisterPNService();
76
+ ```
77
+
78
+ Platform mapping:
79
+ - FCM Android → `PushPlatforms.FCM_FLUTTER_ANDROID`
80
+ - FCM iOS → `PushPlatforms.FCM_FLUTTER_IOS`
81
+ - APNs Device → `PushPlatforms.APNS_FLUTTER_DEVICE`
82
+ - APNs VoIP → `PushPlatforms.APNS_FLUTTER_VOIP`
83
+
84
+ Provider IDs come from `AppCredentials.fcmProviderId` / `AppCredentials.apnProviderId` (your own constants — these are dashboard-configured values, not kit exports).
85
+
86
+ The remaining examples below assume you've copied `PNRegistry` from the sample app. If you call `CometChatNotifications.registerPushToken` directly, swap the call sites accordingly.
87
+
88
+ ## Android — FCM Setup
89
+
90
+ ### 1. Background handler (must be top-level function)
91
+
92
+ ```dart
93
+ @pragma('vm:entry-point')
94
+ Future<void> firebaseMessagingBackgroundHandler(RemoteMessage rMessage) async {
95
+ LocalNotificationService.showNotification(rMessage.data, rMessage, "", false);
96
+ await VoipNotificationHandler.displayIncomingCall(rMessage);
97
+ }
98
+ ```
99
+
100
+ ### 2. Initialize in dashboard/home screen
101
+
102
+ ```dart
103
+ class FirebaseService {
104
+ Future<void> init(BuildContext context) async {
105
+ _firebaseMessaging = FirebaseMessaging.instance;
106
+ await requestPermissions();
107
+ await initListeners(context);
108
+
109
+ String? token = await _firebaseMessaging.getToken();
110
+ if (token != null) {
111
+ PNRegistry.registerPNService(token, true, false);
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### 3. Listener setup
118
+
119
+ ```dart
120
+ // Background messages
121
+ FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
122
+
123
+ // Token refresh
124
+ _firebaseMessaging.onTokenRefresh.listen((token) {
125
+ PNRegistry.registerPNService(token, true, false);
126
+ });
127
+
128
+ // Foreground messages
129
+ FirebaseMessaging.onMessage.listen((message) {
130
+ LocalNotificationService.showNotification(message.data, message, conversationId, isAgentic);
131
+ });
132
+
133
+ // Tap from background
134
+ FirebaseMessaging.onMessageOpenedApp.listen((message) {
135
+ openNotification(context, message, conversationId);
136
+ });
137
+
138
+ // Tap from terminated state
139
+ FirebaseMessaging.instance.getInitialMessage().then((message) {
140
+ if (message != null) openNotification(context, message, conversationId);
141
+ });
142
+ ```
143
+
144
+ ## iOS — APNs Setup
145
+
146
+ ```dart
147
+ final _connector = ApnsPushConnector();
148
+ _connector.shouldPresent = (x) => Future.value(false);
149
+
150
+ _connector.configure(
151
+ onLaunch: (message) async { openNotification(message, context, ""); },
152
+ onResume: (message) async { openNotification(message, context, conversationId); },
153
+ onMessage: (message) async { _showNotification(message.data, message, conversationId, isAgentic); },
154
+ );
155
+
156
+ _connector.requestNotificationPermissions();
157
+
158
+ // APNs device token
159
+ _connector.token.addListener(() {
160
+ PNRegistry.registerPNService(_connector.token.value!, false, false);
161
+ });
162
+
163
+ // VoIP token
164
+ FlutterCallkitIncoming.getDevicePushTokenVoIP().then((voipToken) {
165
+ PNRegistry.registerPNService(voipToken, false, true);
166
+ });
167
+ ```
168
+
169
+ ## VoIP Call Notifications
170
+
171
+ ### Display incoming call (both platforms)
172
+
173
+ ```dart
174
+ static Future<void> displayIncomingCall(RemoteMessage rMessage) async {
175
+ PayloadData callPayload = PayloadData.fromJson(rMessage.data);
176
+ if (callPayload.type == 'call' && callPayload.callAction == CallAction.initiated) {
177
+ CallKitParams params = CallKitParams(
178
+ id: callPayload.sessionId,
179
+ nameCaller: callPayload.senderName,
180
+ type: (callPayload.callType == CallType.audio) ? 0 : 1,
181
+ duration: 45000,
182
+ );
183
+ await FlutterCallkitIncoming.showCallkitIncoming(params);
184
+ }
185
+ }
186
+ ```
187
+
188
+ ### Accept/Decline via CallKit events
189
+
190
+ ```dart
191
+ FlutterCallkitIncoming.onEvent.listen((CallEvent? callEvent) {
192
+ switch (callEvent?.event) {
193
+ case Event.actionCallAccept:
194
+ VoipNotificationHandler.acceptVoipCall(callEvent, context);
195
+ break;
196
+ case Event.actionCallDecline:
197
+ VoipNotificationHandler.declineVoipCall(callEvent);
198
+ break;
199
+ case Event.actionCallTimeout:
200
+ case Event.actionCallEnded:
201
+ VoipNotificationHandler.endCall(sessionId: callEvent?.body['id']);
202
+ break;
203
+ }
204
+ });
205
+ ```
206
+
207
+ ## Local Notification Display
208
+
209
+ Uses `flutter_local_notifications` with inbox-style grouping per conversation:
210
+
211
+ ```dart
212
+ // Skip if user is viewing the same conversation
213
+ if (conversationId == notifConversationId) return;
214
+
215
+ // Skip call-type notifications (handled by CallKit)
216
+ if (data["type"] == "call") return;
217
+
218
+ // Show with stable ID per conversation (replaces previous)
219
+ final notificationId = conversationId.hashCode;
220
+ await flutterLocalNotificationsPlugin.show(notificationId, title, body, details, payload: jsonPayload);
221
+ ```
222
+
223
+ ## Tap-to-Navigate
224
+
225
+ ```dart
226
+ static void handleNotificationTap(NotificationResponse? response) async {
227
+ if (response?.payload != null) {
228
+ final body = jsonDecode(response!.payload!);
229
+ NotificationDataModel model = NotificationDataModel.fromJson(body);
230
+
231
+ User? user; Group? group;
232
+ if (model.receiverType == "user") {
233
+ user = await CometChat.getUser(model.sender);
234
+ } else {
235
+ group = await CometChat.getGroup(model.receiver);
236
+ }
237
+
238
+ if (model.type == "chat" && (user != null || group != null)) {
239
+ Navigator.of(CallNavigationContext.navigatorKey.currentContext!).push(
240
+ MaterialPageRoute(builder: (_) => MessagesSample(user: user, group: group)),
241
+ );
242
+ }
243
+ }
244
+ }
245
+ ```
246
+
247
+ ## Terminated State Handling
248
+
249
+ ```dart
250
+ // In main()
251
+ final launchDetails = await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
252
+ if (launchDetails?.didNotificationLaunchApp == true) {
253
+ NotificationLaunchHandler.pendingNotificationResponse = launchDetails!.notificationResponse;
254
+ }
255
+
256
+ // In dashboard initState()
257
+ Future.delayed(Duration(milliseconds: 300), () {
258
+ final response = NotificationLaunchHandler.pendingNotificationResponse;
259
+ if (response != null) {
260
+ NotificationLaunchHandler.pendingNotificationResponse = null;
261
+ LocalNotificationService.handleNotificationTap(response, isTerminatedState: true);
262
+ }
263
+ });
264
+ ```
265
+
266
+ ## Logout — Unregister Token
267
+
268
+ ```dart
269
+ PNRegistry.unregisterPNService();
270
+ // Then: CometChatUIKit.logout(...)
271
+ ```
272
+
273
+ ## Checklist — Push Notifications
274
+
275
+ - [ ] Firebase initialized before CometChat init
276
+ - [ ] FCM token registered via `PNRegistry.registerPNService(token, true, false)`
277
+ - [ ] APNs device + VoIP tokens registered on iOS
278
+ - [ ] Background handler is top-level `@pragma('vm:entry-point')` function
279
+ - [ ] Token refresh listener re-registers token
280
+ - [ ] Local notifications skip current active conversation
281
+ - [ ] Call notifications handled via `FlutterCallkitIncoming`, not local notifications
282
+ - [ ] Tap-to-navigate uses `CallNavigationContext.navigatorKey.currentContext`
283
+ - [ ] Tokens unregistered on logout via `PNRegistry.unregisterPNService()`
284
+ - [ ] Terminated state launch handled via `NotificationLaunchHandler`
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: cometchat-flutter-v5-theming
3
+ description: "Use when customizing the visual appearance of CometChat Flutter UIKit v5 components. Triggers on CometChatThemeHelper, CometChatColorPalette, CometChatSpacing, CometChatTypography, Style classes, merge()."
4
+ license: "MIT"
5
+ compatibility: "cometchat_uikit_shared ^5.2.3; flutter >=2.5.0"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.0.0"
10
+ tags: "cometchat flutter v5 theme colors typography spacing dark-mode styling"
11
+ ---
12
+
13
+ # CometChat Flutter UIKit v5 — Theming & Styling
14
+
15
+ How to customize the visual appearance of all CometChat v5 components.
16
+
17
+ ## Theme System Architecture
18
+
19
+ Three layers, resolved via Flutter's `ThemeExtension` system:
20
+
21
+ 1. `CometChatColorPalette` — colors (primary, neutral, alert, background, text, icon, button, border)
22
+ 2. `CometChatSpacing` — spacing, padding, margin, and radius tokens
23
+ 3. `CometChatTypography` — text styles (heading1-4, body, caption1-2, button, link, title)
24
+
25
+ Access via static helpers:
26
+ ```dart
27
+ final colors = CometChatThemeHelper.getColorPalette(context);
28
+ final spacing = CometChatThemeHelper.getSpacing(context);
29
+ final typography = CometChatThemeHelper.getTypography(context);
30
+ ```
31
+
32
+ **Important:** `getColorPalette()` creates a new object every call, resolving each token via `Theme.of(context)`. Cache in `didChangeDependencies()`, never call in `build()`.
33
+
34
+ ## Applying a Custom Theme
35
+
36
+ Register `CometChatColorPalette` as a `ThemeExtension` on your `ThemeData`:
37
+
38
+ ```dart
39
+ // ✅ CORRECT
40
+ MaterialApp(
41
+ theme: ThemeData(
42
+ extensions: [
43
+ CometChatColorPalette(
44
+ primary: const Color(0xFF6852D6),
45
+ textPrimary: const Color(0xFF141414),
46
+ textSecondary: const Color(0xFF727272),
47
+ ),
48
+ ],
49
+ ),
50
+ darkTheme: ThemeData(
51
+ extensions: [
52
+ CometChatColorPalette(
53
+ primary: const Color(0xFF604CC3),
54
+ textPrimary: const Color(0xFFFFFFFF),
55
+ textSecondary: const Color(0xFFA0A0A0),
56
+ ),
57
+ ],
58
+ ),
59
+ )
60
+ ```
61
+
62
+ ## Dark Mode
63
+
64
+ ```dart
65
+ CometChatThemeMode.mode = ThemeMode.dark; // Force dark
66
+ CometChatThemeMode.mode = ThemeMode.system; // Follow system
67
+ ```
68
+
69
+ ## Commonly Used Color Tokens
70
+
71
+ | Token | Description | Light Default | Dark Default |
72
+ |-------|-------------|---------------|--------------|
73
+ | `primary` | Brand color | `#6852D6` | `#604CC3` |
74
+ | `background1`–`4` | Surface backgrounds | neutral50→neutral300 | neutral50→neutral300 |
75
+ | `textPrimary` | Main text | neutral900 | neutral900 |
76
+ | `textSecondary` | Secondary text | neutral600 | neutral600 |
77
+ | `borderLight` | Subtle borders | neutral200 | neutral200 |
78
+ | `iconPrimary` | Main icons | neutral900 | neutral900 |
79
+ | `iconSecondary` | Secondary icons | neutral500 | neutral500 |
80
+ | `iconHighlight` | Highlighted icons | primary | primary |
81
+ | `error` | Error states | `#F44649` | `#C73C3E` |
82
+ | `white` / `black` | Fixed (NOT brightness-aware) | `Colors.white` / `Colors.black` | Same |
83
+ | `transparent` | Transparent | `Colors.transparent` | Same |
84
+ | `neutral600` | Used for date styles | — | — |
85
+
86
+ Extended primary shades (`extendedPrimary50`–`900`) are auto-generated from `primary`. Override individually if needed.
87
+
88
+ ## Commonly Used Spacing Tokens
89
+
90
+ | Token | Default |
91
+ |-------|---------|
92
+ | `padding` / `spacing` / `radius` | 2 |
93
+ | `padding1` / `spacing1` / `radius1` | 4 |
94
+ | `padding2` / `spacing2` / `radius2` | 8 |
95
+ | `padding3` / `spacing3` / `radius3` | 12 |
96
+ | `padding4` / `spacing4` / `radius4` | 16 |
97
+ | `padding5` / `spacing5` / `radius5` | 20 |
98
+ | `padding6` / `spacing6` | 24 |
99
+ | `radiusMax` / `spacingMax` | 1000 |
100
+
101
+ ## Typography Tokens
102
+
103
+ `CometChatTypography` provides: `heading1`–`heading4`, `body`, `caption1`, `caption2`, `button`, `link`, `title`.
104
+
105
+ Each has `.bold`, `.medium`, `.regular` variants:
106
+ ```dart
107
+ typography.body?.regular?.fontSize
108
+ typography.heading2?.bold?.fontWeight
109
+ typography.caption1?.regular?.fontFamily
110
+ ```
111
+
112
+ ## Theme Caching Pattern (from package source)
113
+
114
+ All UIKit components cache theme unconditionally in `didChangeDependencies()`:
115
+
116
+ ```dart
117
+ // ✅ CORRECT — matches actual package pattern
118
+ @override
119
+ void didChangeDependencies() {
120
+ super.didChangeDependencies();
121
+ colorPalette = CometChatThemeHelper.getColorPalette(context);
122
+ spacing = CometChatThemeHelper.getSpacing(context);
123
+ typography = CometChatThemeHelper.getTypography(context);
124
+ }
125
+ ```
126
+
127
+ Do NOT use a `_themeInitialized` flag — it prevents theme updates on system theme changes.
128
+
129
+ ## Component Style Classes — merge() Pattern
130
+
131
+ Every component has a `CometChat{Component}Style` extending `ThemeExtension`. Resolved internally:
132
+
133
+ ```dart
134
+ // Inside component's didChangeDependencies():
135
+ style = CometChatThemeHelper.getTheme<CometChatConversationsStyle>(
136
+ context: context,
137
+ defaultTheme: CometChatConversationsStyle.of,
138
+ ).merge(widget.conversationsStyle);
139
+ ```
140
+
141
+ Pass overrides via constructor:
142
+ ```dart
143
+ CometChatConversations(
144
+ conversationsStyle: CometChatConversationsStyle(
145
+ backgroundColor: Colors.black,
146
+ ),
147
+ )
148
+ ```
149
+
150
+ ## Gotchas
151
+
152
+ - `colorPalette.white` / `black` / `transparent` are NOT brightness-aware — use `neutral50` for brightness-aware white
153
+ - Extended primary shades auto-generated from `primary` by blending with white (light) or black (dark)
154
+
155
+ ## Checklist — Theming
156
+
157
+ - [ ] Colors from `CometChatThemeHelper.getColorPalette(context)`, never hardcoded
158
+ - [ ] Theme cached in `didChangeDependencies()`, not `build()`
159
+ - [ ] Custom theme registered as `ThemeExtension` on both `theme` and `darkTheme`
160
+ - [ ] Component styles passed via constructor props