Kotlin SharedFlow with sealed class event types — collect in viewModelScope or lifecycleScope
Purpose
Decoupled communication between UI Kit components — subscribe to event flows to react to changes without direct component references
Events enable a decoupled, flexible architecture in the CometChat UI Kit. Components emit events via the CometChatEvents singleton, and other parts of your application collect these SharedFlow streams to react without direct references between components.
All events are accessed through the CometChatEvents singleton in chatuikit-core. Each domain has a dedicated SharedFlow that emits sealed class event types:
CometChatEvents.messageEvents emits MessageEvent sealed class instances when messages are sent, edited, deleted, or read.Event types:
Event
Description
MessageEvent.Sent(message, status)
Triggered when a message is sent. Status can be inProgress or sent.
MessageEvent.Edited(message, status)
Triggered when a message is edited. Status can be inProgress or sent.
MessageEvent.Deleted(message)
Triggered when a message is deleted.
MessageEvent.Read(message)
Triggered when a message is read.
MessageEvent.LiveReaction(icon)
Triggered when a live reaction is sent.
MessageEvent.FormReceived(message)
Triggered when a form message is received.
MessageEvent.CardReceived(message)
Triggered when a card message is received.
MessageEvent.CustomInteractiveReceived(message)
Triggered when a custom interactive message is received.
MessageEvent.InteractionGoalCompleted(message)
Triggered when an interaction goal is completed.
MessageEvent.SchedulerReceived(message)
Triggered when a scheduler message is received.
Collecting events:
Kotlin (XML Views)
Jetpack Compose
// In an Activity or Fragment — use lifecycleScopelifecycleScope.launch { CometChatEvents.messageEvents.collect { event -> when (event) { is MessageEvent.Sent -> { val message = event.message val status = event.status // Update UI when message is sent } is MessageEvent.Edited -> { val message = event.message // Update UI when message is edited } is MessageEvent.Deleted -> { val message = event.message // Remove message from UI } is MessageEvent.Read -> { val message = event.message // Update read receipts } is MessageEvent.LiveReaction -> { val icon = event.icon // Show live reaction animation } is MessageEvent.FormReceived -> { /* Handle form message */ } is MessageEvent.CardReceived -> { /* Handle card message */ } is MessageEvent.CustomInteractiveReceived -> { /* Handle custom interactive */ } is MessageEvent.InteractionGoalCompleted -> { /* Handle goal completion */ } is MessageEvent.SchedulerReceived -> { /* Handle scheduler message */ } } }}
@Composablefun MessageEventsHandler() { LaunchedEffect(Unit) { CometChatEvents.messageEvents.collect { event -> when (event) { is MessageEvent.Sent -> { val message = event.message val status = event.status // Update UI when message is sent } is MessageEvent.Edited -> { val message = event.message // Update UI when message is edited } is MessageEvent.Deleted -> { val message = event.message // Remove message from UI } is MessageEvent.Read -> { val message = event.message // Update read receipts } is MessageEvent.LiveReaction -> { val icon = event.icon // Show live reaction animation } is MessageEvent.FormReceived -> { /* Handle form message */ } is MessageEvent.CardReceived -> { /* Handle card message */ } is MessageEvent.CustomInteractiveReceived -> { /* Handle custom interactive */ } is MessageEvent.InteractionGoalCompleted -> { /* Handle goal completion */ } is MessageEvent.SchedulerReceived -> { /* Handle scheduler message */ } } } }}
What this does: Collects the messageEvents SharedFlow and pattern-matches on the sealed class to handle each message lifecycle event.
lifecycleScope.launch { CometChatEvents.groupEvents.collect { event -> when (event) { is GroupEvent.Created -> { val group = event.group // Add new group to UI } is GroupEvent.Deleted -> { val group = event.group // Remove group from UI } is GroupEvent.Left -> { val leftUser = event.leftUser val leftGroup = event.leftGroup // Handle user leaving group } is GroupEvent.MemberScopeChanged -> { val updatedUser = event.updatedUser val newScope = event.scopeChangedTo // Update member scope in UI } is GroupEvent.MemberBanned -> { val bannedUser = event.bannedUser // Remove banned user from member list } is GroupEvent.MemberKicked -> { val kickedUser = event.kickedUser // Remove kicked user from member list } is GroupEvent.MemberUnBanned -> { val unbannedUser = event.unbannedUser // Handle unbanned user } is GroupEvent.MemberJoined -> { val joinedUser = event.joinedUser // Add user to member list } is GroupEvent.MemberAdded -> { val usersAdded = event.usersAdded // Add users to member list } is GroupEvent.OwnershipChanged -> { val newOwner = event.newOwner // Update group owner in UI } } }}
@Composablefun GroupEventsHandler() { LaunchedEffect(Unit) { CometChatEvents.groupEvents.collect { event -> when (event) { is GroupEvent.Created -> { /* Add new group to UI */ } is GroupEvent.Deleted -> { /* Remove group from UI */ } is GroupEvent.Left -> { /* Handle user leaving group */ } is GroupEvent.MemberScopeChanged -> { /* Update member scope */ } is GroupEvent.MemberBanned -> { /* Remove banned user */ } is GroupEvent.MemberKicked -> { /* Remove kicked user */ } is GroupEvent.MemberUnBanned -> { /* Handle unbanned user */ } is GroupEvent.MemberJoined -> { /* Add user to member list */ } is GroupEvent.MemberAdded -> { /* Add users to member list */ } is GroupEvent.OwnershipChanged -> { /* Update group owner */ } } } }}
CometChatEvents.userEvents emits UserEvent sealed class instances when the logged-in user blocks or unblocks another user.Event types:
Event
Description
UserEvent.Blocked(user)
Triggered when the logged-in user blocks another user.
UserEvent.Unblocked(user)
Triggered when the logged-in user unblocks another user.
Collecting events:
Kotlin (XML Views)
Jetpack Compose
lifecycleScope.launch { CometChatEvents.userEvents.collect { event -> when (event) { is UserEvent.Blocked -> { val user = event.user // Update UI to reflect blocked user } is UserEvent.Unblocked -> { val user = event.user // Update UI to reflect unblocked user } } }}
@Composablefun UserEventsHandler() { LaunchedEffect(Unit) { CometChatEvents.userEvents.collect { event -> when (event) { is UserEvent.Blocked -> { // Update UI to reflect blocked user } is UserEvent.Unblocked -> { // Update UI to reflect unblocked user } } } }}
Triggered to open a chat with a specific user or group.
Collecting events:
Kotlin (XML Views)
Jetpack Compose
lifecycleScope.launch { CometChatEvents.uiEvents.collect { event -> when (event) { is UIEvent.ShowPanel -> { val alignment = event.alignment // Show custom UI panel } is UIEvent.HidePanel -> { val alignment = event.alignment // Hide custom UI panel } is UIEvent.ActiveChatChanged -> { val user = event.user val group = event.group // React to active chat change } is UIEvent.OpenChat -> { val user = event.user val group = event.group // Navigate to chat with user or group } } }}
@Composablefun UIEventsHandler() { LaunchedEffect(Unit) { CometChatEvents.uiEvents.collect { event -> when (event) { is UIEvent.ShowPanel -> { /* Show custom UI panel */ } is UIEvent.HidePanel -> { /* Hide custom UI panel */ } is UIEvent.ActiveChatChanged -> { /* React to active chat change */ } is UIEvent.OpenChat -> { /* Navigate to chat */ } } } }}