Skip to main content
CometChatConversations renders a scrollable list of recent conversations with real-time updates for new messages, typing indicators, read receipts, and user presence.

Where It Fits

CometChatConversations is a list component. It renders recent conversations and emits the selected Conversation via onItemTap. Wire it to CometChatMessageHeader, CometChatMessageList, and CometChatMessageComposer to build a standard chat layout.
CometChatConversations(
  onItemTap: (conversation) {
    final entity = conversation.conversationWith;
    if (entity is User) {
      navigateToUserChat(entity);
    } else if (entity is Group) {
      navigateToGroupChat(entity);
    }
  },
)

Quick Start

Using Navigator:
Navigator.push(context, MaterialPageRoute(builder: (context) => const CometChatConversations()));
Embedding as a widget:
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: CometChatConversations(),
    ),
  );
}
Prerequisites: CometChat SDK initialized with CometChatUIKit.init(), a user logged in, and the UI Kit dependency added.

Filtering Conversations

Pass a ConversationsRequestBuilder to control what loads:
CometChatConversations(
  conversationsRequestBuilder: ConversationsRequestBuilder()
    ..conversationType = "user"
    ..limit = 10,
)

Filter Recipes

RecipeBuilder property
Only user conversations..conversationType = "user"
Only group conversations..conversationType = "group"
Limit per page..limit = 10
With tags..tags = ["vip"] and ..withTags = true
With user and group tags..withUserAndGroupTags = true

Actions and Events

Callback Methods

onItemTap

Fires when a conversation row is tapped. Primary navigation hook.
CometChatConversations(
  onItemTap: (conversation) {
    // Navigate to chat screen
  },
)

onItemLongPress

Fires when a conversation row is long-pressed. By default shows a delete overlay (when deleteConversationOptionVisibility is true).
CometChatConversations(
  onItemLongPress: (conversation) {
    // Custom long press behavior
  },
)

onBack

Fires when the user presses the back button in the app bar.
CometChatConversations(
  onBack: () {
    Navigator.pop(context);
  },
)

onSelection

Fires when conversations are selected/deselected in multi-select mode.
CometChatConversations(
  selectionMode: SelectionMode.multiple,
  onSelection: (selectedConversations) {
    // Handle selected conversations
  },
)

onError

Fires on internal errors (network failure, auth issue, SDK exception).
CometChatConversations(
  onError: (e) {
    debugPrint("Error: ${e.message}");
  },
)

onLoad

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

onEmpty

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

Global Events

The component emits events via CometChatConversationEvents that can be subscribed to from anywhere:
class _YourScreenState extends State<YourScreen> with CometChatConversationEventListener {

  @override
  void initState() {
    super.initState();
    CometChatConversationEvents.addConversationListListener("listenerId", this);
  }

  @override
  void dispose() {
    CometChatConversationEvents.removeConversationListListener("listenerId");
    super.dispose();
  }

  @override
  void ccConversationDeleted(Conversation conversation) {
    // Handle conversation deleted
  }
}

SDK Events (Real-Time, Automatic)

The component listens to these SDK events internally. No manual setup needed.
SDK ListenerInternal behavior
onTextMessageReceived / onMediaMessageReceived / onCustomMessageReceivedMoves conversation to top, updates last message and unread count
onTypingStarted / onTypingEndedShows/hides typing indicator in subtitle
onMessagesDelivered / onMessagesReadUpdates receipt indicators
onUserOnline / onUserOfflineUpdates presence status dot
onGroupMemberJoined / onGroupMemberLeft / onGroupMemberKicked / onGroupMemberBannedUpdates group conversation metadata
Connection reconnectedTriggers silent refresh to sync missed messages

Functionality

PropertyTypeDefaultDescription
titleString?nullCustom app bar title
showBackButtonboolfalseToggle back button
hideAppbarbool?falseToggle app bar visibility
hideSearchbool?nullToggle search bar
searchReadOnlyboolfalseMake search bar read-only (tap opens custom search)
deleteConversationOptionVisibilitybool?trueShow delete option on long press
groupTypeVisibilitybool?trueShow group type icon on avatar
usersStatusVisibilitybool?trueShow online/offline status indicator
receiptsVisibilitybool?trueShow message receipts
disableSoundForMessagesboolfalseDisable message sounds
customSoundForMessagesString?nullCustom notification sound asset path
selectionModeSelectionMode?nullEnable selection mode (single or multiple)

Custom View Slots

Leading View

Replace the avatar / left section.
CometChatConversations(
  leadingView: (context, conversation) {
    return CircleAvatar(
      child: Text(conversation.conversationWith?.name?[0] ?? ""),
    );
  },
)

Title View

Replace the name / title text.
CometChatConversations(
  titleView: (context, conversation) {
    return Text(
      conversation.conversationWith?.name ?? "",
      style: TextStyle(fontWeight: FontWeight.bold),
    );
  },
)

Subtitle View

Replace the last message preview.
CometChatConversations(
  subtitleView: (context, conversation) {
    final msg = conversation.lastMessage;
    if (msg is TextMessage) {
      return Text(msg.text, maxLines: 1, overflow: TextOverflow.ellipsis);
    }
    return Text("New conversation");
  },
)

Trailing View

