
Cometchat Android V6 Compose Customization
- 5 installs
- 70 repo stars
- Updated June 23, 2026
- cometchat/cometchat-skills
Customizes CometChat v6 Compose components via the BubbleFactory interface, slot lambdas, and @Immutable style classes for per-slot overrides.
About
This skill covers customizing CometChat v6 Compose components by overriding bubble rendering with BubbleFactory, using slot lambda parameters, and applying @Immutable style classes. A developer uses it to render custom message bubbles or override individual bubble slots in Compose.
- BubbleFactory interface and slot lambda per-slot overrides
- @Immutable style classes replacing v5's DataSource/ChatConfigurator pattern
Cometchat Android V6 Compose Customization by the numbers
- 5 all-time installs (skills.sh)
- Ranked #828 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cometchat/cometchat-skills --skill cometchat-android-v6-compose-customizationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 70 |
| Last updated | June 23, 2026 |
| Repository | cometchat/cometchat-skills ↗ |
What it does
Customizes CometChat v6 Compose components via the BubbleFactory interface, slot lambdas, and @Immutable style classes for per-slot overrides.
Files
Companion skills: cometchat-android-v6-kotlin-customization (Views equivalent), cometchat-android-v6-compose-components, cometchat-android-v6-compose-theming, cometchat-android-v6-extensions (DataSource layer), cometchat-android-v6-events
Purpose
Customize CometChat Compose components — override message bubble rendering with BubbleFactory, use slot lambda parameters for per-slot overrides, and apply @Immutable style classes. This is the v6 replacement for v5's DataSource/ChatConfigurator pattern.
Use this skill when
- Creating custom message bubble rendering for specific message types
- Overriding individual bubble slots (avatar, header, footer, content, etc.)
- Applying custom styles to components
- Replacing the entire bubble layout for a message type
Do not use this skill when
- Working with Kotlin Views customization (use
cometchat-android-v6-kotlin-customization) - Changing theme colors globally (use
cometchat-android-v6-compose-theming) - Extending the data layer (use
cometchat-android-v6-extensions)
1. BubbleFactory (Message Bubble Customization)
BubbleFactory is an interface in com.cometchat.uikit.compose.presentation.shared.messagebubble. Each implementation handles a specific message type.
1.1 Creating a Custom BubbleFactory
import com.cometchat.uikit.compose.presentation.shared.messagebubble.BubbleFactory
import com.cometchat.chat.constants.CometChatConstants
import com.cometchat.chat.models.BaseMessage
import com.cometchat.uikit.core.constants.UIKitConstants.MessageBubbleAlignment
class LocationBubbleFactory : BubbleFactory {
override fun getCategory(): String = CometChatConstants.CATEGORY_CUSTOM
override fun getType(): String = "location"
override fun getContentView(
message: BaseMessage,
alignment: MessageBubbleAlignment,
style: CometChatMessageBubbleStyle,
textFormatters: List<CometChatTextFormatter>
): @Composable () -> Unit = {
// Your custom content composable
val metadata = message.metadata
val lat = metadata?.optDouble("latitude") ?: 0.0
val lng = metadata?.optDouble("longitude") ?: 0.0
LocationMapView(latitude = lat, longitude = lng)
}
}1.2 Registering BubbleFactories
CometChatMessageList(
user = user,
bubbleFactories = listOf(
LocationBubbleFactory(),
PaymentBubbleFactory()
)
)The list is converted to a map keyed by "category_type" internally via toFactoryMap().
1.3 Complete Bubble Replacement
Override getBubbleView() to replace the ENTIRE bubble (all slots):
class CustomBubbleFactory : BubbleFactory {
override fun getCategory(): String = "custom"
override fun getType(): String = "payment"
override fun getBubbleView(
message: BaseMessage,
alignment: MessageBubbleAlignment
): (@Composable () -> Unit)? = {
// Complete custom bubble — no header, footer, avatar, etc.
PaymentCard(message = message, alignment = alignment)
}
}When getBubbleView() returns non-null, all other slot methods are ignored.
1.4 Slot Methods
All return (@Composable () -> Unit)? — return null to use defaults:
| Method | Slot | Parameters |
|---|---|---|
getContentView() | Main content | message, alignment, style, textFormatters |
getLeadingView() | Avatar | message, alignment, style |
getHeaderView() | Sender name | message, alignment, style, showTime |
getReplyView() | Reply preview | message, alignment, style |
getBottomView() | Moderation | message, alignment, style, hideModerationView |
getStatusInfoView() | Timestamp/receipts | message, alignment, style, showTime |
getThreadView() | Thread indicator | message, alignment, style, onThreadRepliesClick |
getFooterView() | Reactions | message, alignment, style, onReactionClick, onReactionLongClick, onAddMoreReactionsClick |
1.5 Style Override
override fun getBubbleStyle(
message: BaseMessage,
alignment: MessageBubbleAlignment
): CometChatMessageBubbleStyle? {
return CometChatMessageBubbleStyle(
backgroundColor = Color(0xFFE8F5E9),
cornerRadius = 16.dp
)
}Factory style is the highest priority in the 3-tier style chain.
1.6 Lifecycle
override fun onDispose(message: BaseMessage) {
// Clean up resources when bubble leaves composition
}2. Slot Lambda Parameters (Per-Slot Overrides)
Override individual slots across ALL message types directly on CometChatMessageList:
CometChatMessageList(
user = user,
// Custom avatar for all messages
leadingView = { message, alignment ->
if (alignment == MessageAlignment.LEFT) {
AsyncImage(
model = message.sender?.avatar,
contentDescription = null,
modifier = Modifier.size(32.dp).clip(CircleShape)
)
}
},
// Custom timestamp for all messages
statusInfoView = { message, alignment ->
Text(
text = formatTime(message.sentAt),
style = CometChatTheme.typography.caption1Regular,
color = CometChatTheme.colorScheme.textColorTertiary
)
},
// Custom footer for all messages
footerView = { message, alignment ->
// Custom reactions display
ReactionsRow(message = message)
}
)2.1 All Slot Parameters
| Parameter | Type | Slot |
|---|---|---|
leadingView | @Composable (BaseMessage, MessageAlignment) -> Unit | Avatar |
headerView | @Composable (BaseMessage, MessageAlignment) -> Unit | Sender name |
replyView | @Composable (BaseMessage, MessageAlignment) -> Unit | Reply preview |
contentView | @Composable (BaseMessage, MessageAlignment) -> Unit | Main content |
bottomView | @Composable (BaseMessage, MessageAlignment) -> Unit | Moderation |
statusInfoView | @Composable (BaseMessage, MessageAlignment) -> Unit | Timestamp/receipts |
threadView | @Composable (BaseMessage, MessageAlignment) -> Unit | Thread indicator |
footerView | @Composable (BaseMessage, MessageAlignment) -> Unit | Reactions |
2.2 Priority Order
For each slot, the resolution order is: 1. Explicit slot lambda parameter (highest priority) 2. BubbleFactory slot method 3. Internal default rendering
3. Style Classes
3.1 Using Style Classes
CometChatConversations(
style = CometChatConversationsStyle.default(
backgroundColor = Color(0xFFF5F5F5),
titleTextColor = Color.Black,
titleTextStyle = CometChatTheme.typography.heading1Bold,
separatorColor = Color.LightGray,
itemStyle = CometChatConversationListItemStyle.default(
titleTextColor = Color.DarkGray
)
)
)3.2 Style Class Pattern
All style classes follow this pattern:
@Immutable
data class CometChatConversationsStyle(
val backgroundColor: Color,
val titleTextColor: Color,
val titleTextStyle: TextStyle,
// ... many properties
) {
companion object {
@Composable
fun default(
backgroundColor: Color = CometChatTheme.colorScheme.backgroundColor1,
titleTextColor: Color = CometChatTheme.colorScheme.textColorPrimary,
// ... defaults from CometChatTheme
): CometChatConversationsStyle = CometChatConversationsStyle(/* ... */)
}
}Use Companion.default() with named parameter overrides — never call the data class constructor directly.
3.3 Nested Styles
Some styles contain nested style classes:
CometChatConversationsStyle.default(
itemStyle = CometChatConversationListItemStyle.default(/* ... */),
popupMenuStyle = CometChatPopupMenuStyle.default(/* ... */),
emptyStateStyle = CometChatEmptyStateStyle.default(/* ... */),
errorStateStyle = CometChatErrorStateStyle.default(/* ... */),
loadingStateStyle = CometChatLoadingStateStyle.default(/* ... */),
dialogStyle = CometChatDialogStyle.default(/* ... */)
)4. Custom State Views
CometChatMessageList(
user = user,
loadingView = { CircularProgressIndicator() },
emptyView = { Text("No messages yet") },
errorView = { Text("Something went wrong") }
)5. v5 → v6 Migration
| v5 Pattern | v6 Pattern |
|---|---|
ChatConfigurator.enable(decorator) | CometChatMessageList(bubbleFactories = listOf(...)) |
| DataSource template methods | BubbleFactory slot methods |
| Global decorator chain | Per-component factory registration |
| No bubble replacement | getBubbleView() for complete replacement |
| Theme-level styling only | Per-factory getBubbleStyle() |
Hard rules
- BubbleFactory is an
interface— implement it, don't extend an abstract class getCategory()andgetType()are REQUIRED — they identify which message type the factory handles- When
getBubbleView()returns non-null, ALL other slot methods are ignored for that message type - Slot lambda parameters on
CometChatMessageListoverride BubbleFactory slot methods — use lambdas for cross-type overrides, factories for per-type overrides - Style classes must use
Companion.default()factory — the data class constructor requires ALL parameters - Do NOT confuse BubbleFactory (UI rendering) with DataSource (data fetching) — they are separate layers