@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,666 @@
1
+ ---
2
+ name: cometchat-flutter-v6-customization
3
+ description: >
4
+ Customize CometChat Flutter UIKit v6 beyond defaults — four tiers: props/view slots,
5
+ request builders, text formatters + message templates, and BubbleFactory/DataSource.
6
+ Use when the user wants custom bubbles, custom headers, custom list items, custom
7
+ message actions, or custom message types.
8
+ license: "MIT"
9
+ compatibility: "cometchat_chat_uikit ^6.0.0-beta2"
10
+ allowed-tools: "executeBash, readFile, readCode, fileSearch, listDirectory, grepSearch"
11
+ metadata:
12
+ author: "CometChat"
13
+ version: "3.0.0"
14
+ tags: "cometchat flutter customization bubbles templates formatters datasource"
15
+ ---
16
+
17
+ # CometChat Flutter UIKit v6 — Customization Guide
18
+
19
+ Four tiers of customization, from lightest to deepest.
20
+
21
+ ## 1. Four-Tier Customization Model
22
+
23
+ | Tier | Mechanism | Scope | When to Use |
24
+ |------|-----------|-------|-------------|
25
+ | 1 | Props & View Slots | Per-component UI overrides | Custom list items, subtitles, trailing widgets, headers |
26
+ | 2 | Request Builders | Data filtering & pagination | Filter conversations, users, groups, messages, group members |
27
+ | 3 | Text Formatters & Message Templates | Message rendering & actions | Custom text styling, custom long-press options, custom bubble slots |
28
+ | 4 | BubbleFactory & DataSource | New message types | Location bubbles, poll bubbles, any custom `category_type` |
29
+
30
+ Start at Tier 1. Move deeper only when the lighter tier can't solve the problem.
31
+
32
+ ## 2. Tier 1: Props & View Slots
33
+
34
+ Every list-based component exposes view slot callbacks that let you replace individual parts of each list item without rebuilding the entire widget.
35
+
36
+ ### CometChatConversations
37
+
38
+ ```dart
39
+ CometChatConversations(
40
+ // Replace the entire list item
41
+ listItemView: (Conversation conversation) => MyCustomConversationTile(conversation),
42
+
43
+ // Replace individual slots
44
+ subtitleView: (BuildContext context, Conversation conversation) =>
45
+ Text(conversation.lastMessage?.text ?? ''),
46
+ trailingView: (Conversation conversation) =>
47
+ Icon(Icons.chevron_right),
48
+ leadingView: (BuildContext context, Conversation conversation) =>
49
+ CircleAvatar(child: Text(conversation.conversationWith?.name?[0] ?? '')),
50
+ titleView: (BuildContext context, Conversation conversation) =>
51
+ Text(conversation.conversationWith?.name ?? '', style: TextStyle(fontWeight: FontWeight.bold)),
52
+
53
+ // State views
54
+ emptyStateView: (context) => Center(child: Text('No conversations yet')),
55
+ errorStateView: (context) => Center(child: Text('Something went wrong')),
56
+ loadingStateView: (context) => Center(child: CircularProgressIndicator()),
57
+ )
58
+ ```
59
+
60
+ ### CometChatUsers
61
+
62
+ ```dart
63
+ CometChatUsers(
64
+ listItemView: (User user) => MyCustomUserTile(user),
65
+ subtitleView: (BuildContext context, User user) => Text(user.status ?? ''),
66
+ trailingView: (BuildContext context, User user) => Icon(Icons.message),
67
+ leadingView: (BuildContext context, User user) => CometChatAvatar(name: user.name),
68
+ titleView: (BuildContext context, User user) => Text(user.name),
69
+ )
70
+ ```
71
+
72
+ ### CometChatGroups
73
+
74
+ ```dart
75
+ CometChatGroups(
76
+ listItemView: (Group group) => MyCustomGroupTile(group),
77
+ subtitleView: (BuildContext context, Group group) =>
78
+ Text('${group.membersCount} members'),
79
+ trailingView: (BuildContext context, Group group) => Icon(Icons.arrow_forward),
80
+ leadingView: (BuildContext context, Group group) => CometChatAvatar(name: group.name),
81
+ titleView: (BuildContext context, Group group) => Text(group.name),
82
+ )
83
+ ```
84
+
85
+ ### CometChatMessageHeader
86
+
87
+ ```dart
88
+ CometChatMessageHeader(
89
+ user: user,
90
+ group: group,
91
+ subtitleView: (Group? group, User? user, BuildContext context) =>
92
+ Text('Custom subtitle'),
93
+ trailingView: (User? user, Group? group, BuildContext context) => [
94
+ IconButton(icon: Icon(Icons.search), onPressed: () {}),
95
+ IconButton(icon: Icon(Icons.info_outline), onPressed: () {}),
96
+ ],
97
+ listItemView: (Group? group, User? user, BuildContext context) =>
98
+ MyCustomHeaderWidget(user: user, group: group),
99
+ titleView: null, // use default
100
+ leadingStateView: null, // use default
101
+ )
102
+ ```
103
+
104
+ ### CometChatMessageList
105
+
106
+ ```dart
107
+ CometChatMessageList(
108
+ user: user,
109
+ group: group,
110
+ headerView: (context, state) => MyCustomListHeader(),
111
+ footerView: (context, state) => MyCustomListFooter(),
112
+ emptyStateView: (context) => Center(child: Text('Start a conversation')),
113
+ emptyChatGreetingView: (context) => WelcomeWidget(),
114
+ loadingStateView: (context) => ShimmerList(),
115
+ errorStateView: (context) => RetryWidget(),
116
+ )
117
+ ```
118
+
119
+ ### CometChatMessageComposer
120
+
121
+ ```dart
122
+ CometChatMessageComposer(
123
+ user: user,
124
+ group: group,
125
+ headerView: (context, state) => ReplyPreviewBanner(),
126
+ footerView: (context, state) => SuggestedActionsBar(),
127
+ auxiliaryButtonView: (context, user, group, composerState) =>
128
+ IconButton(icon: Icon(Icons.gif), onPressed: () {}),
129
+ secondaryButtonView: (context, user, group, composerState) =>
130
+ IconButton(icon: Icon(Icons.attach_file), onPressed: () {}),
131
+ sendButtonView: Icon(Icons.send, color: Colors.blue),
132
+ )
133
+ ```
134
+
135
+ ## 3. Tier 2: Request Builders
136
+
137
+ Override the SDK request builder to control what data is fetched.
138
+
139
+ ### ConversationsRequestBuilder
140
+
141
+ ```dart
142
+ CometChatConversations(
143
+ conversationsRequestBuilder: ConversationsRequestBuilder()
144
+ ..limit = 30
145
+ ..conversationType = ConversationType.user // only 1-on-1 chats
146
+ ..withTags = true
147
+ ..tags = ['vip'],
148
+ )
149
+ ```
150
+
151
+ ### MessagesRequestBuilder
152
+
153
+ ```dart
154
+ CometChatMessageList(
155
+ user: user,
156
+ messagesRequestBuilder: MessagesRequestBuilder()
157
+ ..uid = user.uid
158
+ ..limit = 50
159
+ ..hideDeletedMessages = true
160
+ ..searchKeyword = 'invoice'
161
+ ..categories = [MessageCategoryConstants.message]
162
+ ..types = [MessageTypeConstants.text, MessageTypeConstants.image],
163
+ )
164
+ ```
165
+
166
+ ### UsersRequestBuilder
167
+
168
+ ```dart
169
+ CometChatUsers(
170
+ usersRequestBuilder: UsersRequestBuilder()
171
+ ..limit = 30
172
+ ..friendsOnly = true
173
+ ..searchKeyword = 'john'
174
+ ..roles = ['admin', 'moderator'],
175
+ )
176
+ ```
177
+
178
+ ### GroupsRequestBuilder
179
+
180
+ ```dart
181
+ CometChatGroups(
182
+ groupsRequestBuilder: GroupsRequestBuilder()
183
+ ..limit = 30
184
+ ..joinedOnly = true
185
+ ..searchKeyword = 'team'
186
+ ..withTags = true
187
+ ..tags = ['project-alpha'],
188
+ )
189
+ ```
190
+
191
+ ### GroupMembersRequestBuilder
192
+
193
+ ```dart
194
+ CometChatGroupMembers(
195
+ group: group,
196
+ groupMembersRequestBuilder: GroupMembersRequestBuilder(group.guid)
197
+ ..limit = 30
198
+ ..scopes = [GroupMemberScope.admin, GroupMemberScope.moderator],
199
+ )
200
+ ```
201
+
202
+ ## 4. Tier 3: Text Formatters & Message Templates
203
+
204
+ ### Text Formatters
205
+
206
+ `CometChatTextFormatter` is the abstract base class. Subclass it to create custom text styling in both the message list and the composer.
207
+
208
+ Built-in formatters:
209
+
210
+ | Formatter | Purpose |
211
+ |-----------|---------|
212
+ | `CometChatMentionsFormatter` | @mention users with suggestion list |
213
+ | `MarkdownTextFormatter` | Bold, italic, strikethrough, code, links, lists |
214
+ | `CometChatUrlFormatter` | Clickable URLs |
215
+ | `CometChatPhoneNumberFormatter` | Clickable phone numbers |
216
+ | `CometChatEmailFormatter` | Clickable email addresses |
217
+
218
+ Key properties on `CometChatTextFormatter`:
219
+
220
+ ```dart
221
+ abstract class CometChatTextFormatter implements Formatter {
222
+ String? trackingCharacter; // e.g. '@' for mentions
223
+ RegExp? pattern; // regex to match in text
224
+ Function(String?)? onSearch; // called when tracking character typed
225
+ bool? showLoadingIndicator;
226
+ BaseMessage? message;
227
+ User? user;
228
+ Group? group;
229
+ StreamSink<List<SuggestionListItem>>? suggestionListEventSink;
230
+
231
+ void init();
232
+ void handlePreMessageSend(BuildContext context, BaseMessage baseMessage);
233
+ void onScrollToBottom(TextEditingController textEditingController);
234
+ void onChange(TextEditingController textEditingController, String previousText);
235
+
236
+ List<AttributedText> buildInputFieldText({...});
237
+ List<AttributedText> getAttributedText(String text, BuildContext context, BubbleAlignment? alignment, {...});
238
+ TextStyle getMessageBubbleTextStyle(BuildContext context, BubbleAlignment? alignment, {bool forConversation = false});
239
+ TextStyle getMessageInputTextStyle(BuildContext context);
240
+ }
241
+ ```
242
+
243
+ Pass the same formatters to both list and composer:
244
+
245
+ ```dart
246
+ final formatters = [
247
+ CometChatMentionsFormatter(user: user, group: group),
248
+ MarkdownTextFormatter(),
249
+ CometChatUrlFormatter(),
250
+ CometChatPhoneNumberFormatter(),
251
+ CometChatEmailFormatter(),
252
+ ];
253
+
254
+ CometChatMessageList(user: user, textFormatters: formatters)
255
+ CometChatMessageComposer(user: user, textFormatters: formatters)
256
+ ```
257
+
258
+ ### Message Templates
259
+
260
+ `CometChatMessageTemplate` controls how a message type renders in the bubble and what long-press options appear.
261
+
262
+ ```dart
263
+ class CometChatMessageTemplate {
264
+ CometChatMessageTemplate({
265
+ required this.type, // e.g. 'text', 'image', or 'location'
266
+ required this.category, // e.g. 'message' or 'custom'
267
+ this.bubbleView, // replaces the ENTIRE bubble
268
+ this.headerView, // top of bubble (sender name area)
269
+ this.contentView, // main content area
270
+ this.footerView, // below statusInfoView
271
+ this.bottomView, // below contentView
272
+ this.statusInfoView, // receipts/time area
273
+ this.threadView, // thread reply indicator
274
+ this.replyView, // quoted reply preview
275
+ this.options, // long-press menu options
276
+ });
277
+ }
278
+ ```
279
+
280
+ Override templates on `CometChatMessageList`:
281
+
282
+ ```dart
283
+ CometChatMessageList(
284
+ user: user,
285
+ // Replace all templates
286
+ templates: [
287
+ CometChatMessageTemplate(
288
+ type: MessageTypeConstants.text,
289
+ category: MessageCategoryConstants.message,
290
+ contentView: (message, context, alignment, {additionalConfigurations}) =>
291
+ MyCustomTextContent(message: message),
292
+ options: (loggedInUser, message, context, group, additionalConfigurations) => [
293
+ CometChatMessageOption(
294
+ id: 'bookmark',
295
+ title: 'Bookmark',
296
+ icon: Icon(Icons.bookmark_border, size: 24),
297
+ onItemClick: (message, state) {
298
+ // handle bookmark
299
+ },
300
+ ),
301
+ ],
302
+ ),
303
+ ],
304
+ // Or add templates alongside defaults
305
+ addTemplate: [
306
+ CometChatMessageTemplate(
307
+ type: 'location',
308
+ category: 'custom',
309
+ contentView: (message, context, alignment, {additionalConfigurations}) =>
310
+ LocationBubbleContent(message: message as CustomMessage),
311
+ ),
312
+ ],
313
+ )
314
+ ```
315
+
316
+ `CometChatMessageOption` model:
317
+
318
+ ```dart
319
+ CometChatMessageOption(
320
+ id: 'pin', // unique identifier
321
+ title: 'Pin Message', // display text
322
+ icon: Icon(Icons.push_pin), // leading icon
323
+ onItemClick: (BaseMessage message, CometChatMessageListControllerProtocol state) {
324
+ // your action
325
+ },
326
+ messageOptionSheetStyle: CometChatMessageOptionSheetStyle(...),
327
+ )
328
+ ```
329
+
330
+ ## 5. Tier 4: BubbleFactory & DataSource
331
+
332
+ ### BubbleFactory
333
+
334
+ The deepest customization for rendering message content. Each factory handles one `category_type` key.
335
+
336
+ ```dart
337
+ /// Abstract factory — one per message type.
338
+ abstract class BubbleFactory<T extends BaseMessage> {
339
+ Widget build(
340
+ BuildContext context,
341
+ T message,
342
+ BubbleAlignment alignment, {
343
+ CometChatColorPalette? colorPalette,
344
+ CometChatTypography? typography,
345
+ CometChatSpacing? spacing,
346
+ });
347
+
348
+ /// Returns "category_type" key, or "deleted" for deleted messages.
349
+ static String getFactoryKey(BaseMessage message);
350
+
351
+ /// Creates a key from category + type strings.
352
+ static String createKey(String category, String type) => '${category}_$type';
353
+ }
354
+ ```
355
+
356
+ ### DefaultBubbleFactories
357
+
358
+ The built-in registry:
359
+
360
+ ```dart
361
+ class DefaultBubbleFactories {
362
+ static Map<String, BubbleFactory> getDefaults({
363
+ List<CometChatTextFormatter>? textFormatters,
364
+ CometChatTextBubbleStyle? incomingTextStyle,
365
+ CometChatTextBubbleStyle? outgoingTextStyle,
366
+ CometChatImageBubbleStyle? imageStyle,
367
+ CometChatVideoBubbleStyle? videoStyle,
368
+ CometChatAudioBubbleStyle? audioStyle,
369
+ CometChatFileBubbleStyle? fileStyle,
370
+ });
371
+ }
372
+ ```
373
+
374
+ Default keys registered:
375
+ - `message_text` → `TextBubbleFactory`
376
+ - `message_image` → `ImageBubbleFactory`
377
+ - `message_video` → `VideoBubbleFactory`
378
+ - `message_audio` → `AudioBubbleFactory`
379
+ - `message_file` → `FileBubbleFactory`
380
+ - `deleted` → `DeletedBubbleFactory`
381
+
382
+ ### Creating a Custom BubbleFactory
383
+
384
+ Example: a location message bubble.
385
+
386
+ ```dart
387
+ class LocationBubbleFactory extends BubbleFactory<CustomMessage> {
388
+ @override
389
+ Widget build(
390
+ BuildContext context,
391
+ CustomMessage message,
392
+ BubbleAlignment alignment, {
393
+ CometChatColorPalette? colorPalette,
394
+ CometChatTypography? typography,
395
+ CometChatSpacing? spacing,
396
+ }) {
397
+ final data = message.customData;
398
+ final lat = data?['latitude'] as double? ?? 0;
399
+ final lng = data?['longitude'] as double? ?? 0;
400
+
401
+ return GestureDetector(
402
+ onTap: () => _openMap(lat, lng),
403
+ child: Column(
404
+ mainAxisSize: MainAxisSize.min,
405
+ children: [
406
+ Image.network(
407
+ 'https://maps.googleapis.com/maps/api/staticmap?center=$lat,$lng&zoom=15&size=300x200&key=YOUR_KEY',
408
+ width: 240,
409
+ height: 160,
410
+ fit: BoxFit.cover,
411
+ ),
412
+ Padding(
413
+ padding: EdgeInsets.all(spacing?.padding2 ?? 8),
414
+ child: Text(
415
+ '📍 $lat, $lng',
416
+ style: typography?.body?.regular,
417
+ ),
418
+ ),
419
+ ],
420
+ ),
421
+ );
422
+ }
423
+ }
424
+ ```
425
+
426
+ ### Registering Custom Factories
427
+
428
+ Merge your custom factories with the defaults using `CometChatMessageTemplate.addTemplate` on the message list, or by providing a custom `templates` list that includes a `contentView` for your custom type.
429
+
430
+ The `CometChatMessageBubble` widget supports two modes:
431
+ - Smart mode: pass `message` and the factory registry resolves the content widget via `BubbleFactory.getFactoryKey(message)` → O(1) map lookup.
432
+ - Manual mode: pass `contentView` directly — bypasses the factory.
433
+
434
+ ```dart
435
+ // Using addTemplate to register a custom type alongside defaults
436
+ CometChatMessageList(
437
+ user: user,
438
+ addTemplate: [
439
+ CometChatMessageTemplate(
440
+ type: 'location',
441
+ category: 'custom',
442
+ contentView: (message, context, alignment, {additionalConfigurations}) {
443
+ final factory = LocationBubbleFactory();
444
+ return factory.build(context, message as CustomMessage, alignment);
445
+ },
446
+ ),
447
+ ],
448
+ )
449
+ ```
450
+
451
+ ### DataSource Pattern
452
+
453
+ Each component follows Clean Architecture with its own data source layer. The data sources abstract SDK calls behind interfaces:
454
+
455
+ ```dart
456
+ // Example: ConversationsRemoteDataSource
457
+ abstract class ConversationsRemoteDataSource {
458
+ Future<List<Conversation>> getConversations({ConversationsRequest? request});
459
+ Future<void> deleteConversation(String conversationWith);
460
+ }
461
+
462
+ class ConversationsRemoteDataSourceImpl implements ConversationsRemoteDataSource {
463
+ // Delegates to CometChat SDK
464
+ }
465
+ ```
466
+
467
+ To customize data fetching, provide a custom BLoC instance:
468
+
469
+ ```dart
470
+ CometChatConversations(
471
+ conversationsBloc: MyCustomConversationsBloc(),
472
+ )
473
+
474
+ CometChatUsers(
475
+ usersBloc: MyCustomUsersBloc(),
476
+ )
477
+
478
+ CometChatGroups(
479
+ groupsBloc: MyCustomGroupsBloc(),
480
+ )
481
+
482
+ CometChatMessageList(
483
+ messageListBloc: MyCustomMessageListBloc(),
484
+ )
485
+ ```
486
+
487
+ ## 6. Style Overrides
488
+
489
+ Every component has a `CometChat{Component}Style` class that extends `ThemeExtension`. Styles use a `merge()` pattern — your overrides layer on top of theme defaults.
490
+
491
+ ### Pattern
492
+
493
+ ```dart
494
+ @immutable
495
+ class CometChatTextBubbleStyle extends ThemeExtension<CometChatTextBubbleStyle> {
496
+ const CometChatTextBubbleStyle({
497
+ this.textStyle,
498
+ this.textColor,
499
+ this.backgroundColor,
500
+ this.border,
501
+ this.borderRadius,
502
+ this.messageBubbleAvatarStyle,
503
+ this.messageBubbleDateStyle,
504
+ this.messageBubbleBackgroundImage,
505
+ this.senderNameTextStyle,
506
+ this.messageReceiptStyle,
507
+ // ...
508
+ });
509
+
510
+ // Factory to get theme-registered instance
511
+ static CometChatTextBubbleStyle of(BuildContext context) => const CometChatTextBubbleStyle();
512
+
513
+ // Merge your overrides on top of theme defaults
514
+ CometChatTextBubbleStyle merge(CometChatTextBubbleStyle? style);
515
+
516
+ // copyWith for selective overrides
517
+ CometChatTextBubbleStyle copyWith({...});
518
+ }
519
+ ```
520
+
521
+ ### Usage
522
+
523
+ ```dart
524
+ CometChatConversations(
525
+ conversationsStyle: CometChatConversationsStyle(
526
+ backgroundColor: Colors.grey[100],
527
+ titleTextStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
528
+ ),
529
+ )
530
+
531
+ CometChatMessageHeader(
532
+ user: user,
533
+ messageHeaderStyle: CometChatMessageHeaderStyle(
534
+ backgroundColor: colorPalette.background1,
535
+ ),
536
+ )
537
+
538
+ CometChatMessageList(
539
+ user: user,
540
+ style: CometChatMessageListStyle(
541
+ backgroundColor: Colors.white,
542
+ ),
543
+ )
544
+
545
+ CometChatMessageComposer(
546
+ user: user,
547
+ messageComposerStyle: CometChatMessageComposerStyle(
548
+ backgroundColor: Colors.white,
549
+ borderRadius: BorderRadius.circular(24),
550
+ ),
551
+ )
552
+ ```
553
+
554
+ ### Theme Caching
555
+
556
+ For performance, parent widgets cache theme lookups in `didChangeDependencies()` and pass them to children via optional `colorPalette`, `spacing`, `typography` params. This avoids expensive `CometChatThemeHelper` lookups during keyboard animation rebuilds.
557
+
558
+ ```dart
559
+ // Parent caches once
560
+ late CometChatColorPalette _colorPalette;
561
+ bool _themeInitialized = false;
562
+
563
+ @override
564
+ void didChangeDependencies() {
565
+ super.didChangeDependencies();
566
+ if (!_themeInitialized) {
567
+ _colorPalette = CometChatThemeHelper.getColorPalette(context);
568
+ _themeInitialized = true;
569
+ }
570
+ }
571
+
572
+ // Pass to children
573
+ CometChatMessageBubble(
574
+ colorPalette: _colorPalette, // pre-cached, zero lookups in child
575
+ spacing: _spacing,
576
+ )
577
+ ```
578
+
579
+ ## 7. Anti-Patterns
580
+
581
+ ```dart
582
+ // ❌ WRONG — different formatters for list and composer
583
+ CometChatMessageList(textFormatters: [MarkdownTextFormatter()])
584
+ CometChatMessageComposer(textFormatters: []) // inconsistent rendering
585
+
586
+ // ✅ CORRECT — same formatter list
587
+ final formatters = [CometChatMentionsFormatter(user: user), MarkdownTextFormatter()];
588
+ CometChatMessageList(textFormatters: formatters)
589
+ CometChatMessageComposer(textFormatters: formatters)
590
+ ```
591
+
592
+ ```dart
593
+ // ❌ WRONG — calling CometChatThemeHelper in build() of a frequently-rebuilt widget
594
+ @override
595
+ Widget build(BuildContext context) {
596
+ final colorPalette = CometChatThemeHelper.getColorPalette(context); // expensive every rebuild
597
+ return Container(color: colorPalette.primary);
598
+ }
599
+
600
+ // ✅ CORRECT — cache in didChangeDependencies, use _themeInitialized flag
601
+ ```
602
+
603
+ ```dart
604
+ // ❌ WRONG — overriding templates without providing options (loses default long-press menu)
605
+ CometChatMessageList(
606
+ templates: [
607
+ CometChatMessageTemplate(
608
+ type: MessageTypeConstants.text,
609
+ category: MessageCategoryConstants.message,
610
+ contentView: (msg, ctx, align, {additionalConfigurations}) => Text(msg.text),
611
+ // options: null — no long-press menu at all!
612
+ ),
613
+ ],
614
+ )
615
+
616
+ // ✅ CORRECT — use addTemplate to add new types, or include options when overriding templates
617
+ ```
618
+
619
+ ```dart
620
+ // ❌ WRONG — creating a BubbleFactory that ignores the colorPalette/spacing params
621
+ class BadFactory extends BubbleFactory<CustomMessage> {
622
+ @override
623
+ Widget build(BuildContext context, CustomMessage message, BubbleAlignment alignment, {
624
+ CometChatColorPalette? colorPalette,
625
+ CometChatTypography? typography,
626
+ CometChatSpacing? spacing,
627
+ }) {
628
+ return Container(color: Colors.blue); // hardcoded color, ignores theme
629
+ }
630
+ }
631
+
632
+ // ✅ CORRECT — use the passed theme values
633
+ return Container(color: colorPalette?.primary ?? Colors.blue);
634
+ ```
635
+
636
+ ```dart
637
+ // ❌ WRONG — forgetting resizeToAvoidBottomInset: false on Scaffold with composer
638
+ Scaffold(
639
+ body: Column(children: [
640
+ Expanded(child: CometChatMessageList(user: user)),
641
+ CometChatMessageComposer(user: user),
642
+ ]),
643
+ )
644
+
645
+ // ✅ CORRECT
646
+ Scaffold(
647
+ resizeToAvoidBottomInset: false,
648
+ body: Column(children: [
649
+ Expanded(child: CometChatMessageList(user: user)),
650
+ CometChatMessageComposer(user: user),
651
+ ]),
652
+ )
653
+ ```
654
+
655
+ ## 8. Checklist
656
+
657
+ - [ ] Start at Tier 1 (props/view slots) before going deeper
658
+ - [ ] Same `textFormatters` list passed to both `CometChatMessageList` and `CometChatMessageComposer`
659
+ - [ ] Use `addTemplate` to add new message types alongside defaults (don't replace `templates` unless intentional)
660
+ - [ ] Custom `BubbleFactory.build()` uses the passed `colorPalette`/`typography`/`spacing` params, not hardcoded values
661
+ - [ ] Style overrides use `merge()` pattern, not constructor replacement
662
+ - [ ] Theme lookups cached in `didChangeDependencies()` with `_themeInitialized` flag
663
+ - [ ] `Scaffold` containing `CometChatMessageComposer` has `resizeToAvoidBottomInset: false`
664
+ - [ ] Custom `CometChatMessageOption.onItemClick` handles both `BaseMessage` and the controller protocol
665
+ - [ ] Request builders set `limit` to a reasonable value (default 30–50)
666
+ - [ ] Mutable `_user`/`_group` state copies passed to UIKit components, not `widget.user`/`widget.group`