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

# Message List

> Scrollable list of messages for a conversation with real-time updates, reactions, threaded replies, and message actions.

`CometChatMessageList` renders a scrollable list of messages for a conversation with real-time updates for new messages, edits, deletions, reactions, and threaded replies.

***

## Where It Fits

`CometChatMessageList` is a message display component. It requires either a `User` or `Group` object to fetch and render messages. Wire it with `CometChatMessageHeader` and `CometChatMessageComposer` to build a complete messaging layout.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
    )
    ```
  </Tab>
</Tabs>

***

## Quick Start

Using Navigator:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    Navigator.push(context, MaterialPageRoute(builder: (context) => CometChatMessageList(user: user)));
    ```
  </Tab>
</Tabs>

Embedding as a widget:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: SafeArea(
          child: CometChatMessageList(
            user: user, // or group: group
          ),
        ),
      );
    }
    ```
  </Tab>
</Tabs>

Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()`, a user logged in, and the UI Kit dependency added.

<Warning>
  Simply adding the `MessageList` component to the layout will only display the loading indicator. You must supply a `User` or `Group` object to fetch messages.
</Warning>

***

## Filtering

Pass a `MessagesRequestBuilder` to control what loads:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      messagesRequestBuilder: MessagesRequestBuilder()
        ..uid = user.uid
        ..searchKeyword = "hello"
        ..limit = 30,
    )
    ```
  </Tab>
</Tabs>

<Note>
  The following parameters in `MessagesRequestBuilder` will always be altered inside the message list: UID, GUID, types, categories.
</Note>

***

## Actions and Events

### Callback Methods

#### `onThreadRepliesClick`

Fires when a user taps a threaded message bubble.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      onThreadRepliesClick: (message, context, {template}) {
        // Navigate to thread view
      },
    )
    ```
  </Tab>
</Tabs>

#### `onError`

Fires on internal errors.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      onError: (e) {
        debugPrint("Error: ${e.message}");
      },
    )
    ```
  </Tab>
</Tabs>

#### `onLoad`

Fires when the list is successfully fetched and loaded.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      onLoad: (messages) {
        debugPrint("Loaded ${messages.length}");
      },
    )
    ```
  </Tab>
</Tabs>

#### `onEmpty`

Fires when the list is empty after loading.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      onEmpty: () {
        debugPrint("No messages");
      },
    )
    ```
  </Tab>
</Tabs>

#### `onReactionClick`

Fires when a reaction pill is tapped.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      onReactionClick: (emoji, message) {
        // Handle reaction click
      },
    )
    ```
  </Tab>
</Tabs>

#### `onReactionLongPress`

