Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
cometchat avatar

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-customization

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs5
repo stars70
Last updatedJune 23, 2026
Repositorycometchat/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

SKILL.mdMarkdownGitHub ↗
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:

MethodSlotParameters
getContentView()Main contentmessage, alignment, style, textFormatters
getLeadingView()Avatarmessage, alignment, style
getHeaderView()Sender namemessage, alignment, style, showTime
getReplyView()Reply previewmessage, alignment, style
getBottomView()Moderationmessage, alignment, style, hideModerationView
getStatusInfoView()Timestamp/receiptsmessage, alignment, style, showTime
getThreadView()Thread indicatormessage, alignment, style, onThreadRepliesClick
getFooterView()Reactionsmessage, 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

ParameterTypeSlot
leadingView@Composable (BaseMessage, MessageAlignment) -> UnitAvatar
headerView@Composable (BaseMessage, MessageAlignment) -> UnitSender name
replyView@Composable (BaseMessage, MessageAlignment) -> UnitReply preview
contentView@Composable (BaseMessage, MessageAlignment) -> UnitMain content
bottomView@Composable (BaseMessage, MessageAlignment) -> UnitModeration
statusInfoView@Composable (BaseMessage, MessageAlignment) -> UnitTimestamp/receipts
threadView@Composable (BaseMessage, MessageAlignment) -> UnitThread indicator
footerView@Composable (BaseMessage, MessageAlignment) -> UnitReactions

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 Patternv6 Pattern
ChatConfigurator.enable(decorator)CometChatMessageList(bubbleFactories = listOf(...))
DataSource template methodsBubbleFactory slot methods
Global decorator chainPer-component factory registration
No bubble replacementgetBubbleView() for complete replacement
Theme-level styling onlyPer-factory getBubbleStyle()

Hard rules

  • BubbleFactory is an interface — implement it, don't extend an abstract class
  • getCategory() and getType() 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 CometChatMessageList override 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

Related skills

Mobile Developmentfrontendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.