> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-platform-docs-release.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# All Real Time Listeners

> Learn how to register and manage real-time event listeners for messages, users, groups, calls, connections, login, and AI in the CometChat Flutter SDK.

<Accordion title="AI Integration Quick Reference">
  ```dart theme={null}
  // Message Listener - receive messages in real-time
  CometChat.addMessageListener("message_listener", MessageListener(
    onTextMessageReceived: (TextMessage message) {
      debugPrint("Text received: ${message.text}");
    },
    onMediaMessageReceived: (MediaMessage message) {
      debugPrint("Media received: ${message.attachment?.fileUrl}");
    },
  ));

  // User Listener - track user online/offline status
  CometChat.addUserListener("user_listener", UserListener(
    onUserOnline: (User user) {
      debugPrint("${user.name} is online");
    },
    onUserOffline: (User user) {
      debugPrint("${user.name} is offline");
    },
  ));

  // Group Listener - track group membership changes
  CometChat.addGroupListener("group_listener", GroupListener(
    onGroupMemberJoined: (action, joinedUser, joinedGroup) {
      debugPrint("${joinedUser.name} joined ${joinedGroup.name}");
    },
    onGroupMemberLeft: (action, leftUser, leftGroup) {
      debugPrint("${leftUser.name} left ${leftGroup.name}");
    },
  ));

  // Call Listener - track incoming/outgoing calls
  CometChat.addCallListener("call_listener", CallListener(
    onIncomingCallReceived: (Call call) {
      debugPrint("Incoming call from: ${call.sender?.name}");
    },
    onOutgoingCallAccepted: (Call call) {
      debugPrint("Call accepted");
    },
  ));

  // Connection Listener - monitor WebSocket connection
  CometChat.addConnectionListener("conn_listener", ConnectionListener(
    onConnected: () => debugPrint("Connected"),
    onDisconnected: () => debugPrint("Disconnected"),
  ));

  // Remove listeners when no longer needed
  CometChat.removeMessageListener("message_listener");
  CometChat.removeUserListener("user_listener");
  CometChat.removeGroupListener("group_listener");
  CometChat.removeCallListener("call_listener");
  CometChat.removeConnectionListener("conn_listener");
  ```
</Accordion>

CometChat provides real-time event listeners to keep your app updated with live changes. These listeners notify your app when messages are received, users come online/offline, group membership changes occur, calls are initiated, and connection state changes.

<Warning>
  **Listener Cleanup Required:** Always remove listeners when they're no longer needed (e.g., on widget dispose or page navigation). Failing to remove listeners can cause memory leaks and duplicate event handling.
</Warning>

CometChat provides 7 listener types:

1. [MessageListener](#message-listener)
2. [UserListener](#user-listener)
3. [GroupListener](#group-listener)
4. [CallListener](#call-listener)
5. [ConnectionListener](#connection-listener)
6. [LoginListener](#login-listener)
7. [AIAssistantListener](#ai-assistant-listener)

## Message Listener

The `MessageListener` class provides you with live events related to messages. Below are the callback methods provided by the `MessageListener` class.

### MessageListener Events

| Method                                                     | Parameter Type                                                  | Description                                                        |
| ---------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------ |
| `onTextMessageReceived(TextMessage message)`               | [`TextMessage`](/sdk/reference/messages#textmessage)            | Triggered when a text message is received                          |
| `onMediaMessageReceived(MediaMessage message)`             | [`MediaMessage`](/sdk/reference/messages#mediamessage)          | Triggered when a media message is received                         |
| `onCustomMessageReceived(CustomMessage message)`           | [`CustomMessage`](/sdk/reference/messages#custommessage)        | Triggered when a custom message is received                        |
| `onTypingStarted(TypingIndicator typingIndicator)`         | [`TypingIndicator`](/sdk/reference/auxiliary#typingindicator)   | Triggered when a user starts typing in a user/group conversation   |
| `onTypingEnded(TypingIndicator typingIndicator)`           | [`TypingIndicator`](/sdk/reference/auxiliary#typingindicator)   | Triggered when a user stops typing in a user/group conversation    |
| `onMessagesDelivered(MessageReceipt messageReceipt)`       | [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt)     | Triggered when messages are marked as delivered for a conversation |
| `onMessagesRead(MessageReceipt messageReceipt)`            | [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt)     | Triggered when messages are marked as read for a conversation      |
| `onMessagesDeliveredToAll(MessageReceipt messageReceipt)`  | [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt)     | Triggered when messages are delivered to all participants          |
| `onMessagesReadByAll(MessageReceipt messageReceipt)`       | [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt)     | Triggered when messages are read by all participants               |
| `onMessageEdited(BaseMessage message)`                     | [`BaseMessage`](/sdk/reference/messages#basemessage)            | Triggered when a message is edited in a user/group conversation    |
| `onMessageDeleted(BaseMessage message)`                    | [`BaseMessage`](/sdk/reference/messages#basemessage)            | Triggered when a message is deleted in a user/group conversation   |
| `onMessageModerated(BaseMessage message)`                  | [`BaseMessage`](/sdk/reference/messages#basemessage)            | Triggered when a message is moderated                              |
| `onTransientMessageReceived(TransientMessage message)`     | [`TransientMessage`](/sdk/reference/auxiliary#transientmessage) | Triggered when a transient message is received                     |
| `onInteractiveMessageReceived(InteractiveMessage message)` | `InteractiveMessage`                                            | Triggered when an interactive message is received                  |
| `onInteractionGoalCompleted(InteractionReceipt receipt)`   | `InteractionReceipt`                                            | Triggered when an interaction goal is achieved                     |
| `onMessageReactionAdded(ReactionEvent reactionEvent)`      | `ReactionEvent`                                                 | Triggered when a reaction is added to a message                    |
| `onMessageReactionRemoved(ReactionEvent reactionEvent)`    | `ReactionEvent`                                                 | Triggered when a reaction is removed from a message                |
| `onAIAssistantMessageReceived(AIAssistantMessage message)` | `AIAssistantMessage`                                            | Triggered when an AI assistant message is received                 |
| `onAIToolResultReceived(AIToolResultMessage message)`      | `AIToolResultMessage`                                           | Triggered when an AI tool result message is received               |
| `onAIToolArgumentsReceived(AIToolArgumentMessage message)` | `AIToolArgumentMessage`                                         | Triggered when AI tool arguments are received                      |

To add the `MessageListener`, you need to use the `addMessageListener()` method provided by the `CometChat` class.

| Parameter    | Type              | Description                                                                      |
| ------------ | ----------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`          | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `MessageListener` | An instance of a class that implements the `MessageListener` mixin               |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with MessageListener {

      //CometChat.addMessageListener("listenerId", this);
    	@override
      void onTextMessageReceived(TextMessage textMessage) {

      }

      @override
      void onMediaMessageReceived(MediaMessage mediaMessage) {

      }

      @override
      void onCustomMessageReceived(CustomMessage customMessage) {

      }

        @override
      void onTypingStarted(TypingIndicator typingIndicator) {

      }

      @override
      void onTypingEnded(TypingIndicator typingIndicator) {

      }


      @override
      void onMessagesDelivered(MessageReceipt messageReceipt) {

      }

      @override
      void onMessagesRead(MessageReceipt messageReceipt) {

      }

      @override
      void onMessageEdited(BaseMessage message) {

      }

      @override
      void onMessageDeleted(BaseMessage message) {

      }

      @override
      void onInteractionGoalCompleted(InteractionReceipt receipt) {


      }

      @override
      void onInteractiveMessageReceived(InteractiveMessage message) {

      }


      @Override
      public void onTransientMessageReceived(TransientMessage transientMessage) {

      }

      @Override
      public void onMessageReactionAdded(ReactionEvent reactionEvent) {

      }

      @Override
      public void onMessageReactionRemoved(ReactionEvent reactionEvent) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the activity/fragment where the `MessageListener` is declared is not in use, you need to remove the listener using the `removeMessageListener()` method which takes the id of the listener to be removed as the parameter. We suggest you call this method in the `onPause()` method of the activity/fragment.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeMessageListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

## User Listener

The `UserListener` class provides you with live events related to users. Below are the callback methods provided by the `UserListener` class.

### UserListener Events

| Method                     | Parameter Type                         | Description                                                                                                                                                   |
| -------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onUserOnline(User user)`  | [`User`](/sdk/reference/entities#user) | Triggered when a user comes online and is available to chat. The details of the user can be obtained from the `User` object received as the method parameter. |
| `onUserOffline(User user)` | [`User`](/sdk/reference/entities#user) | Triggered when a user goes offline. The details of the user can be obtained from the `User` object received as the parameter.                                 |

To add the `UserListener`, you need to use the `addUserListener()` method provided by the `CometChat` class.

| Parameter    | Type           | Description                                                                      |
| ------------ | -------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`       | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `UserListener` | An instance of a class that implements the `UserListener` mixin                  |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with UserListener {
      //CometChat.addUserListener("user_Listener_id", this);
    	@override
      void onUserOnline(User user) {

      }

      @override
      void onUserOffline(User user) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the activity/fragment where the `UserListener` is declared is not in use, you need to remove the listener using the `removeUserListener()` method which takes the id of the listener to be removed as the parameter. We suggest you call this method in the `onPause()` method of the activity/fragment.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeUserListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

## Group Listener

The `GroupListener` class provides you with all the real-time events related to groups. Below are the callback methods provided by the `GroupListener` class.

### GroupListener Events

| Method                                                                                                                                    | Parameter Types                                                                                                                                                                          | Description                                                                                                                      |
| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `onGroupMemberJoined(Action action, User joinedUser, Group joinedGroup)`                                                                  | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`Group`](/sdk/reference/entities#group)                                                             | Triggered when a user joins any group. All the members present in the group will receive this event.                             |
| `onGroupMemberLeft(Action action, User leftUser, Group leftGroup)`                                                                        | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`Group`](/sdk/reference/entities#group)                                                             | Triggered when a user who was a member of any group leaves the group. All the members of the group receive this event.           |
| `onGroupMemberKicked(Action action, User kickedUser, User kickedBy, Group kickedFrom)`                                                    | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`User`](/sdk/reference/entities#user), [`Group`](/sdk/reference/entities#group)                     | Triggered when a user is kicked from a group. All the members including the user receive this event.                             |
| `onGroupMemberBanned(Action action, User bannedUser, User bannedBy, Group bannedFrom)`                                                    | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`User`](/sdk/reference/entities#user), [`Group`](/sdk/reference/entities#group)                     | Triggered when a user is banned from a group. All the members including the user receive this event.                             |
| `onGroupMemberUnbanned(Action action, User unbannedUser, User unbannedBy, Group unbannedFrom)`                                            | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`User`](/sdk/reference/entities#user), [`Group`](/sdk/reference/entities#group)                     | Triggered when a user is unbanned from a group. All the members of the group receive this event.                                 |
| `onGroupMemberScopeChanged(Action action, User updatedBy, User updatedUser, String scopeChangedTo, String scopeChangedFrom, Group group)` | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`User`](/sdk/reference/entities#user), `String`, `String`, [`Group`](/sdk/reference/entities#group) | Triggered when the scope of any group member has been changed. All the members that are a part of that group receive this event. |
| `onMemberAddedToGroup(Action action, User addedBy, User userAdded, Group addedTo)`                                                        | [`Action`](/sdk/reference/messages#action), [`User`](/sdk/reference/entities#user), [`User`](/sdk/reference/entities#user), [`Group`](/sdk/reference/entities#group)                     | Triggered when a user is added to any group. All the members including the user himself receive this event.                      |

To add the `GroupListener`, you need to use the `addGroupListener()` method provided by the `CometChat` class.

| Parameter    | Type            | Description                                                                      |
| ------------ | --------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`        | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `GroupListener` | An instance of a class that implements the `GroupListener` mixin                 |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with GroupListener {
      //CometChat.addGroupListener("UNIQUE_LISTENER_ID", this);

      @override
      void onGroupMemberJoined(Action action, User joinedUser, Group joinedGroup) {

      }

      @override
      void onGroupMemberLeft(Action action, User leftUser, Group leftGroup) {

      }

      @override
      void onGroupMemberKicked(Action action, User kickedUser, User kickedBy, Group kickedFrom) {

      }

      @override
      void onGroupMemberBanned(Action action, User bannedUser, User bannedBy, Group bannedFrom) {

      }

      @override
      void onGroupMemberUnbanned(Action action, User unbannedUser, User unbannedBy, Group unbannedFrom) {

      }

      @override
      void onGroupMemberScopeChanged(Action action, User updatedBy, User updatedUser, String scopeChangedTo, String scopeChangedFrom, Group group) {

      }

      @override
      void onMemberAddedToGroup(Action action, User addedby, User userAdded, Group addedTo) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the activity/fragment where the `GroupListener` is declared is not in use, you need to remove the listener using the `removeGroupListener()` method which takes the id of the listener to be removed as the parameter. We suggest you call this method in the `onPause()` method of the activity/fragment.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeGroupListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

## Call Listener

The `CallListener` class provides you with real-time events related to calls. Below are the callback methods provided by the `CallListener` class.

### CallListener Events

| Method                                  | Parameter Type                         | Description                                                 |
| --------------------------------------- | -------------------------------------- | ----------------------------------------------------------- |
| `onIncomingCallReceived(Call call)`     | [`Call`](/sdk/reference/messages#call) | Triggered when an incoming call is received                 |
| `onOutgoingCallAccepted(Call call)`     | [`Call`](/sdk/reference/messages#call) | Triggered when an outgoing call is accepted by the receiver |
| `onOutgoingCallRejected(Call call)`     | [`Call`](/sdk/reference/messages#call) | Triggered when an outgoing call is rejected by the receiver |
| `onIncomingCallCancelled(Call call)`    | [`Call`](/sdk/reference/messages#call) | Triggered when an incoming call is cancelled by the caller  |
| `onCallEndedMessageReceived(Call call)` | [`Call`](/sdk/reference/messages#call) | Triggered when a call ended message is received             |

To add the `CallListener`, you need to use the `addCallListener()` method provided by the `CometChat` class.

| Parameter    | Type           | Description                                                                      |
| ------------ | -------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`       | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `CallListener` | An instance of a class that implements the `CallListener` mixin                  |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with CallListener {
      //CometChat.addCallListener("UNIQUE_LISTENER_ID", this);

      @override
      void onIncomingCallReceived(Call call) {

      }

      @override
      void onOutgoingCallAccepted(Call call) {

      }

      @override
      void onOutgoingCallRejected(Call call) {

      }

      @override
      void onIncomingCallCancelled(Call call) {

      }

      @override
      void onCallEndedMessageReceived(Call call) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the `CallListener` is no longer needed, remove it using the `removeCallListener()` method.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeCallListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

## Connection Listener

The `ConnectionListener` class provides you with real-time events related to the WebSocket connection status. Below are the callback methods provided by the `ConnectionListener` class.

### ConnectionListener Events

| Method                                        | Parameter Type       | Description                                                                                     |
| --------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------- |
| `onConnected()`                               | —                    | Triggered when the SDK successfully establishes a connection to the WebSocket server            |
| `onConnecting()`                              | —                    | Triggered when the SDK is attempting to establish a connection to the WebSocket server          |
| `onDisconnected()`                            | —                    | Triggered when the SDK gets disconnected due to network fluctuations or other issues            |
| `onFeatureThrottled()`                        | —                    | Triggered when CometChat automatically toggles off certain features to prevent performance loss |
| `onConnectionError(CometChatException error)` | `CometChatException` | Triggered when an error occurs while maintaining the WebSocket connection                       |

To add the `ConnectionListener`, you need to use the `addConnectionListener()` method provided by the `CometChat` class.

| Parameter    | Type                 | Description                                                                      |
| ------------ | -------------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`             | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `ConnectionListener` | An instance of a class that implements the `ConnectionListener` mixin            |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with ConnectionListener {
      //CometChat.addConnectionListener("UNIQUE_LISTENER_ID", this);

      @override
      void onConnected() {

      }

      @override
      void onConnecting() {

      }

      @override
      void onDisconnected() {

      }

      @override
      void onFeatureThrottled() {

      }

      @override
      void onConnectionError(CometChatException error) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the `ConnectionListener` is no longer needed, remove it using the `removeConnectionListener()` method.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeConnectionListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

## Login Listener

The `LoginListener` class provides you with real-time events related to user authentication. Below are the callback methods provided by the `LoginListener` class.

### LoginListener Events

| Method                                | Parameter Type                         | Description                                 |
| ------------------------------------- | -------------------------------------- | ------------------------------------------- |
| `loginSuccess(User user)`             | [`User`](/sdk/reference/entities#user) | Triggered when a user successfully logs in  |
| `loginFailure(CometChatException e)`  | `CometChatException`                   | Triggered when a login attempt fails        |
| `logoutSuccess()`                     | —                                      | Triggered when a user successfully logs out |
| `logoutFailure(CometChatException e)` | `CometChatException`                   | Triggered when a logout attempt fails       |

To add the `LoginListener`, you need to use the `addLoginListener()` method provided by the `CometChat` class.

| Parameter    | Type            | Description                                                                      |
| ------------ | --------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`        | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `LoginListener` | An instance of a class that implements the `LoginListener` mixin                 |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with LoginListener {
      //CometChat.addLoginListener("UNIQUE_LISTENER_ID", this);

      @override
      void loginSuccess(User user) {

      }

      @override
      void loginFailure(CometChatException e) {

      }

      @override
      void logoutSuccess() {

      }

      @override
      void logoutFailure(CometChatException e) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the `LoginListener` is no longer needed, remove it using the `removeLoginListener()` method.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeLoginListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

## AI Assistant Listener

The `AIAssistantListener` class provides you with real-time events related to AI assistant interactions. Below are the callback methods provided by the `AIAssistantListener` class.

### AIAssistantListener Events

| Method                                                                  | Parameter Type                                                         | Description                                      |
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------ |
| `onAIAssistantEventReceived(AIAssistantBaseEvent aiAssistantBaseEvent)` | [`AIAssistantBaseEvent`](/sdk/reference/messages#aiassistantbaseevent) | Triggered when an AI assistant event is received |

To add the `AIAssistantListener`, you need to use the `addAIAssistantListener()` method provided by the `CometChat` class.

| Parameter    | Type                  | Description                                                                      |
| ------------ | --------------------- | -------------------------------------------------------------------------------- |
| `listenerId` | `String`              | A unique identifier for the listener. No two listeners should share the same ID. |
| `listener`   | `AIAssistantListener` | An instance of a class that implements the `AIAssistantListener` mixin           |

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class Class_Name with AIAssistantListener {
      //CometChat.addAIAssistantListener("UNIQUE_LISTENER_ID", this);

      @override
      void onAIAssistantEventReceived(AIAssistantBaseEvent aiAssistantBaseEvent) {

      }

    }
    ```
  </Tab>
</Tabs>

where `UNIQUE_LISTENER_ID` is the unique identifier for the listener. Please make sure that no two listeners are added with the same listener id as this could lead to unexpected behavior resulting in loss of events.

Once the `AIAssistantListener` is no longer needed, remove it using the `removeAIAssistantListener()` method.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChat.removeAIAssistantListener(UNIQUE_LISTENER_ID)
    ```
  </Tab>
</Tabs>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Receive Messages" icon="inbox" href="/sdk/flutter/receive-messages">
    Handle incoming messages in real-time using message listeners
  </Card>

  <Card title="User Presence" icon="circle-user" href="/sdk/flutter/user-presence">
    Track when users come online or go offline
  </Card>

  <Card title="Typing Indicators" icon="keyboard" href="/sdk/flutter/typing-indicators">
    Show real-time typing status in conversations
  </Card>

  <Card title="Delivery & Read Receipts" icon="check-double" href="/sdk/flutter/delivery-read-receipts">
    Track message delivery and read status
  </Card>

  <Card title="Connection Status" icon="wifi" href="/sdk/flutter/connection-status">
    Monitor SDK connection to CometChat servers
  </Card>

  <Card title="Login Listeners" icon="user-check" href="/sdk/flutter/authentication-overview#login-listener">
    Monitor user login and logout events
  </Card>
</CardGroup>