Fires when a reaction pill is long-pressed.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      onReactionLongPress: (emoji, message) {
        // Handle reaction long press
      },
    )
    ```
  </Tab>
</Tabs>

### SDK Events (Real-Time, Automatic)

The component listens to SDK message events internally. No manual setup needed.

| SDK Listener                                                                   | Internal behavior                             |
| ------------------------------------------------------------------------------ | --------------------------------------------- |
| `onTextMessageReceived` / `onMediaMessageReceived` / `onCustomMessageReceived` | Inserts new message with animation            |
| `onMessageEdited`                                                              | Updates message in-place                      |
| `onMessageDeleted`                                                             | Removes or marks message as deleted           |
| `onMessagesDelivered` / `onMessagesRead`                                       | Updates receipt status via ValueNotifier      |
| `onTypingStarted` / `onTypingEnded`                                            | Updates typing indicator                      |
| `onMessageReactionAdded` / `onMessageReactionRemoved`                          | Updates reaction counts                       |
| Connection reconnected                                                         | Triggers silent sync to fetch missed messages |

***

## Functionality

| Property                    | Type                                | Default    | Description                                                           |
| --------------------------- | ----------------------------------- | ---------- | --------------------------------------------------------------------- |
| `user`                      | `User?`                             | required\* | User for 1-on-1 conversation                                          |
| `group`                     | `Group?`                            | required\* | Group for group conversation                                          |
| `parentMessageId`           | `int?`                              | `null`     | Parent message ID for thread replies                                  |
| `alignment`                 | `ChatAlignment`                     | `standard` | Chat alignment setting                                                |
| `hideDeletedMessages`       | `bool`                              | `false`    | Hide deleted messages entirely                                        |
| `disableReceipts`           | `bool`                              | `false`    | Disable read/delivery receipts                                        |
| `disableSoundForMessages`   | `bool`                              | `false`    | Disable message sounds                                                |
| `hideReplies`               | `bool`                              | `true`     | Hide thread replies in main conversation                              |
| `hideGroupActionMessages`   | `bool?`                             | `false`    | Hide group action messages                                            |
| `hideTimestamp`             | `bool?`                             | `null`     | Toggle timestamp visibility                                           |
| `hideDateSeparator`         | `bool?`                             | `false`    | Hide date separators                                                  |
| `hideStickyDate`            | `bool?`                             | `false`    | Hide floating sticky date header                                      |
| `avatarVisibility`          | `bool?`                             | `true`     | Toggle avatar visibility                                              |
| `receiptsVisibility`        | `bool?`                             | `true`     | Toggle read receipts                                                  |
| `disableReactions`          | `bool?`                             | `false`    | Toggle reactions                                                      |
| `enableSwipeToReply`        | `bool`                              | `true`     | Enable swipe-to-reply gesture                                         |
| `startFromUnreadMessages`   | `bool`                              | `false`    | Scroll to first unread on open                                        |
| `loadLastAgentConversation` | `bool`                              | `false`    | Loads the most recent existing agent conversation on start            |
| `showMarkAsUnreadOption`    | `bool`                              | `false`    | Show "Mark as Unread" in long-press options                           |
| `goToMessageId`             | `int?`                              | `null`     | Scroll to a specific message after load                               |
| `hideFlagOption`            | `bool`                              | `false`    | Hide the Flag/Report option from message long-press actions           |
| `hideFlagRemarkField`       | `bool`                              | `false`    | Hide the optional remark/context text field in the flag dialog        |
| `flagReasonLocalizer`       | `String Function(String reasonId)?` | `null`     | Custom localizer that converts a flag-reason ID into a display string |

\* One of `user` or `group` is required.

***

## Custom View Slots

### Header View

Custom view displayed at the top of the message list.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      headerView: (context, {user, group, parentMessageId}) {
        return Container(
          padding: EdgeInsets.all(8),
          child: Text("Pinned Messages"),
        );
      },
    )
    ```
  </Tab>
</Tabs>

### Footer View

Custom view displayed at the bottom of the message list.

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      footerView: (context, {user, group, parentMessageId}) {
        return Container(
          padding: EdgeInsets.all(8),
          child: Text("End of messages"),
        );
      },
    )
    ```
  </Tab>
</Tabs>

### State Views

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      emptyStateView: (context) => Center(child: Text("No messages yet")),
      errorStateView: (context) => Center(child: Text("Something went wrong")),
      loadingStateView: (context) => Center(child: CircularProgressIndicator()),
      emptyChatGreetingView: (context) => Center(child: Text("Say hello!")),
    )
    ```
  </Tab>
</Tabs>

### Text Formatters (Mentions)

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      textFormatters: [
        CometChatMentionsFormatter(),
      ],
    )
    ```
  </Tab>
</Tabs>

### Message Templates

Override or extend message bubble rendering:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    // Replace all templates
    CometChatMessageList(
      user: user,
      templates: getCustomTemplates(),
    )

    // Add/override specific templates (merged with defaults)
    CometChatMessageList(
      user: user,
      addTemplate: [
        CometChatMessageTemplate(
          type: MessageTypeConstants.text,
          category: MessageCategoryConstants.message,
          contentView: (message, context, alignment, {additionalConfigurations}) {
            return Text((message as TextMessage).text,
              style: TextStyle(color: Colors.red));
          },
        ),
      ],
    )
    ```
  </Tab>
