class CustomChatComponentFactory : ChatComponentFactory {
@Composable
override fun ChannelItemReadStatusIndicator(
params: ChannelItemReadStatusIndicatorParams,
) {
// Do not show any status indicator
}
@Composable
override fun MessageFooterStatusIndicator(
params: MessageFooterStatusIndicatorParams,
) {
// Do not show any status indicator
}
}Message Status Indicators
For messages sent by the current user, the status indicators represent the state of the message. It is shown below the message bubble, by default.
Status indicators states
The possible states of the status indicators are:
- pending: The message is pending to be sent to the server.
- sent: The message has been sent to the server successfully. It is shown as a gray checkmark.
- delivered: The message has been delivered to at least one of the channel members devices. It is shown as double gray checkmark.
- read: The message has been read by at least one of the channel members. It is shown as double blue checkmark.
The delivered state needs to be enabled in the Dashboard for each channel type.
| Pending | Sent | Delivered | Read | Read by many |
|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
If read_events are turned OFF for the channel, read indicators are hidden.
If delivery_events are turned OFF for the channel, delivery indicators are hidden.
Basic Customization
Hide status indicators
In case your app does not need to show the status indicators,
you can hide them by overriding the MessageFooterStatusIndicator component factory method.
When hidden, no status icons appear next to your messages.
Advanced Customization
Show all read and delivered members
To show all the read and delivered members, you can create a custom screen that shows the members that have read the message and the ones that were delivered but not read yet.
For this, we can extend the message menu to add a message info option to show a screen with the read and delivered members.
class CustomChatComponentFactory(
private val delegate: ChatComponentFactory = object : ChatComponentFactory {},
) : ChatComponentFactory by delegate {
/**
* Creates a message menu with an additional option for message info.
*/
@Composable
override fun MessageMenu(params: MessageMenuParams) {
var showMessageInfoDialog by remember { mutableStateOf(false) }
val allOptions = listOf(
MessageOptionItemState(
title = R.string.message_option_message_info,
titleColor = ChatTheme.colors.textPrimary,
iconPainter = rememberVectorPainter(Icons.Outlined.Info),
iconColor = ChatTheme.colors.textSecondary,
action = CustomAction(params.message, mapOf("message_info" to true)),
),
) + params.messageOptions
val extendedOnMessageAction: (MessageAction) -> Unit = { action ->
when {
action is CustomAction && action.extraProperties.contains("message_info") ->
showMessageInfoDialog = true
else -> params.onMessageAction(action)
}
}
var dismissed by remember { mutableStateOf(false) }
if (showMessageInfoDialog) {
ModalBottomSheet(
onDismissRequest = {
showMessageInfoDialog = false
params.onDismiss()
dismissed = true
},
containerColor = ChatTheme.colors.backgroundCoreApp,
) {
// Show read/delivered members for the message
// Use your own implementation to fetch and display read receipts
}
} else if (!dismissed) {
delegate.MessageMenu(
params = params.copy(
messageOptions = allOptions,
onMessageAction = extendedOnMessageAction,
),
)
}
}
}At the moment, showing the timestamps of the read and delivered members is not recommended since the timestamp is always related to the latest message in the channel, and not for each message individually.




