{"id":"1b61b7d8-90c1-471a-8f0c-33fa8bbe2185","shortId":"dkEqmZ","kind":"skill","title":"cometchat-flutter-v6-customization","tagline":"Customize CometChat Flutter UIKit v6 beyond defaults — four tiers: props/view slots, request builders, text formatters + message templates, and BubbleFactory/DataSource. Use when the user wants custom bubbles, custom headers, custom list items, custom message actions, or custom m","description":"# CometChat Flutter UIKit v6 — Customization Guide\n\nFour tiers of customization, from lightest to deepest.\n\n## 1. Four-Tier Customization Model\n\n| Tier | Mechanism | Scope | When to Use |\n|------|-----------|-------|-------------|\n| 1 | Props & View Slots | Per-component UI overrides | Custom list items, subtitles, trailing widgets, headers |\n| 2 | Request Builders | Data filtering & pagination | Filter conversations, users, groups, messages, group members |\n| 3 | Text Formatters & Message Templates | Message rendering & actions | Custom text styling, custom long-press options, custom bubble slots |\n| 4 | BubbleFactory & DataSource | New message types | Location bubbles, poll bubbles, any custom `category_type` |\n\nStart at Tier 1. Move deeper only when the lighter tier can't solve the problem.\n\n## 2. Tier 1: Props & View Slots\n\nEvery list-based component exposes view slot callbacks that let you replace individual parts of each list item without rebuilding the entire widget.\n\n### CometChatConversations\n\n```dart\nCometChatConversations(\n  // Replace the entire list item\n  listItemView: (Conversation conversation) => MyCustomConversationTile(conversation),\n\n  // Replace individual slots\n  subtitleView: (BuildContext context, Conversation conversation) =>\n      Text(conversation.lastMessage?.text ?? ''),\n  trailingView: (Conversation conversation) =>\n      Icon(Icons.chevron_right),\n  leadingView: (BuildContext context, Conversation conversation) =>\n      CircleAvatar(child: Text(conversation.conversationWith?.name?[0] ?? '')),\n  titleView: (BuildContext context, Conversation conversation) =>\n      Text(conversation.conversationWith?.name ?? '', style: TextStyle(fontWeight: FontWeight.bold)),\n\n  // State views\n  emptyStateView: (context) => Center(child: Text('No conversations yet')),\n  errorStateView: (context) => Center(child: Text('Something went wrong')),\n  loadingStateView: (context) => Center(child: CircularProgressIndicator()),\n)\n```\n\n### CometChatUsers\n\n```dart\nCometChatUsers(\n  listItemView: (User user) => MyCustomUserTile(user),\n  subtitleView: (BuildContext context, User user) => Text(user.status ?? ''),\n  trailingView: (BuildContext context, User user) => Icon(Icons.message),\n  leadingView: (BuildContext context, User user) => CometChatAvatar(name: user.name),\n  titleView: (BuildContext context, User user) => Text(user.name),\n)\n```\n\n### CometChatGroups\n\n```dart\nCometChatGroups(\n  listItemView: (Group group) => MyCustomGroupTile(group),\n  subtitleView: (BuildContext context, Group group) =>\n      Text('${group.membersCount} members'),\n  trailingView: (BuildContext context, Group group) => Icon(Icons.arrow_forward),\n  leadingView: (BuildContext context, Group group) => CometChatAvatar(name: group.name),\n  titleView: (BuildContext context, Group group) => Text(group.name),\n)\n```\n\n### CometChatMessageHeader\n\n```dart\nCometChatMessageHeader(\n  user: user,\n  group: group,\n  subtitleView: (Group? group, User? user, BuildContext context) =>\n      Text('Custom subtitle'),\n  trailingView: (User? user, Group? group, BuildContext context) => [\n    IconButton(icon: Icon(Icons.search), onPressed: () {}),\n    IconButton(icon: Icon(Icons.info_outline), onPressed: () {}),\n  ],\n  listItemView: (Group? group, User? user, BuildContext context) =>\n      MyCustomHeaderWidget(user: user, group: group),\n  titleView: null, // use default\n  leadingStateView: null, // use default\n)\n```\n\n### CometChatMessageList\n\n```dart\nCometChatMessageList(\n  user: user,\n  group: group,\n  headerView: (context, state) => MyCustomListHeader(),\n  footerView: (context, state) => MyCustomListFooter(),\n  emptyStateView: (context) => Center(child: Text('Start a conversation')),\n  emptyChatGreetingView: (context) => WelcomeWidget(),\n  loadingStateView: (context) => ShimmerList(),\n  errorStateView: (context) => RetryWidget(),\n)\n```\n\n### CometChatMessageComposer\n\n```dart\nCometChatMessageComposer(\n  user: user,\n  group: group,\n  headerView: (context, state) => ReplyPreviewBanner(),\n  footerView: (context, state) => SuggestedActionsBar(),\n  auxiliaryButtonView: (context, user, group, composerState) =>\n      IconButton(icon: Icon(Icons.gif), onPressed: () {}),\n  secondaryButtonView: (context, user, group, composerState) =>\n      IconButton(icon: Icon(Icons.attach_file), onPressed: () {}),\n  sendButtonView: Icon(Icons.send, color: Colors.blue),\n)\n```\n\n## 3. Tier 2: Request Builders\n\nOverride the SDK request builder to control what data is fetched.\n\n### ConversationsRequestBuilder\n\n```dart\nCometChatConversations(\n  conversationsRequestBuilder: ConversationsRequestBuilder()\n    ..limit = 30\n    ..conversationType = ConversationType.user // only 1-on-1 chats\n    ..withTags = true\n    ..tags = ['vip'],\n)\n```\n\n### MessagesRequestBuilder\n\n```dart\nCometChatMessageList(\n  user: user,\n  messagesRequestBuilder: MessagesRequestBuilder()\n    ..uid = user.uid\n    ..limit = 50\n    ..hideDeletedMessages = true\n    ..searchKeyword = 'invoice'\n    ..categories = [MessageCategoryConstants.message]\n    ..types = [MessageTypeConstants.text, MessageTypeConstants.image],\n)\n```\n\n### UsersRequestBuilder\n\n```dart\nCometChatUsers(\n  usersRequestBuilder: UsersRequestBuilder()\n    ..limit = 30\n    ..friendsOnly = true\n    ..searchKeyword = 'john'\n    ..roles = ['admin', 'moderator'],\n)\n```\n\n### GroupsRequestBuilder\n\n```dart\nCometChatGroups(\n  groupsRequestBuilder: GroupsRequestBuilder()\n    ..limit = 30\n    ..joinedOnly = true\n    ..searchKeyword = 'team'\n    ..withTags = true\n    ..tags = ['project-alpha'],\n)\n```\n\n### GroupMembersRequestBuilder\n\n```dart\nCometChatGroupMembers(\n  group: group,\n  groupMembersRequestBuilder: GroupMembersRequestBuilder(group.guid)\n    ..limit = 30\n    ..scopes = [GroupMemberScope.admin, GroupMemberScope.moderator],\n)\n```\n\n## 4. Tier 3: Text Formatters & Message Templates\n\n### Text Formatters\n\n`CometChatTextFormatter` is the abstract base class. Subclass it to create custom text styling in both the message list and the composer.\n\nBuilt-in formatters:\n\n| Formatter | Purpose |\n|-----------|---------|\n| `CometChatMentionsFormatter` | @mention users with suggestion list |\n| `MarkdownTextFormatter` | Bold, italic, strikethrough, code, links, lists |\n| `CometChatUrlFormatter` | Clickable URLs |\n| `CometChatPhoneNumberFormatter` | Clickable phone numbers |\n| `CometChatEmailFormatter` | Clickable email addresses |\n\nKey properties on `CometChatTextFormatter`:\n\n```dart\nabstract class CometChatTextFormatter implements Formatter {\n  String? trackingCharacter;       // e.g. '@' for mentions\n  RegExp? pattern;                 // regex to match in text\n  Function(String?)? onSearch;     // called when tracking character typed\n  bool? showLoadingIndicator;\n  BaseMessage? message;\n  User? user;\n  Group? group;\n  StreamSink<List<SuggestionListItem>>? suggestionListEventSink;\n\n  void init();\n  void handlePreMessageSend(BuildContext context, BaseMessage baseMessage);\n  void onScrollToBottom(TextEditingController textEditingController);\n  void onChange(TextEditingController textEditingController, String previousText);\n\n  List<AttributedText> buildInputFieldText({...});\n  List<AttributedText> getAttributedText(String text, BuildContext context, BubbleAlignment? alignment, {...});\n  TextStyle getMessageBubbleTextStyle(BuildContext context, BubbleAlignment? alignment, {bool forConversation = false});\n  TextStyle getMessageInputTextStyle(BuildContext context);\n}\n```\n\nPass the same formatters to both list and composer:\n\n```dart\nfinal formatters = [\n  CometChatMentionsFormatter(user: user, group: group),\n  MarkdownTextFormatter(),\n  CometChatUrlFormatter(),\n  CometChatPhoneNumberFormatter(),\n  CometChatEmailFormatter(),\n];\n\nCometChatMessageList(user: user, textFormatters: formatters)\nCometChatMessageComposer(user: user, textFormatters: formatters)\n```\n\n### Message Templates\n\n`CometChatMessageTemplate` controls how a message type renders in the bubble and what long-press options appear.\n\n```dart\nclass CometChatMessageTemplate {\n  CometChatMessageTemplate({\n    required this.type,       // e.g. 'text', 'image', or 'location'\n    required this.category,   // e.g. 'message' or 'custom'\n    this.bubbleView,          // replaces the ENTIRE bubble\n    this.headerView,          // top of bubble (sender name area)\n    this.contentView,         // main content area\n    this.footerView,          // below statusInfoView\n    this.bottomView,          // below contentView\n    this.statusInfoView,      // receipts/time area\n    this.threadView,          // thread reply indicator\n    this.replyView,           // quoted reply preview\n    this.options,             // long-press menu options\n  });\n}\n```\n\nOverride templates on `CometChatMessageList`:\n\n```dart\nCometChatMessageList(\n  user: user,\n  // Replace all templates\n  templates: [\n    CometChatMessageTemplate(\n      type: MessageTypeConstants.text,\n      category: MessageCategoryConstants.message,\n      contentView: (message, context, alignment, {additionalConfigurations}) =>\n          MyCustomTextContent(message: message),\n      options: (loggedInUser, message, context, group, additionalConfigurations) => [\n        CometChatMessageOption(\n          id: 'bookmark',\n          title: 'Bookmark',\n          icon: Icon(Icons.bookmark_border, size: 24),\n          onItemClick: (message, state) {\n            // handle bookmark\n          },\n        ),\n      ],\n    ),\n  ],\n  // Or add templates alongside defaults\n  addTemplate: [\n    CometChatMessageTemplate(\n      type: 'location',\n      category: 'custom',\n      contentView: (message, context, alignment, {additionalConfigurations}) =>\n          LocationBubbleContent(message: message as CustomMessage),\n    ),\n  ],\n)\n```\n\n`CometChatMessageOption` model:\n\n```dart\nCometChatMessageOption(\n  id: 'pin',                    // unique identifier\n  title: 'Pin Message',         // display text\n  icon: Icon(Icons.push_pin),   // leading icon\n  onItemClick: (BaseMessage message, CometChatMessageListControllerProtocol state) {\n    // your action\n  },\n  messageOptionSheetStyle: CometChatMessageOptionSheetStyle(...),\n)\n```\n\n## 5. Tier 4: BubbleFactory & DataSource\n\n### BubbleFactory\n\nThe deepest customization for rendering message content. Each factory handles one `category_type` key.\n\n```dart\n/// Abstract factory — one per message type.\nabstract class BubbleFactory<T extends BaseMessage> {\n  Widget build(\n    BuildContext context,\n    T message,\n    BubbleAlignment alignment, {\n    CometChatColorPalette? colorPalette,\n    CometChatTypography? typography,\n    CometChatSpacing? spacing,\n  });\n\n  /// Returns \"category_type\" key, or \"deleted\" for deleted messages.\n  static String getFactoryKey(BaseMessage message);\n\n  /// Creates a key from category + type strings.\n  static String createKey(String category, String type) => '${category}_$type';\n}\n```\n\n### DefaultBubbleFactories\n\nThe built-in registry:\n\n```dart\nclass DefaultBubbleFactories {\n  static Map<String, BubbleFactory> getDefaults({\n    List<CometChatTextFormatter>? textFormatters,\n    CometChatTextBubbleStyle? incomingTextStyle,\n    CometChatTextBubbleStyle? outgoingTextStyle,\n    CometChatImageBubbleStyle? imageStyle,\n    CometChatVideoBubbleStyle? videoStyle,\n    CometChatAudioBubbleStyle? audioStyle,\n    CometChatFileBubbleStyle? fileStyle,\n  });\n}\n```\n\nDefault keys registered:\n- `message_text` → `TextBubbleFactory`\n- `message_image` → `ImageBubbleFactory`\n- `message_video` → `VideoBubbleFactory`\n- `message_audio` → `AudioBubbleFactory`\n- `message_file` → `FileBubbleFactory`\n- `deleted` → `DeletedBubbleFactory`\n\n### Creating a Custom BubbleFactory\n\nExample: a location message bubble.\n\n```dart\nclass LocationBubbleFactory extends BubbleFactory<CustomMessage> {\n  @override\n  Widget build(\n    BuildContext context,\n    CustomMessage message,\n    BubbleAlignment alignment, {\n    CometChatColorPalette? colorPalette,\n    CometChatTypography? typography,\n    CometChatSpacing? spacing,\n  }) {\n    final data = message.customData;\n    final lat = data?['latitude'] as double? ?? 0;\n    final lng = data?['longitude'] as double? ?? 0;\n\n    return GestureDetector(\n      onTap: () => _openMap(lat, lng),\n      child: Column(\n        mainAxisSize: MainAxisSize.min,\n        children: [\n          Image.network(\n            'https://maps.googleapis.com/maps/api/staticmap?center=$lat,$lng&zoom=15&size=300x200&key=YOUR_KEY',\n            width: 240,\n            height: 160,\n            fit: BoxFit.cover,\n          ),\n          Padding(\n            padding: EdgeInsets.all(spacing?.padding2 ?? 8),\n            child: Text(\n              '📍 $lat, $lng',\n              style: typography?.body?.regular,\n            ),\n          ),\n        ],\n      ),\n    );\n  }\n}\n```\n\n### Registering Custom Factories\n\nMerge 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.\n\nThe `CometChatMessageBubble` widget supports two modes:\n- Smart mode: pass `message` and the factory registry resolves the content widget via `BubbleFactory.getFactoryKey(message)` → O(1) map lookup.\n- Manual mode: pass `contentView` directly — bypasses the factory.\n\n```dart\n// Using addTemplate to register a custom type alongside defaults\nCometChatMessageList(\n  user: user,\n  addTemplate: [\n    CometChatMessageTemplate(\n      type: 'location',\n      category: 'custom',\n      contentView: (message, context, alignment, {additionalConfigurations}) {\n        final factory = LocationBubbleFactory();\n        return factory.build(context, message as CustomMessage, alignment);\n      },\n    ),\n  ],\n)\n```\n\n### DataSource Pattern\n\nEach component follows Clean Architecture with its own data source layer. The data sources abstract SDK calls behind interfaces:\n\n```dart\n// Example: ConversationsRemoteDataSource\nabstract class ConversationsRemoteDataSource {\n  Future<List<Conversation>> getConversations({ConversationsRequest? request});\n  Future<void> deleteConversation(String conversationWith);\n}\n\nclass ConversationsRemoteDataSourceImpl implements ConversationsRemoteDataSource {\n  // Delegates to CometChat SDK\n}\n```\n\nTo customize data fetching, provide a custom BLoC instance:\n\n```dart\nCometChatConversations(\n  conversationsBloc: MyCustomConversationsBloc(),\n)\n\nCometChatUsers(\n  usersBloc: MyCustomUsersBloc(),\n)\n\nCometChatGroups(\n  groupsBloc: MyCustomGroupsBloc(),\n)\n\nCometChatMessageList(\n  messageListBloc: MyCustomMessageListBloc(),\n)\n```\n\n## 6. Style Overrides\n\nEvery component has a `CometChat{Component}Style` class that extends `ThemeExtension`. Styles use a `merge()` pattern — your overrides layer on top of theme defaults.\n\n### Pattern\n\n```dart\n@immutable\nclass CometChatTextBubbleStyle extends ThemeExtension<CometChatTextBubbleStyle> {\n  const CometChatTextBubbleStyle({\n    this.textStyle,\n    this.textColor,\n    this.backgroundColor,\n    this.border,\n    this.borderRadius,\n    this.messageBubbleAvatarStyle,\n    this.messageBubbleDateStyle,\n    this.messageBubbleBackgroundImage,\n    this.senderNameTextStyle,\n    this.messageReceiptStyle,\n    // ...\n  });\n\n  // Factory to get theme-registered instance\n  static CometChatTextBubbleStyle of(BuildContext context) => const CometChatTextBubbleStyle();\n\n  // Merge your overrides on top of theme defaults\n  CometChatTextBubbleStyle merge(CometChatTextBubbleStyle? style);\n\n  // copyWith for selective overrides\n  CometChatTextBubbleStyle copyWith({...});\n}\n```\n\n### Usage\n\n```dart\nCometChatConversations(\n  conversationsStyle: CometChatConversationsStyle(\n    backgroundColor: Colors.grey[100],\n    titleTextStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),\n  ),\n)\n\nCometChatMessageHeader(\n  user: user,\n  messageHeaderStyle: CometChatMessageHeaderStyle(\n    backgroundColor: colorPalette.background1,\n  ),\n)\n\nCometChatMessageList(\n  user: user,\n  style: CometChatMessageListStyle(\n    backgroundColor: Colors.white,\n  ),\n)\n\nCometChatMessageComposer(\n  user: user,\n  messageComposerStyle: CometChatMessageComposerStyle(\n    backgroundColor: Colors.white,\n    borderRadius: BorderRadius.circular(24),\n  ),\n)\n```\n\n### Theme Caching\n\nFor 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.\n\n```dart\n// Parent caches once\nlate CometChatColorPalette _colorPalette;\nbool _themeInitialized = false;\n\n@override\nvoid didChangeDependencies() {\n  super.didChangeDependencies();\n  if (!_themeInitialized) {\n    _colorPalette = CometChatThemeHelper.getColorPalette(context);\n    _themeInitialized = true;\n  }\n}\n\n// Pass to children\nCometChatMessageBubble(\n  colorPalette: _colorPalette,  // pre-cached, zero lookups in child\n  spacing: _spacing,\n)\n```\n\n## 7. Anti-Patterns\n\n```dart\n// ❌ WRONG — different formatters for list and composer\nCometChatMessageList(textFormatters: [MarkdownTextFormatter()])\nCometChatMessageComposer(textFormatters: []) // inconsistent rendering\n\n// ✅ CORRECT — same formatter list\nfinal formatters = [CometChatMentionsFormatter(user: user), MarkdownTextFormatter()];\nCometChatMessageList(textFormatters: formatters)\nCometChatMessageComposer(textFormatters: formatters)\n```\n\n```dart\n// ❌ WRONG — calling CometChatThemeHelper in build() of a frequently-rebuilt widget\n@override\nWidget build(BuildContext context) {\n  final colorPalette = CometChatThemeHelper.getColorPalette(context); // expensive every rebuild\n  return Container(color: colorPalette.primary);\n}\n\n// ✅ CORRECT — cache in didChangeDependencies, use _themeInitialized flag\n```\n\n```dart\n// ❌ WRONG — overriding templates without providing options (loses default long-press menu)\nCometChatMessageList(\n  templates: [\n    CometChatMessageTemplate(\n      type: MessageTypeConstants.text,\n      category: MessageCategoryConstants.message,\n      contentView: (msg, ctx, align, {additionalConfigurations}) => Text(msg.text),\n      // options: null — no long-press menu at all!\n    ),\n  ],\n)\n\n// ✅ CORRECT — use addTemplate to add new types, or include options when overriding templates\n```\n\n```dart\n// ❌ WRONG — creating a BubbleFactory that ignores the colorPalette/spacing params\nclass BadFactory extends BubbleFactory<CustomMessage> {\n  @override\n  Widget build(BuildContext context, CustomMessage message, BubbleAlignment alignment, {\n    CometChatColorPalette? colorPalette,\n    CometChatTypography? typography,\n    CometChatSpacing? spacing,\n  }) {\n    return Container(color: Colors.blue); // hardcoded color, ignores theme\n  }\n}\n\n// ✅ CORRECT — use the passed theme values\nreturn Container(color: colorPalette?.primary ?? Colors.blue);\n```\n\n```dart\n// ❌ WRONG — forgetting resizeToAvoidBottomInset: false on Scaffold with composer\nScaffold(\n  body: Column(children: [\n    Expanded(child: CometChatMessageList(user: user)),\n    CometChatMessageComposer(user: user),\n  ]),\n)\n\n// ✅ CORRECT\nScaffold(\n  resizeToAvoidBottomInset: false,\n  body: Column(children: [\n    Expanded(child: CometChatMessageList(user: user)),\n    CometChatMessageComposer(user: user),\n  ]),\n)\n```\n\n## 8. Checklist\n\n- [ ] Start at Tier 1 (props/view slots) before going deeper\n- [ ] Same `textFormatters` list passed to both `CometChatMessageList` and `CometChatMessageComposer`\n- [ ] Use `addTemplate` to add new message types alongside defaults (don't replace `templates` unless intentional)\n- [ ] Custom `BubbleFactory.build()` uses the passed `colorPalette`/`typography`/`spacing` params, not hardcoded values\n- [ ] Style overrides use `merge()` pattern, not constructor replacement\n- [ ] Theme lookups cached in `didChangeDependencies()` with `_themeInitialized` flag\n- [ ] `Scaffold` containing `CometChatMessageComposer` has `resizeToAvoidBottomInset: false`\n- [ ] Custom `CometChatMessageOption.onItemClick` handles both `BaseMessage` and the controller protocol\n- [ ] Request builders set `limit` to a reasonable value (default 30–50)\n- [ ] Mutable `_user`/`_group` state copies passed to UIKit components, not `widget.user`/`widget.group`","tags":["cometchat","flutter","customization","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react"],"capabilities":["skill","source-cometchat","skill-cometchat-flutter-v6-customization","topic-agent-skills","topic-ai-agent","topic-chat","topic-claude-code","topic-cometchat","topic-cursor","topic-messaging","topic-nextjs","topic-react","topic-react-native","topic-ui-kit"],"categories":["cometchat-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cometchat/cometchat-skills/cometchat-flutter-v6-customization","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cometchat/cometchat-skills","source_repo":"https://github.com/cometchat/cometchat-skills","install_from":"skills.sh"}},"qualityScore":"0.463","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (20,149 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:51.360Z","embedding":null,"createdAt":"2026-05-07T13:05:11.209Z","updatedAt":"2026-05-18T19:04:51.360Z","lastSeenAt":"2026-05-18T19:04:51.360Z","tsv":"'-1':485 '/maps/api/staticmap?center=$lat,$lng&zoom=15&size=300x200&key=your_key'',':1081 '0':217,1059,1066 '1':57,69,134,149,483,1155,1658 '100':1351 '160':1085 '18':1355 '2':85,147,459 '24':844,1381 '240':1083 '3':98,457,557 '30':479,517,531,551,1740 '4':117,555,901 '5':899 '50':501,1741 '6':1266 '7':1449 '8':1093,1653 'abstract':567,620,920,926,1216,1224 'action':39,105,896 'add':851,1559,1676 'additionalconfigur':824,833,865,1189,1543 'address':614 'addtempl':855,1168,1179,1557,1674 'admin':523 'align':683,689,823,864,936,1043,1188,1199,1542,1590 'alongsid':853,1174,1680 'alpha':541 'anim':1411 'anti':1451 'anti-pattern':1450 'appear':746 'architectur':1206 'area':775,779,788 'audio':1014 'audiobubblefactori':1015 'audiostyl':998 'auxiliarybuttonview':431 'avoid':1405 'backgroundcolor':1349,1363,1370,1377 'badfactori':1579 'base':156,568 'basemessag':647,662,663,891,955,1726 'behind':1219 'beyond':11 'bloc':1251 'bodi':1100,1627,1642 'bold':598 'bookmark':836,838,849 'bool':645,690,1420 'border':842 'borderradius':1379 'borderradius.circular':1380 'boxfit.cover':1087 'bubbl':31,115,124,126,739,768,772,1029 'bubblealign':682,688,935,1042,1589 'bubblefactori':118,902,904,928,985,1024,1034,1572,1581 'bubblefactory.build':1689 'bubblefactory.getfactorykey':1152 'bubblefactory/datasource':24 'build':930,1037,1489,1498,1584 'buildcontext':194,208,219,262,269,276,284,299,307,315,323,341,351,369,660,680,686,695,931,1038,1322,1499,1585 'builder':18,87,461,466,1732 'buildinputfieldtext':675 'built':586,976 'built-in':585,975 'bypass':1163 'cach':1383,1388,1415,1442,1513,1710 'call':640,1218,1486 'callback':161 'categori':129,506,818,859,916,944,961,968,971,1183,1537 'center':234,242,250,401 'charact':643 'chat':486 'checklist':1654 'child':213,235,243,251,402,1073,1094,1446,1631,1646 'children':1077,1397,1436,1629,1644 'circleavatar':212 'circularprogressind':252 'class':569,621,748,927,980,1031,1225,1236,1276,1296,1578 'clean':1205 'clickabl':605,608,612 'code':601 'color':455,1510,1599,1602,1613 'colorpalett':938,1045,1400,1419,1429,1438,1439,1502,1592,1614,1693 'colorpalette.background1':1364 'colorpalette.primary':1511 'colorpalette/spacing':1576 'colors.blue':456,1600,1616 'colors.grey':1350 'colors.white':1371,1378 'column':1074,1628,1643 'cometchat':2,7,43,1242,1273 'cometchat-flutter-v6-customization':1 'cometchataudiobubblestyl':997 'cometchatavatar':280,319 'cometchatcolorpalett':937,1044,1418,1591 'cometchatconvers':177,179,475,1254,1346 'cometchatconversationsstyl':1348 'cometchatemailformatt':611,717 'cometchatfilebubblestyl':999 'cometchatgroup':290,292,527,1260 'cometchatgroupmemb':544 'cometchatimagebubblestyl':993 'cometchatmentionsformatt':591,709,1474 'cometchatmessagebubbl':1134,1437 'cometchatmessagecompos':416,418,723,1372,1464,1481,1635,1650,1672,1718 'cometchatmessagecomposerstyl':1376 'cometchatmessagehead':329,331,1358 'cometchatmessageheaderstyl':1362 'cometchatmessagelist':384,386,493,718,806,808,1176,1263,1365,1461,1478,1532,1632,1647,1670 'cometchatmessagelistcontrollerprotocol':893 'cometchatmessageliststyl':1369 'cometchatmessageopt':834,871,874 'cometchatmessageoption.onitemclick':1723 'cometchatmessageoptionsheetstyl':898 'cometchatmessagetempl':730,749,750,815,856,1180,1534 'cometchatmessagetemplate.addtemplate':1113 'cometchatphonenumberformatt':607,716 'cometchatspac':941,1048,1595 'cometchattextbubblestyl':989,991,1297,1301,1320,1325,1334,1336,1342 'cometchattextformatt':564,618,622 'cometchatthemehelp':1407,1487 'cometchatthemehelper.getcolorpalette':1430,1503 'cometchattypographi':939,1046,1593 'cometchaturlformatt':604,715 'cometchatus':253,255,513,1257 'cometchatvideobubblestyl':995 'compon':75,157,1203,1270,1274,1750 'compos':584,705,1460,1625 'composerst':435,445 'const':1300,1324 'constructor':1706 'contain':1509,1598,1612,1717 'content':778,911,1149 'contentview':785,820,861,1128,1161,1185,1539 'context':195,209,220,233,241,249,263,270,277,285,300,308,316,324,342,352,370,392,396,400,408,411,414,424,428,432,442,661,681,687,696,822,831,863,932,1039,1187,1195,1323,1431,1500,1504,1586 'control':468,731,1729 'convers':92,186,187,189,196,197,202,203,210,211,221,222,238,406 'conversation.conversationwith':215,224 'conversation.lastmessage':199 'conversationsbloc':1255 'conversationsremotedatasourc':1223,1226,1239 'conversationsremotedatasourceimpl':1237 'conversationsrequest':1230 'conversationsrequestbuild':473,476,477 'conversationsstyl':1347 'conversationtyp':480 'conversationtype.user':481 'conversationwith':1235 'copi':1746 'copywith':1338,1343 'correct':1468,1512,1555,1605,1638 'creat':573,957,1021,1570 'createkey':966 'ctx':1541 'custom':5,6,30,32,34,37,41,47,52,61,78,106,109,114,128,344,574,763,860,907,1023,1103,1107,1122,1131,1172,1184,1245,1250,1688,1722 'custommessag':870,1040,1198,1587 'dart':178,254,291,330,385,417,474,492,512,526,543,619,706,747,807,873,919,979,1030,1166,1221,1253,1294,1345,1413,1453,1484,1519,1568,1617 'data':88,470,1051,1055,1062,1210,1214,1246 'datasourc':119,903,1200 'deeper':136,1663 'deepest':56,906 'default':12,379,383,854,1001,1111,1175,1292,1333,1527,1681,1739 'defaultbubblefactori':973,981 'deleg':1240 'delet':948,950,1019 'deleteconvers':1233 'deletedbubblefactori':1020 'didchangedepend':1392,1425,1515,1712 'differ':1455 'direct':1162 'display':882 'doubl':1058,1065 'e.g':627,753,760 'edgeinsets.all':1090 'email':613 'emptychatgreetingview':407 'emptystateview':232,399 'entir':175,182,767 'errorstateview':240,413 'everi':153,1269,1506 'exampl':1025,1222 'expand':1630,1645 'expens':1406,1505 'expos':158 'extend':1033,1278,1298,1580 'factori':913,921,1104,1108,1145,1165,1191,1312 'factory.build':1194 'fals':692,1422,1621,1641,1721 'fetch':472,1247 'file':450,1017 'filebubblefactori':1018 'filestyl':1000 'filter':89,91 'final':707,1050,1053,1060,1190,1472,1501 'fit':1086 'flag':1518,1715 'flutter':3,8,44 'follow':1204 'fontsiz':1354 'fontweight':228,1356 'fontweight.bold':229 'fontweight.w600':1357 'footerview':395,427 'forconvers':691 'forget':1619 'formatt':20,100,559,563,588,589,624,700,708,722,727,1456,1470,1473,1480,1483 'forward':313 'four':13,49,59 'four-tier':58 'frequent':1493 'frequently-rebuilt':1492 'friendson':518 'function':637 'futur':1227,1232 'gesturedetector':1068 'get':1314 'getattributedtext':677 'getconvers':1229 'getdefault':986 'getfactorykey':954 'getmessagebubbletextstyl':685 'getmessageinputtextstyl':694 'go':1662 'group':94,96,294,295,297,301,302,309,310,317,318,325,326,334,335,337,338,349,350,365,366,374,375,389,390,421,422,434,444,545,546,651,652,712,713,832,1744 'group.guid':549 'group.memberscount':304 'group.name':321,328 'groupmemberscope.admin':553 'groupmemberscope.moderator':554 'groupmembersrequestbuild':542,547,548 'groupsbloc':1261 'groupsrequestbuild':525,528,529 'guid':48 'handl':848,914,1724 'handlepremessagesend':659 'hardcod':1601,1698 'header':33,84 'headerview':391,423 'height':1084 'hidedeletedmessag':502 'icon':204,273,311,354,355,359,360,437,438,447,448,453,839,840,884,885,889 'iconbutton':353,358,436,446 'icons.arrow':312 'icons.attach':449 'icons.bookmark':841 'icons.chevron':205 'icons.gif':439 'icons.info':361 'icons.message':274 'icons.push':886 'icons.search':356 'icons.send':454 'id':835,875 'identifi':878 'ignor':1574,1603 'imag':755,1008 'image.network':1078 'imagebubblefactori':1009 'imagestyl':994 'immut':1295 'implement':623,1238 'includ':1126,1563 'incomingtextstyl':990 'inconsist':1466 'indic':792 'individu':166,191 'init':657 'instanc':1252,1318 'intent':1687 'interfac':1220 'invoic':505 'ital':599 'item':36,80,171,184 'john':521 'joinedon':532 'key':615,918,946,959,1002 'keyboard':1410 'lat':1054,1071,1096 'late':1417 'latitud':1056 'layer':1212,1287 'lead':888 'leadingstateview':380 'leadingview':207,275,314 'let':163 'lighter':140 'lightest':54 'limit':478,500,516,530,550,1734 'link':602 'list':35,79,155,170,183,581,596,603,654,674,676,703,987,1117,1124,1228,1458,1471,1666 'list-bas':154 'listitemview':185,256,293,364 'lng':1061,1072,1097 'loadingstateview':248,410 'locat':123,757,858,1027,1182 'locationbubblecont':866 'locationbubblefactori':1032,1192 'loggedinus':829 'long':111,743,799,1529,1550 'long-press':110,742,798,1528,1549 'longitud':1063 'lookup':1157,1390,1408,1444,1709 'lose':1526 'm':42 'main':777 'mainaxiss':1075 'mainaxissize.min':1076 'manual':1158 'map':983,1156 'maps.googleapis.com':1080 'maps.googleapis.com/maps/api/staticmap?center=$lat,$lng&zoom=15&size=300x200&key=your_key'',':1079 'markdowntextformatt':597,714,1463,1477 'match':634 'mechan':64 'member':97,305 'mention':592,629 'menu':801,1531,1552 'merg':1105,1283,1326,1335,1703 'messag':21,38,95,101,103,121,560,580,648,728,734,761,821,826,827,830,846,862,867,868,881,892,910,924,934,951,956,1004,1007,1010,1013,1016,1028,1041,1116,1142,1153,1186,1196,1588,1678 'message.customdata':1052 'messagecategoryconstants.message':507,819,1538 'messagecomposerstyl':1375 'messageheaderstyl':1361 'messagelistbloc':1264 'messageoptionsheetstyl':897 'messagesrequestbuild':491,496,497 'messagetypeconstants.image':510 'messagetypeconstants.text':509,817,1536 'mode':1138,1140,1159 'model':62,872 'moder':524 'move':135 'msg':1540 'msg.text':1545 'mutabl':1742 'mycustomconversationsbloc':1256 'mycustomconversationtil':188 'mycustomgroupsbloc':1262 'mycustomgrouptil':296 'mycustomheaderwidget':371 'mycustomlistfoot':398 'mycustomlisthead':394 'mycustommessagelistbloc':1265 'mycustomtextcont':825 'mycustomusersbloc':1259 'mycustomusertil':259 'name':216,225,281,320,774 'new':120,1560,1677 'null':377,381,1547 'number':610 'o':1154 'onchang':669 'one':915,922 'onitemclick':845,890 'onpress':357,363,440,451 'onscrolltobottom':665 'onsearch':639 'ontap':1069 'openmap':1070 'option':113,745,802,828,1399,1525,1546,1564 'outgoingtextstyl':992 'outlin':362 'overrid':77,462,803,1035,1268,1286,1328,1341,1423,1496,1521,1566,1582,1701 'pad':1088,1089 'padding2':1092 'pagin':90 'param':1403,1577,1696 'parent':1386,1414 'part':167 'pass':697,1141,1160,1394,1434,1608,1667,1692,1747 'pattern':631,1201,1284,1293,1452,1704 'per':74,923 'per-compon':73 'perform':1385 'phone':609 'pin':876,880,887 'poll':125 'pre':1441 'pre-cach':1440 'press':112,744,800,1530,1551 'preview':796 'previoustext':673 'primari':1615 'problem':146 'project':540 'project-alpha':539 'prop':70,150 'properti':616 'props/view':15,1659 'protocol':1730 'provid':1120,1248,1524 'purpos':590 'quot':794 'reason':1737 'rebuild':173,1412,1507 'rebuilt':1494 'receipts/time':787 'regex':632 'regexp':630 'regist':1003,1102,1170,1317 'registri':978,1146 'regular':1101 'render':104,736,909,1467 'replac':165,180,190,765,811,1684,1707 'repli':791,795 'replypreviewbann':426 'request':17,86,460,465,1231,1731 'requir':751,758 'resizetoavoidbottominset':1620,1640,1720 'resolv':1147 'retrywidget':415 'return':943,1067,1193,1508,1597,1611 'right':206 'role':522 'scaffold':1623,1626,1639,1716 'scope':65,552 'sdk':464,1217,1243 'searchkeyword':504,520,534 'secondarybuttonview':441 'select':1340 'sendbuttonview':452 'sender':773 'set':1733 'shimmerlist':412 'showloadingind':646 'size':843 'skill' 'skill-cometchat-flutter-v6-customization' 'slot':16,72,116,152,160,192,1660 'smart':1139 'solv':144 'someth':245 'sourc':1211,1215 'source-cometchat' 'space':942,1049,1091,1401,1447,1448,1596,1695 'start':131,404,1655 'state':230,393,397,425,429,847,894,1745 'static':952,964,982,1319 'statusinfoview':782 'streamsink':653 'strikethrough':600 'string':625,638,672,678,953,963,965,967,969,984,1234 'style':108,226,576,1098,1267,1275,1280,1337,1368,1700 'subclass':570 'subtitl':81,345 'subtitleview':193,261,298,336 'suggest':595 'suggestedactionsbar':430 'suggestionlisteventsink':655 'super.didchangedependencies':1426 'support':1136 'tag':489,538 'team':535 'templat':22,102,561,729,804,813,814,852,1123,1522,1533,1567,1685 'text':19,99,107,198,200,214,223,236,244,266,288,303,327,343,403,558,562,575,636,679,754,883,1005,1095,1544 'textbubblefactori':1006 'texteditingcontrol':666,667,670,671 'textformatt':721,726,988,1462,1465,1479,1482,1665 'textstyl':227,684,693,1353 'theme':1291,1316,1332,1382,1389,1604,1609,1708 'theme-regist':1315 'themeextens':1279,1299 'themeiniti':1421,1428,1432,1517,1714 'this.backgroundcolor':1304 'this.border':1305 'this.borderradius':1306 'this.bottomview':783 'this.bubbleview':764 'this.category':759 'this.contentview':776 'this.footerview':780 'this.headerview':769 'this.messagebubbleavatarstyle':1307 'this.messagebubblebackgroundimage':1309 'this.messagebubbledatestyle':1308 'this.messagereceiptstyle':1311 'this.options':797 'this.replyview':793 'this.sendernametextstyle':1310 'this.statusinfoview':786 'this.textcolor':1303 'this.textstyle':1302 'this.threadview':789 'this.type':752 'thread':790 'tier':14,50,60,63,133,141,148,458,556,900,1657 'titl':837,879 'titletextstyl':1352 'titleview':218,283,322,376 'top':770,1289,1330 'topic-agent-skills' 'topic-ai-agent' 'topic-chat' 'topic-claude-code' 'topic-cometchat' 'topic-cursor' 'topic-messaging' 'topic-nextjs' 'topic-react' 'topic-react-native' 'topic-ui-kit' 'track':642 'trackingcharact':626 'trail':82 'trailingview':201,268,306,346 'true':488,503,519,533,537,1433 'two':1137 'type':122,130,508,644,735,816,857,917,925,945,962,970,972,1132,1173,1181,1535,1561,1679 'typographi':940,1047,1099,1402,1594,1694 'ui':76 'uid':498 'uikit':9,45,1749 'uniqu':877 'unless':1686 'url':606 'usag':1344 'use':25,68,378,382,1112,1167,1281,1516,1556,1606,1673,1690,1702 'user':28,93,257,258,260,264,265,271,272,278,279,286,287,332,333,339,340,347,348,367,368,372,373,387,388,419,420,433,443,494,495,593,649,650,710,711,719,720,724,725,809,810,1177,1178,1359,1360,1366,1367,1373,1374,1475,1476,1633,1634,1636,1637,1648,1649,1651,1652,1743 'user.name':282,289 'user.status':267 'user.uid':499 'usersbloc':1258 'usersrequestbuild':511,514,515 'v6':4,10,46 'valu':1610,1699,1738 'via':1151,1398 'video':1011 'videobubblefactori':1012 'videostyl':996 'view':71,151,159,231 'vip':490 'void':656,658,664,668,1424 'want':29 'welcomewidget':409 'went':246 'widget':83,176,929,1036,1135,1150,1387,1495,1497,1583 'widget.group':1753 'widget.user':1752 'width':1082 'without':172,1523 'withtag':487,536 'wrong':247,1454,1485,1520,1569,1618 'yet':239 'zero':1443","prices":[{"id":"dfedf1e2-3b14-4a25-9589-95a6c3883c0a","listingId":"1b61b7d8-90c1-471a-8f0c-33fa8bbe2185","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cometchat","category":"cometchat-skills","install_from":"skills.sh"},"createdAt":"2026-05-07T13:05:11.209Z"}],"sources":[{"listingId":"1b61b7d8-90c1-471a-8f0c-33fa8bbe2185","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-flutter-v6-customization","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-flutter-v6-customization","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:11.209Z","lastSeenAt":"2026-05-18T19:04:51.360Z"}],"details":{"listingId":"1b61b7d8-90c1-471a-8f0c-33fa8bbe2185","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-flutter-v6-customization","github":{"repo":"cometchat/cometchat-skills","stars":27,"topics":["agent-skills","ai-agent","chat","claude-code","cometchat","cursor","messaging","nextjs","react","react-native","ui-kit"],"license":null,"html_url":"https://github.com/cometchat/cometchat-skills","pushed_at":"2026-05-18T05:04:24Z","description":"Add CometChat chat to any React, Next.js, React Native, Angular, Android, iOS, or Flutter project through your AI coding agent. Works with Claude Code, Cursor, Codex, VS Code Copilot, Windsurf, Cline, Kiro, and 50+ more agents.","skill_md_sha":"941b62f6c13dc8193e6f9465da47ae320a4cf9dd","skill_md_path":"skills/cometchat-flutter-v6-customization/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-flutter-v6-customization"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-flutter-v6-customization","license":"MIT","description":"Customize CometChat Flutter UIKit v6 beyond defaults — four tiers: props/view slots, request builders, text formatters + message templates, and BubbleFactory/DataSource. Use when the user wants custom bubbles, custom headers, custom list items, custom message actions, or custom message types.","compatibility":"cometchat_chat_uikit ^6.0.0-beta2"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-flutter-v6-customization"},"updatedAt":"2026-05-18T19:04:51.360Z"}}