</Tabs>

See [Message Template](/ui-kit/flutter/message-template) for the full template structure.

***

## Message Option Visibility

| Property                     | Default | Description              |
| ---------------------------- | ------- | ------------------------ |
| `hideCopyMessageOption`      | `false` | Hide "Copy Message"      |
| `hideDeleteMessageOption`    | `false` | Hide "Delete Message"    |
| `hideEditMessageOption`      | `false` | Hide "Edit Message"      |
| `hideMessageInfoOption`      | `false` | Hide "Message Info"      |
| `hideMessagePrivatelyOption` | `false` | Hide "Message Privately" |
| `hideReactionOption`         | `false` | Hide "Reaction"          |
| `hideReplyInThreadOption`    | `false` | Hide "Reply in Thread"   |
| `hideTranslateMessageOption` | `false` | Hide "Translate Message" |
| `hideShareMessageOption`     | `false` | Hide "Share Message"     |
| `hideModerationView`         | `null`  | Hide moderation view     |

***

## Common Patterns

### Thread replies view

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      parentMessageId: parentMessage.id,
    )
    ```
  </Tab>
</Tabs>

### Jump to a specific message

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      goToMessageId: 12345,
    )
    ```
  </Tab>
</Tabs>

### Start from unread messages

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      startFromUnreadMessages: true,
    )
    ```
  </Tab>
</Tabs>

### Load last agent conversation

Resume the most recent AI agent conversation on start:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      loadLastAgentConversation: true,
    )
    ```
  </Tab>
</Tabs>

### Flag / Report a message

Flag/report is available by default from the message long-press menu. Toggle its visibility and customize the dialog:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      // hide the Flag option entirely
      hideFlagOption: false,
      // hide the optional "Remark" text field in the flag dialog
      hideFlagRemarkField: false,
      // localize reason IDs to your own display strings
      flagReasonLocalizer: (reasonId) {
        switch (reasonId) {
          case 'spam':
            return 'Spam or unsolicited';
          case 'inappropriate':
            return 'Inappropriate content';
          default:
            return reasonId;
        }
      },
    )
    ```
  </Tab>
</Tabs>

### Mark a message as unread

Expose the "Mark as Unread" option in the long-press menu:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      showMarkAsUnreadOption: true,
    )
    ```
  </Tab>
</Tabs>

***

## Advanced

### BLoC Access

Provide a custom `MessageListBloc` to override behavior:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      messageListBloc: CustomMessageListBloc(user: user),
    )
    ```
  </Tab>
</Tabs>

### Extending MessageListBloc

`MessageListBloc` uses the `ListBase<BaseMessage>` mixin with override hooks:

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    class CustomMessageListBloc extends MessageListBloc {
      CustomMessageListBloc({required User user}) : super(user: user);

      @override
      void onItemAdded(BaseMessage item, List<BaseMessage> updatedList) {
        // Custom logic when a message is added
        super.onItemAdded(item, updatedList);
      }
    }
    ```
  </Tab>
</Tabs>

