Skip to main content
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.
CometChatMessageList(
  user: user,
)

Quick Start

Using Navigator:
Navigator.push(context, MaterialPageRoute(builder: (context) => CometChatMessageList(user: user)));
Embedding as a widget:
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: CometChatMessageList(
        user: user, // or group: group
      ),
    ),
  );
}
Prerequisites: CometChat SDK initialized with CometChatUIKit.init(), a user logged in, and the UI Kit dependency added.
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.

Filtering

Pass a MessagesRequestBuilder to control what loads:
CometChatMessageList(
  user: user,
  messagesRequestBuilder: MessagesRequestBuilder()
    ..uid = user.uid
    ..searchKeyword = "hello"
    ..limit = 30,
)
The following parameters in MessagesRequestBuilder will always be altered inside the message list: UID, GUID, types, categories.

Actions and Events

Callback Methods

onThreadRepliesClick

Fires when a user taps a threaded message bubble.
CometChatMessageList(
  user: user,
  onThreadRepliesClick: (message, context, {template}) {
    // Navigate to thread view
  },
)

onError

Fires on internal errors.
CometChatMessageList(
  user: user,
  onError: (e) {
    debugPrint("Error: ${e.message}");
  },
)

onLoad

Fires when the list is successfully fetched and loaded.
CometChatMessageList(
  user: user,
  onLoad: (messages) {
    debugPrint("Loaded ${messages.length}");
  },
)

onEmpty

Fires when the list is empty after loading.
CometChatMessageList(
  user: user,
  onEmpty: () {
    debugPrint("No messages");
  },
)

onReactionClick

Fires when a reaction pill is tapped.
CometChatMessageList(
  user: user,
  onReactionClick: (emoji, message) {
    // Handle reaction click
  },
)

onReactionLongPress

Fires when a reaction pill is long-pressed.
CometChatMessageList(
  user: user,
  onReactionLongPress: (emoji, message) {
    // Handle reaction long press
  },
)

SDK Events (Real-Time, Automatic)

The component listens to SDK message events internally. No manual setup needed.
SDK ListenerInternal behavior
onTextMessageReceived / onMediaMessageReceived / onCustomMessageReceivedInserts new message with animation
onMessageEditedUpdates message in-place
onMessageDeletedRemoves or marks message as deleted
onMessagesDelivered / onMessagesReadUpdates receipt status via ValueNotifier
onTypingStarted / onTypingEndedUpdates typing indicator
onMessageReactionAdded / onMessageReactionRemovedUpdates reaction counts
Connection reconnectedTriggers silent sync to fetch missed messages

Functionality

PropertyTypeDefaultDescription
userUser?required*User for 1-on-1 conversation
groupGroup?required*Group for group conversation
parentMessageIdint?nullParent message ID for thread replies
alignmentChatAlignmentstandardChat alignment setting
hideDeletedMessagesboolfalseHide deleted messages entirely
disableReceiptsboolfalseDisable read/delivery receipts
disableSoundForMessagesboolfalseDisable message sounds
hideRepliesbooltrueHide thread replies in main conversation
hideGroupActionMessagesbool?falseHide group action messages
hideTimestampbool?nullToggle timestamp visibility
hideDateSeparatorbool?falseHide date separators
hideStickyDatebool?falseHide floating sticky date header
avatarVisibilitybool?trueToggle avatar visibility
receiptsVisibilitybool?trueToggle read receipts
disableReactionsbool?falseToggle reactions
enableSwipeToReplybooltrueEnable swipe-to-reply gesture
startFromUnreadMessagesboolfalseScroll to first unread on open
showMarkAsUnreadOptionboolfalseShow “Mark as Unread” in long-press options
goToMessageIdint?nullScroll to a specific message after load
* One of user or group is required.

Custom View Slots

Header View

Custom view displayed at the top of the message list.
CometChatMessageList(
  user: user,
  headerView: (context, {user, group, parentMessageId}) {
    return Container(
      padding: EdgeInsets.all(8),
      child: Text("Pinned Messages"),
    );
  },
)
Custom view displayed at the bottom of the message list.
CometChatMessageList(
  user: user,
  footerView: (context, {user, group, parentMessageId}) {
    return Container(
      padding: EdgeInsets.all(8),
      child: Text("End of messages"),
    );
  },
)

State Views

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!")),
)

Text Formatters (Mentions)

CometChatMessageList(
  user: user,
  textFormatters: [
    CometChatMentionsFormatter(),
  ],
)

Message Templates

Override or extend message bubble rendering:
// 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));
      },
    ),
  ],
)
See Message Template for the full template structure.

Message Option Visibility

PropertyDefaultDescription
hideCopyMessageOptionfalseHide “Copy Message”
hideDeleteMessageOptionfalseHide “Delete Message”
hideEditMessageOptionfalseHide “Edit Message”
hideMessageInfoOptionfalseHide “Message Info”
hideMessagePrivatelyOptionfalseHide “Message Privately”
hideReactionOptionfalseHide “Reaction”
hideReplyInThreadOptionfalseHide “Reply in Thread”
hideTranslateMessageOptionfalseHide “Translate Message”
hideShareMessageOptionfalseHide “Share Message”
hideModerationViewnullHide moderation view

Common Patterns

Thread replies view

CometChatMessageList(
  user: user,
  parentMessageId: parentMessage.id,
)

Jump to a specific message

CometChatMessageList(
  user: user,
  goToMessageId: 12345,
)

Start from unread messages

CometChatMessageList(
  user: user,
  startFromUnreadMessages: true,
)

Advanced

BLoC Access

Provide a custom MessageListBloc to override behavior:
CometChatMessageList(
  user: user,
  messageListBloc: CustomMessageListBloc(user: user),
)

Extending MessageListBloc

MessageListBloc uses the ListBase<BaseMessage> mixin with override hooks:
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);
  }
}
For ListBase override hooks (onItemAdded, onItemRemoved, onItemUpdated, onListCleared, onListReplaced), see BLoC & Data — ListBase Hooks.

Public BLoC Events

EventDescription
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

MethodReturnsDescription
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)

MethodReturnsDescription
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

ValueDescription
sendingMessage is being sent (id = 0)
sentMessage has been sent to server
deliveredMessage has been delivered to recipient
readMessage has been read by recipient
errorMessage failed to send

Operations Stream

The BLoC exposes an operationsStream consumed by CometChatAnimatedMessageList for smooth animations:
OperationDescription
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

CometChatMessageList(
  user: user,
  style: CometChatMessageListStyle(
    backgroundColor: Color(0xFFFEEDE1),
    outgoingMessageBubbleStyle: CometChatOutgoingMessageBubbleStyle(
      backgroundColor: Color(0xFFF76808),
    ),
    incomingMessageBubbleStyle: CometChatIncomingMessageBubbleStyle(
      backgroundColor: Colors.white,
    ),
  ),
)
See Component Styling and Message Bubble Styling for the full reference.

Next Steps

Message Header

Display user/group info in the app bar

Message Composer

Rich input for sending messages

Message Template

Customize message bubble structure

Component Styling

Detailed styling reference