Replace the timestamp / badge / right section.
CometChatConversations(
  trailingView: (conversation) {
    if (conversation.unreadMessageCount > 0) {
      return Badge(label: Text("${conversation.unreadMessageCount}"));
    }
    return null;
  },
)

List Item View

Replace the entire list item row.
CometChatConversations(
  listItemView: (conversation) {
    return ListTile(
      leading: CircleAvatar(child: Text(conversation.conversationWith?.name?[0] ?? "")),
      title: Text(conversation.conversationWith?.name ?? ""),
      subtitle: Text("Custom item"),
    );
  },
)

State Views

CometChatConversations(
  emptyStateView: (context) => Center(child: Text("No conversations yet")),
  errorStateView: (context) => Center(child: Text("Something went wrong")),
  loadingStateView: (context) => Center(child: CircularProgressIndicator()),
)

// Replace all options
CometChatConversations(
  setOptions: (conversation, bloc, context) {
    return [
      CometChatOption(
        id: "delete",
        icon: AssetConstants.delete,
        title: "Delete",
        onClick: () {
          bloc.add(DeleteConversation(conversation.conversationId!));
        },
      ),
    ];
  },
)

// Append to defaults
CometChatConversations(
  addOptions: (conversation, bloc, context) {
    return [
      CometChatOption(
        id: "archive",
        iconWidget: Icon(Icons.archive_outlined),
        title: "Archive",
        onClick: () {
          // Archive conversation
        },
      ),
    ];
  },
)

Common Patterns

Minimal list — hide all chrome

CometChatConversations(
  hideAppbar: true,
  hideSearch: true,
)

Users-only conversations

CometChatConversations(
  conversationsRequestBuilder: ConversationsRequestBuilder()
    ..conversationType = "user",
)

Custom date formatting

CometChatConversations(
  datePattern: (conversation) {
    final timestamp = conversation.updatedAt;
    return DateFormat('MMM d').format(DateTime.fromMillisecondsSinceEpoch(timestamp! * 1000));
  },
)

Advanced

BLoC Access

Provide a custom ConversationsBloc to override behavior:
CometChatConversations(
  conversationsBloc: CustomConversationsBloc(),
)

Extending ConversationsBloc

ConversationsBloc uses the ListBase<Conversation> mixin with override hooks for custom list behavior:
class CustomConversationsBloc extends ConversationsBloc {
  @override
  void onItemAdded(Conversation item, List<Conversation> updatedList) {
    // Custom sorting — pinned conversations first
    final sorted = _sortWithPinnedFirst(updatedList);
    super.onItemAdded(item, sorted);
  }

  @override
  void onListReplaced(List<Conversation> previousList, List<Conversation> newList) {
    // Filter out blocked users on every list refresh
    final filtered = newList.where((c) => !isBlocked(c)).toList();
    super.onListReplaced(previousList, filtered);
  }
}
For ListBase override hooks (onItemAdded, onItemRemoved, onItemUpdated, onListCleared, onListReplaced), see BLoC & Data — ListBase Hooks.

Public BLoC Events

EventDescription
LoadConversations({silent})Load initial conversations. silent: true keeps existing list visible during refresh.
LoadMoreConversations()Load next page (pagination)
RefreshConversations()Refresh the list
DeleteConversation(conversationId)Delete via SDK and remove from list
RemoveConversation(conversationId)Remove from list without SDK call
SetActiveConversation(conversationId)Mark as active (suppresses unread count)
UpdateConversation(conversationId, updatedConversation)Update with modified data
ResetUnreadCount(conversationId)Reset unread count to 0

Public BLoC Methods

MethodReturnsDescription
getTypingNotifier(conversationId)ValueNotifier<List<TypingIndicator>>Per-conversation typing notifier for isolated rebuilds
getTypingIndicators(conversationId)List<TypingIndicator>Current typing indicators for a conversation

Route Observer

Pass a RouteObserver to freeze rebuilds when another screen is pushed on top (prevents expensive rebuilds during keyboard animation):
// In your app
final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();

MaterialApp(
  navigatorObservers: [routeObserver],
)

// Pass to conversations
CometChatConversations(
  routeObserver: routeObserver,
)

Style

CometChatConversations(
  conversationsStyle: CometChatConversationsStyle(
    backgroundColor: Colors.white,
    avatarStyle: CometChatAvatarStyle(
      borderRadius: BorderRadius.circular(8),
      backgroundColor: Color(0xFFFBAA75),
    ),
    badgeStyle: CometChatBadgeStyle(
      backgroundColor: Color(0xFFF76808),
    ),
    receiptStyle: CometChatMessageReceiptStyle(),
    typingIndicatorStyle: CometChatTypingIndicatorStyle(),
    dateStyle: CometChatDateStyle(),
    mentionsStyle: CometChatMentionsStyle(),
    deleteConversationDialogStyle: CometChatConfirmDialogStyle(),
  ),
)

Style Properties

PropertyDescription
backgroundColorList background color
avatarStyleAvatar appearance
badgeStyleUnread badge appearance
receiptStyleRead receipt icons
typingIndicatorStyleTyping indicator text
dateStyleTimestamp appearance
mentionsStyleMention highlight style
deleteConversationDialogStyleDelete confirmation dialog
See Component Styling for the full reference.

Next Steps

Users

Browse and search available users

Message List

Display messages for a conversation

Component Styling

Detailed styling reference

Message Template

Customize message bubble structure