For `ListBase` override hooks (`onItemAdded`, `onItemRemoved`, `onItemUpdated`, `onListCleared`, `onListReplaced`), see [BLoC & Data — ListBase Hooks](/ui-kit/flutter/customization-bloc-data#listbase-hooks).

### Public BLoC Events

| Event                                                | Description                       |
| ---------------------------------------------------- | --------------------------------- |
| `LoadMessages(conversationWith, conversationType)`   | Load initial messages             |
| `LoadOlderMessages()`                                | Load older messages (scroll up)   |
| `LoadNewerMessages()`                                | Load newer messages (scroll down) |
| `RefreshMessages()`                                  | Refresh from the latest           |
| `SyncMessages()`                                     | Silently sync missed messages     |
| `JumpToMessage(messageId)`                           | Jump to a specific message        |
| `AddReaction(message, reaction)`                     | Add a reaction                    |
| `RemoveReaction(message, reaction)`                  | Remove a reaction                 |
| `MarkMessageAsRead(message)`                         | Mark a message as read            |
| `MarkMessageAsUnread(...)`                           | Mark a message as unread          |
| `LoadFromUnread(conversationWith, conversationType)` | Load from first unread message    |

### Public BLoC Methods

#### O(1) Lookup Methods

| Method                         | Returns        | Description                                   |
| ------------------------------ | -------------- | --------------------------------------------- |
| `findMessageIndex(messageId)`  | `int?`         | Find message index by ID                      |
| `findMessageIndexByMuid(muid)` | `int?`         | Find message index by muid (pending messages) |
| `findMessage(messageId)`       | `BaseMessage?` | Get message by ID                             |
| `findMessageByMuid(muid)`      | `BaseMessage?` | Get message by muid                           |

#### ValueNotifier Accessors (Isolated Rebuilds)

| Method                                         | Returns                                | Description                                |
| ---------------------------------------------- | -------------------------------------- | ------------------------------------------ |
| `getReceiptNotifier(messageId)`                | `ValueNotifier<MessageReceiptStatus>`  | Per-message receipt status notifier        |
| `getReceiptNotifierForMessage(message)`        | `ValueNotifier<MessageReceiptStatus>`  | Receipt notifier handling both ID and muid |
| `getTypingNotifier(conversationId)`            | `ValueNotifier<List<TypingIndicator>>` | Per-conversation typing notifier           |
| `getThreadReplyCountNotifier(parentMessageId)` | `ValueNotifier<int>`                   | Per-message thread reply count notifier    |

#### MessageReceiptStatus Enum

| Value       | Description                             |
| ----------- | --------------------------------------- |
| `sending`   | Message is being sent (id = 0)          |
| `sent`      | Message has been sent to server         |
| `delivered` | Message has been delivered to recipient |
| `read`      | Message has been read by recipient      |
| `error`     | Message failed to send                  |

### Operations Stream

The BLoC exposes an `operationsStream` consumed by `CometChatAnimatedMessageList` for smooth animations:

| Operation                                                | Description                |
| -------------------------------------------------------- | -------------------------- |
| `MessageOperation.insert(message, index)`                | Insert a single message    |
| `MessageOperation.insertAll(messages, index)`            | Insert a batch of messages |
| `MessageOperation.update(oldMessage, newMessage, index)` | Replace a message in-place |
| `MessageOperation.remove(message, index)`                | Remove a message           |
| `MessageOperation.set(messages)`                         | Replace the entire list    |

***

## Style

<Tabs>
  <Tab title="Dart">
    ```dart theme={null}
    CometChatMessageList(
      user: user,
      style: CometChatMessageListStyle(
        backgroundColor: Color(0xFFFEEDE1),
        outgoingMessageBubbleStyle: CometChatOutgoingMessageBubbleStyle(
          backgroundColor: Color(0xFFF76808),
        ),
        incomingMessageBubbleStyle: CometChatIncomingMessageBubbleStyle(
          backgroundColor: Colors.white,
        ),
      ),
    )
    ```
  </Tab>
</Tabs>

See [Component Styling](/ui-kit/flutter/component-styling) and [Message Bubble Styling](/ui-kit/flutter/message-bubble-styling) for the full reference.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Message Header" icon="heading" href="/ui-kit/flutter/message-header">
    Display user/group info in the app bar
  </Card>

  <Card title="Message Composer" icon="pen-to-square" href="/ui-kit/flutter/message-composer">
    Rich input for sending messages
  </Card>

  <Card title="Message Template" icon="puzzle-piece" href="/ui-kit/flutter/message-template">
    Customize message bubble structure
  </Card>

  <Card title="Component Styling" icon="paintbrush" href="/ui-kit/flutter/component-styling">
    Detailed styling reference
  </Card>
</CardGroup>
