Ground truth: cometchat_chat_uikit: ^5.2 (legacy/maintenance-only; calls via raw cometchat_calls_sdk ^5.0.2) — pub-cache source + ui-kit/flutter/v5. Official docs: https://www.cometchat.com/docs/ui-kit/flutter/v5/overview · Docs MCP: claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp (or fetch the URL directly without MCP). Verify symbols against the installed package/source before relying on them.
CometChat Flutter UIKit v5 — Events
Two layers: SDK listeners (low-level) and UIKit events (high-level component coordination).
Event System Architecture
Layer 1: SDK Listeners (CometChat SDK)
Raw message/call/user/group events from the network.
Layer 2: UIKit Events (CometChat UIKit)
High-level events emitted by UIKit components for UI coordination. Use a static Map<String, Listener> pattern.
Listener Registration Pattern
All event classes follow the same register/remove pattern:
// ✅ CORRECT — register in initState, remove in dispose
class _MyWidgetState extends State<MyWidget> {
late final String _listenerId;
@override
void initState() {
super.initState();
_listenerId = 'my_widget_${DateTime.now().millisecondsSinceEpoch}';
// UIKit events
CometChatMessageEvents.addMessagesListener(_listenerId, this);
CometChatUIEvents.addUiListener(_listenerId, this);
// SDK listeners
CometChat.addMessageListener(_listenerId, this);
CometChat.addUserListener(_listenerId, this);
CometChat.addGroupListener(_listenerId, this);
CometChat.addCallListener(_listenerId, this);
}
@override
void dispose() {
CometChatMessageEvents.removeMessagesListener(_listenerId);
CometChatUIEvents.removeUiListener(_listenerId);
CometChat.removeMessageListener(_listenerId);
CometChat.removeUserListener(_listenerId);
CometChat.removeGroupListener(_listenerId);
CometChat.removeCallListener(_listenerId);
super.dispose();
}
}
For GetxController, use onInit() / onClose() instead of initState() / dispose().
UIKit Event Classes — Registration
| Class |
Register |
Remove |
CometChatMessageEvents |
addMessagesListener(id, listener) |
removeMessagesListener(id) |
CometChatUserEvents |
addUsersListener(id, listener) |
removeUsersListener(id) |
CometChatGroupEvents |
addGroupsListener(id, listener) |
removeGroupsListener(id) |
CometChatCallEvents |
addCallEventsListener(id, listener) |
removeCallEventsListener(id) |
CometChatUIEvents |
addUiListener(id, listener) |
removeUiListener(id) |
CometChatConversationEvents |
addConversationListListener(id, listener) |
removeConversationListListener(id) |
SDK Listeners — Registration
| Listener |
Register |
Remove |
| Messages |
CometChat.addMessageListener(id, this) |
CometChat.removeMessageListener(id) |
| Users (online/offline) |
CometChat.addUserListener(id, this) |
CometChat.removeUserListener(id) |
| Groups |
CometChat.addGroupListener(id, this) |
CometChat.removeGroupListener(id) |
| Calls |
CometChat.addCallListener(id, this) |
CometChat.removeCallListener(id) |
| Connection |
CometChat.addConnectionListener(id, this) |
CometChat.removeConnectionListener(id) |
Key UIKit Events (commonly used)
CometChatUIEvents:
openChat(User? user, Group? group) — request to open a chat
CometChatMessageEvents:
ccMessageSent(BaseMessage message, MessageStatus status) — message sent
ccMessageEdited(BaseMessage message, MessageEditStatus status) — message edited
ccMessageDeleted(BaseMessage message, EventStatus status) — message deleted
CometChatUserEvents:
ccUserBlocked(User user) / ccUserUnblocked(User user)
CometChatGroupEvents:
ccGroupMemberKicked, ccGroupMemberBanned, ccGroupMemberAdded, ccOwnershipChanged
CometChatCallEvents:
ccOutgoingCall(Call), ccCallAccepted(Call), ccCallRejected(Call), ccCallEnded(Call)
UIKit Events vs SDK Listeners
- UIKit events — react to UIKit-level actions (message sent via composer, group created via UI, user blocked via UI)
- SDK listeners — raw network events (message received, user online/offline, group member joined)
- UIKit components internally use both
Gotchas
Unique Listener IDs
// ❌ WRONG — hardcoded ID
CometChat.addMessageListener('messages', this);
// ✅ CORRECT — unique ID
final id = 'messages_${DateTime.now().millisecondsSinceEpoch}';
CometChat.addMessageListener(id, this);
Always Remove in dispose()
// ❌ WRONG — listener leaks
@override
void dispose() {
super.dispose();
}
// ✅ CORRECT
@override
void dispose() {
CometChat.removeMessageListener(_listenerId);
super.dispose();
}
Never Register in build()
// ❌ WRONG — called every rebuild
@override
Widget build(BuildContext context) {
CometChat.addMessageListener(id, this);
return Container();
}
Checklist — Events
1---2name: cometchat-flutter-v5-events3description: "Use when working with CometChat Flutter UIKit v5 event system. Triggers on CometChatMessageEvents, CometChatUserEvents, CometChatGroupEvents, CometChatCallEvents, CometChatUIEvents, listeners."4license: "MIT"5compatibility: "cometchat_uikit_shared ^5.2.3; cometchat_sdk ^4.1.2"6metadata:7 author: "CometChat"8 version: "3.0.0"9 tags: "cometchat flutter v5 events listeners real-time typing receipts"10---1112> **Ground truth:** `cometchat_chat_uikit: ^5.2` (legacy/maintenance-only; calls via raw `cometchat_calls_sdk ^5.0.2`) — pub-cache source + `ui-kit/flutter/v5`. **Official docs:** https://www.cometchat.com/docs/ui-kit/flutter/v5/overview · **Docs MCP:** `claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp` (or fetch the URL directly without MCP). Verify symbols against the installed package/source before relying on them.1314# CometChat Flutter UIKit v5 — Events1516Two layers: SDK listeners (low-level) and UIKit events (high-level component coordination).1718## Event System Architecture1920### Layer 1: SDK Listeners (CometChat SDK)21Raw message/call/user/group events from the network.2223### Layer 2: UIKit Events (CometChat UIKit)24High-level events emitted by UIKit components for UI coordination. Use a static `Map<String, Listener>` pattern.2526## Listener Registration Pattern2728All event classes follow the same register/remove pattern:2930```dart31// ✅ CORRECT — register in initState, remove in dispose32class _MyWidgetState extends State<MyWidget> {33 late final String _listenerId;3435 @override36 void initState() {37 super.initState();38 _listenerId = 'my_widget_${DateTime.now().millisecondsSinceEpoch}';3940 // UIKit events41 CometChatMessageEvents.addMessagesListener(_listenerId, this);42 CometChatUIEvents.addUiListener(_listenerId, this);4344 // SDK listeners45 CometChat.addMessageListener(_listenerId, this);46 CometChat.addUserListener(_listenerId, this);47 CometChat.addGroupListener(_listenerId, this);48 CometChat.addCallListener(_listenerId, this);49 }5051 @override52 void dispose() {53 CometChatMessageEvents.removeMessagesListener(_listenerId);54 CometChatUIEvents.removeUiListener(_listenerId);55 CometChat.removeMessageListener(_listenerId);56 CometChat.removeUserListener(_listenerId);57 CometChat.removeGroupListener(_listenerId);58 CometChat.removeCallListener(_listenerId);59 super.dispose();60 }61}62```6364For GetxController, use `onInit()` / `onClose()` instead of `initState()` / `dispose()`.6566## UIKit Event Classes — Registration6768| Class | Register | Remove |69|-------|----------|--------|70| `CometChatMessageEvents` | `addMessagesListener(id, listener)` | `removeMessagesListener(id)` |71| `CometChatUserEvents` | `addUsersListener(id, listener)` | `removeUsersListener(id)` |72| `CometChatGroupEvents` | `addGroupsListener(id, listener)` | `removeGroupsListener(id)` |73| `CometChatCallEvents` | `addCallEventsListener(id, listener)` | `removeCallEventsListener(id)` |74| `CometChatUIEvents` | `addUiListener(id, listener)` | `removeUiListener(id)` |75| `CometChatConversationEvents` | `addConversationListListener(id, listener)` | `removeConversationListListener(id)` |7677## SDK Listeners — Registration7879| Listener | Register | Remove |80|----------|----------|--------|81| Messages | `CometChat.addMessageListener(id, this)` | `CometChat.removeMessageListener(id)` |82| Users (online/offline) | `CometChat.addUserListener(id, this)` | `CometChat.removeUserListener(id)` |83| Groups | `CometChat.addGroupListener(id, this)` | `CometChat.removeGroupListener(id)` |84| Calls | `CometChat.addCallListener(id, this)` | `CometChat.removeCallListener(id)` |85| Connection | `CometChat.addConnectionListener(id, this)` | `CometChat.removeConnectionListener(id)` |8687## Key UIKit Events (commonly used)8889**CometChatUIEvents:**90- `openChat(User? user, Group? group)` — request to open a chat9192**CometChatMessageEvents:**93- `ccMessageSent(BaseMessage message, MessageStatus status)` — message sent94- `ccMessageEdited(BaseMessage message, MessageEditStatus status)` — message edited95- `ccMessageDeleted(BaseMessage message, EventStatus status)` — message deleted9697**CometChatUserEvents:**98- `ccUserBlocked(User user)` / `ccUserUnblocked(User user)`99100**CometChatGroupEvents:**101- `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberAdded`, `ccOwnershipChanged`102103**CometChatCallEvents:**104- `ccOutgoingCall(Call)`, `ccCallAccepted(Call)`, `ccCallRejected(Call)`, `ccCallEnded(Call)`105106## UIKit Events vs SDK Listeners107108- **UIKit events** — react to UIKit-level actions (message sent via composer, group created via UI, user blocked via UI)109- **SDK listeners** — raw network events (message received, user online/offline, group member joined)110- UIKit components internally use both111112## Gotchas113114### Unique Listener IDs115```dart116// ❌ WRONG — hardcoded ID117CometChat.addMessageListener('messages', this);118119// ✅ CORRECT — unique ID120final id = 'messages_${DateTime.now().millisecondsSinceEpoch}';121CometChat.addMessageListener(id, this);122```123124### Always Remove in dispose()125```dart126// ❌ WRONG — listener leaks127@override128void dispose() {129 super.dispose();130}131132// ✅ CORRECT133@override134void dispose() {135 CometChat.removeMessageListener(_listenerId);136 super.dispose();137}138```139140### Never Register in build()141```dart142// ❌ WRONG — called every rebuild143@override144Widget build(BuildContext context) {145 CometChat.addMessageListener(id, this);146 return Container();147}148```149150## Checklist — Events151152- [ ] Listener ID is unique (use timestamp or hashCode)153- [ ] Listener registered in `initState()` / `onInit()`, not `build()`154- [ ] Listener removed in `dispose()` / `onClose()` with same ID155- [ ] UIKit events for UI coordination, SDK listeners for raw events156- [ ] `subscriptionType` set in UIKitSettings for presence events to work