diff --git a/.gitignore b/.gitignore index 96adadbc8..ad4a26a0c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ .DS_Store .kiro/ + +# IDE files +.idea/ + +# Python caches +__pycache__/ +*.pyc +/codebase +/doc-auditor diff --git a/.mintignore b/.mintignore new file mode 100644 index 000000000..a2bfd86bc --- /dev/null +++ b/.mintignore @@ -0,0 +1,2 @@ +.kiro/ +/codebase \ No newline at end of file diff --git a/docs.json b/docs.json index 9b489faf5..18f182972 100644 --- a/docs.json +++ b/docs.json @@ -549,6 +549,7 @@ "ui-kit/react/property-changes" ] }, + "ui-kit/react/troubleshooting", "ui-kit/react/link/sample", "ui-kit/react/link/changelog", "ui-kit/react/link/figma" @@ -1550,6 +1551,21 @@ "ui-kit/android/sound-manager" ] }, + { + "group": "Customization", + "pages": [ + "ui-kit/android/customization-overview", + "ui-kit/android/customization-view-slots", + "ui-kit/android/customization-styles", + "ui-kit/android/customization-viewmodel-data", + "ui-kit/android/customization-adapters", + "ui-kit/android/customization-events", + "ui-kit/android/customization-state-views", + "ui-kit/android/customization-text-formatters", + "ui-kit/android/customization-menu-options", + "ui-kit/android/customization-datasource" + ] + }, { "group": "Components", "pages": [ @@ -1561,6 +1577,7 @@ "ui-kit/android/message-header", "ui-kit/android/message-list", "ui-kit/android/message-composer", + "ui-kit/android/message-template", "ui-kit/android/threaded-messages-header", "ui-kit/android/incoming-call", "ui-kit/android/outgoing-call", @@ -1577,14 +1594,6 @@ "ui-kit/android/events" ] }, - { - "group": "Advanced", - "pages": [ - "ui-kit/android/message-template", - "ui-kit/android/mentions-formatter-guide", - "ui-kit/android/shortcut-formatter-guide" - ] - }, { "group": "Guides", "pages": [ @@ -1593,9 +1602,13 @@ "ui-kit/android/guide-block-unblock-user", "ui-kit/android/guide-new-chat", "ui-kit/android/guide-message-privately", + "ui-kit/android/guide-search-messages", "ui-kit/android/guide-call-log-details", "ui-kit/android/guide-group-chat", - "ui-kit/android/guide-ai-agent" + "ui-kit/android/guide-ai-agent", + "ui-kit/android/custom-text-formatter-guide", + "ui-kit/android/mentions-formatter-guide", + "ui-kit/android/shortcut-formatter-guide" ] }, { @@ -1605,6 +1618,7 @@ "ui-kit/android/property-changes" ] }, + "ui-kit/android/troubleshooting", "ui-kit/android/link/sample", "ui-kit/android/link/figma", "ui-kit/android/link/changelog" diff --git a/fundamentals/extensions-overview.mdx b/fundamentals/extensions-overview.mdx index d6e58d1dd..3aa338a73 100644 --- a/fundamentals/extensions-overview.mdx +++ b/fundamentals/extensions-overview.mdx @@ -11,32 +11,32 @@ Extensions pickup where our core leaves. They help extend the functionality of C Extensions that help improve the user messaging experience. *Recommended for most apps.* -[Pin message](/fundamentals/pin-message)\ [Bitly](/fundamentals/bitly)\ -[Avatars](/fundamentals/avatars)\ -[Message shortcuts](/fundamentals/message-shortcuts)\ [Link Preview](/fundamentals/link-preview)\ +[Message shortcuts](/fundamentals/message-shortcuts)\ +[Pin message](/fundamentals/pin-message)\ [Rich Media Preview](/fundamentals/rich-media-preview)\ [Save message](/fundamentals/save-message)\ [Thumbnail Generation](/fundamentals/thumbnail-generation)\ [TinyURL](/fundamentals/tinyurl)\ -[Voice Transcription](/fundamentals/voice-transcription) +[Voice Transcription](/fundamentals/voice-transcription)\ +[Avatars](/fundamentals/avatars) ### User Engagement Extensions that help increase user engagement. *Recommended for advanced apps.* -[Email replies](/fundamentals/email-replies)\ -[Polls](/fundamentals/polls)\ [Giphy](/fundamentals/giphy)\ -[Mentions](/fundamentals/mentions)\ [Message Translation](/fundamentals/message-translation)\ -[Reactions](/fundamentals/reactions)\ -[Smart Reply](/fundamentals/smart-replies)\ +[Polls](/fundamentals/polls)\ +[Reminders](/fundamentals/reminders)\ [Stickers](/fundamentals/stickers)\ [Stipop](/fundamentals/stickers-stipop)\ [Tenor](/fundamentals/tenor)\ -[Reminders](/fundamentals/reminders)\ +[Email replies](/fundamentals/email-replies)\ +[Mentions](/fundamentals/mentions)\ +[Reactions](/fundamentals/reactions)\ +[Smart Reply](/fundamentals/smart-replies)\ [Live Streaming by api.video](/fundamentals/video-broadcasting) ### Collaboration @@ -46,12 +46,19 @@ Extensions that help with collaboration. *Recommended for advanced apps.* [Collaborative Whiteboard](/fundamentals/collaborative-whiteboard)\ [Collaborative Document](/fundamentals/collaborative-document) +### Security + +*Extensions that help you to build adding extra security to your apps.* *Recommended for live streaming and event apps.* + +[Disappearing messages](/fundamentals/disappearing-messages)\ +[End to End Encryption](/fundamentals/end-to-end-encryption) + ### Customer Support Extensions that help you add support to your app. *Recommended for advanced apps.* -[Intercom](/fundamentals/intercom)\ -[Chatwoot](/fundamentals/chatwoot) +[Chatwoot](/fundamentals/chatwoot)\ +[Intercom](/fundamentals/intercom) ### Notifications @@ -66,10 +73,3 @@ Extensions that help alert users of new messages. *Recommended for all apps.* *Extensions that help you to build a safe messaging environment.* *Recommended for live streaming and event apps.* [Legacy Moderation Extensions](/moderation/legacy-extensions) - -### Security - -*Extensions that help you to build adding extra security to your apps.* *Recommended for live streaming and event apps.* - -[Disappearing messages](/fundamentals/disappearing-messages)\ -[End to End Encryption](/fundamentals/end-to-end-encryption) diff --git a/sdk/javascript/video-view-customisation.mdx b/sdk/javascript/video-view-customisation.mdx index 2fd632577..5e3880224 100644 --- a/sdk/javascript/video-view-customisation.mdx +++ b/sdk/javascript/video-view-customisation.mdx @@ -1,8 +1,16 @@ --- title: "Video View Customisation" +description: "Customize the main video container in CometChat calls — aspect ratio, full screen button, name label, and network label positioning." --- - + +**Quick Reference** +- **Class:** `CometChat.MainVideoContainerSetting` +- **Apply via:** `CallSettingsBuilder.setMainVideoContainerSetting(videoSettings)` +- **Customizable elements:** Aspect ratio, full screen button, name label, network label +- **Position constants:** `POSITION_TOP_LEFT`, `POSITION_TOP_RIGHT`, `POSITION_BOTTOM_LEFT`, `POSITION_BOTTOM_RIGHT` +- **Requires:** [Default Calling](/sdk/javascript/default-call) or [Direct Calling](/sdk/javascript/direct-call) setup + This section will guide you to customise the main video container. @@ -26,16 +34,62 @@ The `MainVideoContainerSetting` Class is the required in case you want to custom Example: - -```typescript + +```javascript let videoSettings = new CometChat.MainVideoContainerSetting(); -videoSettings.setMainVideoAspectRatio(CometChat.CallSettings.ASPECT_RATIO_CONTAIN); +videoSettings.setMainVideoAspectRatio(CometChat.CallSettings.ASPECT_RATIO_CONTAIN); videoSettings.setFullScreenButtonParams(CometChat.CallSettings.POSITION_BOTTOM_RIGHT, true); videoSettings.setNameLabelParams(CometChat.CallSettings.POSITION_BOTTOM_LEFT, true, "rgba(27, 27, 27, 0.4)"); -videoSettings.setNetworkLabelParams(CometChat.CallSettings.POSITION_BOTTOM_RIGHT, true); +videoSettings.setNetworkLabelParams(CometChat.CallSettings.POSITION_BOTTOM_RIGHT, true); ``` - + +```typescript +let videoSettings: CometChat.MainVideoContainerSetting = new CometChat.MainVideoContainerSetting(); +videoSettings.setMainVideoAspectRatio(CometChat.CallSettings.ASPECT_RATIO_CONTAIN); +videoSettings.setFullScreenButtonParams(CometChat.CallSettings.POSITION_BOTTOM_RIGHT, true); +videoSettings.setNameLabelParams(CometChat.CallSettings.POSITION_BOTTOM_LEFT, true, "rgba(27, 27, 27, 0.4)"); +videoSettings.setNetworkLabelParams(CometChat.CallSettings.POSITION_BOTTOM_RIGHT, true); +``` + + + + + +| Practice | Details | +| --- | --- | +| Aspect ratio choice | Use `ASPECT_RATIO_CONTAIN` to show the full video without cropping; use `ASPECT_RATIO_COVER` for a full-bleed look that may crop edges | +| Label positioning | Avoid placing the name label and network label in the same corner to prevent overlap | +| Full screen button | Keep the full screen button visible for better UX; only hide it if your app provides its own full screen toggle | + + + + +| Symptom | Cause | Fix | +| --- | --- | --- | +| Video settings not applied | `setMainVideoContainerSetting()` not called on `CallSettingsBuilder` | Pass the `MainVideoContainerSetting` object to `CallSettingsBuilder.setMainVideoContainerSetting()` before calling `startCall()` | +| Labels overlapping | Multiple labels positioned in the same corner | Assign different position constants to each label | +| Full screen button missing | Visibility set to `false` | Set the second parameter of `setFullScreenButtonParams()` to `true` | + + + + +## Next Steps + + + + Implement default audio/video calling. + + + Implement direct calling without call events. + + + Add virtual background and blur effects. + + + Record calls for playback. + + diff --git a/sdk/javascript/virtual-background.mdx b/sdk/javascript/virtual-background.mdx index 63edd0a83..0879041c1 100644 --- a/sdk/javascript/virtual-background.mdx +++ b/sdk/javascript/virtual-background.mdx @@ -1,8 +1,16 @@ --- title: "Virtual Background" +description: "Implement virtual background features in CometChat video calls — background blur, custom images, and enforced backgrounds using the JavaScript SDK." --- - + +**Quick Reference** +- **Settings class:** `CometChat.VirtualBackground` +- **Apply via:** `CallSettingsBuilder.setVirtualBackground(virtualBackground)` +- **Toggle UI:** `CallSettingsBuilder.showVirtualBackgroundSetting(true|false)` +- **Runtime control:** `CometChat.CallController.getInstance()` → `setBackgroundBlur()`, `setBackgroundImage()`, `openVirtualBackground()` +- **Requires:** [Default Calling](/sdk/javascript/default-call) or [Direct Calling](/sdk/javascript/direct-call) setup + This section will guide you to implement virtual background feature in video calls. @@ -35,21 +43,17 @@ You can use the `openVirtualBackground()` method to open the virtual background -```js +```javascript let callController = CometChat.CallController.getInstance(); callController.openVirtualBackground(); ``` - - ```typescript let callController: CometChat.CallController = CometChat.CallController.getInstance(); callController.openVirtualBackground(); ``` - - ### Set Background Blur @@ -58,23 +62,19 @@ You can use the `setBackgroundBlur()` method to apply background blur on the vid -```js +```javascript let callController = CometChat.CallController.getInstance(); let blurLevel = 1; callController.setBackgroundBlur(blurLevel); ``` - - ```typescript let callController: CometChat.CallController = CometChat.CallController.getInstance(); let blurLevel: number = 1; callController.setBackgroundBlur(blurLevel); ``` - - ### Set Background Image @@ -83,23 +83,19 @@ You can use the `setBackgroundImage()`method to set the background image. This m -```js +```javascript let callController = CometChat.CallController.getInstance(); let imageURL = "URL_OF_BACKGROUND_IMAGE"; callController.setBackgroundImage(imageURL); ``` - - ```typescript let callController: CometChat.CallController = CometChat.CallController.getInstance(); let imageURL: string = "URL_OF_BACKGROUND_IMAGE"; callController.setBackgroundImage(imageURL); ``` - - ## Virtual Background Settings @@ -114,3 +110,44 @@ The `VirtualBackground` Class is the required in case you want to change how the | `setImages(images: Array)` | This method allows developer to add their custom background image which the end user can choose. | | `enforceBackgroundBlur(enforceBackgroundBlur: number)` | This method starts the call with background blurred. To blur the background you need to pass an integer value between 1-99 which decides the blur level. **Default = 0** | | `enforceBackgroundImage(enforceBackgroundImage: string)` | This methods starts the call with the provided background image. | + + + + +| Practice | Details | +| --- | --- | +| Blur level range | Use values between 1-99 for `enforceBackgroundBlur()`. Higher values produce stronger blur. A value of 0 disables blur | +| Image hosting | Host background images on a CDN for fast loading. Large images may cause lag when applied | +| Enforce vs allow | Use `enforceBackgroundBlur()` or `enforceBackgroundImage()` when you want a mandatory background (e.g., for privacy). Use `allowBackgroundBlur()` and `allowUserImages()` to let users choose | +| Custom buttons | Use `CallController` methods (`setBackgroundBlur`, `setBackgroundImage`, `openVirtualBackground`) when building a custom UI instead of the default CometChat menu | + + + + +| Symptom | Cause | Fix | +| --- | --- | --- | +| Virtual background option not visible | `showVirtualBackgroundSetting(false)` was set | Set `showVirtualBackgroundSetting(true)` in `CallSettingsBuilder` | +| Background blur not applied on call start | `enforceBackgroundBlur()` not set or set to 0 | Pass a value between 1-99 to `enforceBackgroundBlur()` | +| Custom images not appearing | `setImages()` not called or empty array passed | Pass a non-empty array of valid image URLs to `setImages()` | +| `CallController.getInstance()` returns null | Called before the call has started | Only use `CallController` methods after `startCall()` has been invoked | +| User can't upload their own images | `allowUserImages(false)` was set | Set `allowUserImages(true)` in the `VirtualBackground` configuration | + + + + +## Next Steps + + + + Customize the main video container layout. + + + Record calls for playback. + + + Enable screen sharing and presenter mode. + + + Customize the calling UI appearance. + + diff --git a/ui-kit/android/ai-assistant-chat-history.mdx b/ui-kit/android/ai-assistant-chat-history.mdx index d692600a1..657588a81 100644 --- a/ui-kit/android/ai-assistant-chat-history.mdx +++ b/ui-kit/android/ai-assistant-chat-history.mdx @@ -1,44 +1,70 @@ --- title: "AI Assistant Chat History" +description: "Displays the conversation history between users and an AI assistant for easy review of past interactions." --- + + +```json +{ + "component": "CometChatAIAssistantChatHistory", + "package": "com.cometchat.chatuikit.aiassistantchathistory", + "xmlElement": "", + "description": "Displays the conversation history between users and an AI assistant for easy review of past interactions.", + "primaryOutput": { + "method": "setOnItemClickListener", + "type": "OnItemClickListener" + }, + "methods": { + "data": { + "setUser": { + "type": "User", + "required": true, + "note": "User must have role set to @agentic" + } + }, + "callbacks": { + "setOnItemClickListener": "OnItemClickListener", + "setOnItemLongClickListener": "OnItemLongClickListener", + "setOnNewChatClickListener": "OnClick", + "setOnCloseClickListener": "OnClick" + }, + "visibility": { + "setErrorStateVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" }, + "setEmptyStateVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" } + }, + "style": { + "setStyle": { + "type": "@StyleRes int", + "parent": "CometChatAIAssistantChatHistoryStyle" + } + } + }, + "events": [], + "sdkListeners": [] +} +``` -## Overview - -The `AI Assistant Chat History` component is a pre-built user interface element designed to display the conversation history between users and an AI assistant within a chat application. It provides a structured and visually appealing way to present past interactions, making it easy for users to review previous messages and context. - - - - - -*** - -## Usage - -### Integration + -`AIAssistantChatHistory`, as a Composite Component, offers flexible integration options, allowing it to be launched directly via button clicks or any user-triggered action. +## Quick Start -The following code snippet exemplifies how you can seamlessly integrate the GroupMembers component into your application. +1. Open your layout XML file. +2. Add the `CometChatAIAssistantChatHistory` XML element: - - -```xml - +```xml lines + ``` - +> **What this does:** Adds the `CometChatAIAssistantChatHistory` component to your layout. It fills the available width and height and renders the AI assistant chat history list. - - -If you're defining the Group members within the XML code, you'll need to extract them and set them on the Group object using the appropriate method. +3. In your Activity or Fragment, create a `User` object with the role set to `@agentic` and pass it to the component: -```java - +```java lines User user = new User(); user.setUid("userId"); user.setName("User Name"); @@ -50,8 +76,7 @@ binding.cometChatAiAssistantChatHistory.setUser(user); -```kotlin - +```kotlin lines val user = User() user.uid = "userId" user.name = "User Name" @@ -64,20 +89,40 @@ binding.cometChatAiAssistantChatHistory.setUser(user) -*** +> **What this does:** Creates a `User` object with the `@agentic` role and sets it on the `CometChatAIAssistantChatHistory` component. This is required for the component to fetch and display the AI assistant chat histories for that user. -### Actions +4. Build and run your app. +5. Verify that the AI assistant chat history list appears with past conversation items. -[Actions](/ui-kit/android/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. + + + + +## Core Concepts + +- **`CometChatAIAssistantChatHistory`**: The main component class that renders the AI assistant chat history list. It is a Composite Component that can be launched via button clicks or any user-triggered action. +- **Actions**: Callbacks such as `setOnItemClickListener`, `setOnItemLongClickListener`, `setOnNewChatClickListener`, and `setOnCloseClickListener` that let you respond to user interactions. +- **Style**: XML theme styles applied via `setStyle()` to customize colors, fonts, and visual appearance of the chat history. +- **Functionality**: Methods like `setUser`, `setErrorStateVisibility`, and `setEmptyStateVisibility` that configure the component's behavior and state visibility. + +## Actions and Events + +### Callback Methods + +What you're changing: How the component responds to user interactions such as taps, long-presses, new chat clicks, and close clicks. -##### setOnItemClickListener +- **Where**: Activity or Fragment where you hold a reference to `CometChatAIAssistantChatHistory`. +- **Applies to**: `CometChatAIAssistantChatHistory`. +- **Default behavior**: Predefined actions execute automatically when the user interacts with the component. +- **Override**: Call the corresponding setter method to replace the default behavior with your own logic. -Function invoked when a chat history item is clicked, typically used to open an ai assistant chat screen. +#### `setOnItemClickListener` + +Function invoked when a chat history item is clicked, used to open an AI assistant chat screen. -```java YourActivity.java - +```java YourActivity.java lines binding.cometchatAiAssistantChatHistory.setOnItemClickListener((view, position, message) -> { }); @@ -86,7 +131,7 @@ binding.cometchatAiAssistantChatHistory.setOnItemClickListener((view, position, -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines binding.cometchatAiAssistantChatHistory.setOnItemClickListener { view, position, message -> } @@ -96,15 +141,15 @@ binding.cometchatAiAssistantChatHistory.setOnItemClickListener { view, position, -*** +> **What this does:** Replaces the default item-click behavior. When a user taps a chat history item, your custom lambda executes instead of the built-in navigation. -##### setOnItemLongClick +#### `setOnItemLongClickListener` -Function executed when a user item is long-pressed, allowing additional actions like delete or block. +Function executed when a chat history item is long-pressed, allowing additional actions like delete or block. -```java YourActivity.java +```java YourActivity.java lines binding.cometchatAiAssistantChatHistory.setOnItemLongClickListener((view, position, message) -> { }); @@ -113,7 +158,7 @@ binding.cometchatAiAssistantChatHistory.setOnItemLongClickListener((view, positi -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines binding.cometchatAiAssistantChatHistory.setOnItemLongClickListener { view, position, message -> } @@ -123,15 +168,15 @@ binding.cometchatAiAssistantChatHistory.setOnItemLongClickListener { view, posit -*** +> **What this does:** Replaces the default long-press behavior. When a user long-presses a chat history item, your custom lambda executes. -##### setOnNewChatClickListener +#### `setOnNewChatClickListener` -Function triggered when the new chat button is clicked, typically used to start a new conversation with the AI assistant. +Function triggered when the new chat button is clicked, used to start a new conversation with the AI assistant. -```java YourActivity.java +```java YourActivity.java lines binding.cometchatAiAssistantChatHistory.setOnNewChatClickListener(() -> { }); @@ -140,7 +185,7 @@ binding.cometchatAiAssistantChatHistory.setOnNewChatClickListener(() -> { -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines binding.cometchatAiAssistantChatHistory.setOnNewChatClickListener { } @@ -150,15 +195,15 @@ binding.cometchatAiAssistantChatHistory.setOnNewChatClickListener { -*** +> **What this does:** Replaces the default new-chat-click behavior. When the user taps the new chat button, your custom logic runs instead of the built-in action. -##### setOnCloseClickListener +#### `setOnCloseClickListener` -Function activated when the close button is clicked, usually to exit the chat history view. +Function activated when the close button is clicked, used to exit the chat history view. -```java YourActivity.java +```java YourActivity.java lines binding.cometchatAiAssistantChatHistory.setOnCloseClickListener(() -> { }); @@ -167,7 +212,7 @@ binding.cometchatAiAssistantChatHistory.setOnCloseClickListener(() -> { -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines binding.cometchatAiAssistantChatHistory.setOnCloseClickListener { } @@ -177,50 +222,59 @@ binding.cometchatAiAssistantChatHistory.setOnCloseClickListener { -## Customization +> **What this does:** Replaces the default close-click behavior. When the user taps the close button, your custom logic runs instead of the built-in exit action. -The `AIAssistantChatHistory` component offers a variety of customization options to tailor its appearance and functionality to better fit your application's needs. These customizations are categorized into three main areas: Style, Functionality, and Advanced. +- **Verify**: After setting an action callback, trigger the corresponding user interaction (tap, long-press, new chat, close) and confirm your custom logic executes instead of the default behavior. -### Style +## Styling -Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component. +What you're changing: The visual appearance of the AI Assistant Chat History component using XML theme styles. + +- **Where**: `themes.xml` for style definitions, and your Activity/Fragment for applying the style. +- **Applies to**: `CometChatAIAssistantChatHistory`. +- **Default behavior**: The component uses its default style. +- **Override**: Define a custom style in `themes.xml`, then call `setStyle()` on the component. -```xml themes.xml - - - +- **Code**: + +```xml themes.xml lines + + + ``` +> **What this does:** Defines a custom style `CustomAIAssistantChatHistoryStyle` that sets the background color to `#FFFAF6` for the component, header, new chat area, date separator, and items. It applies a Times New Roman font to the header, new chat text, date separator, and item text. A helper style `textStyleTimesNewRoman` defines the font family. + -```java +```java lines binding.cometchatAiAssistantChatHistory.setStyle(R.style.CustomAIAssistantChatHistoryStyle); ``` -```kotlin +```kotlin lines binding.cometchatAiAssistantChatHistory.setStyle(R.style.CustomAIAssistantChatHistoryStyle); ``` @@ -228,18 +282,64 @@ binding.cometchatAiAssistantChatHistory.setStyle(R.style.CustomAIAssistantChatHi -*** +> **What this does:** Applies the `CustomAIAssistantChatHistoryStyle` theme to the `CometChatAIAssistantChatHistory` component, changing the background colors and fonts. To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_assistant_chat_history.xml). -### Functionality - -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can toggle the visibility of UI elements. - -Below is a list of customizations along with corresponding code snippets - -| Methods | Description | Code | -| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -| setUser | Sets the user whose chat histories with the ai assistant need to be fetched. This is a required property for the component to function properly. | `.setUser(user);` | -| setErrorStateVisibility | Used to toggle the visibility of the error state of the component | `.setErrorStateVisibility(View.GONE);` | -| setEmptyStateVisibility | Used to toggle the visibility of the empty state of the component | `.setEmptyStateVisibility(View.GONE);` | +- **Verify**: The chat history component displays with the `#FFFAF6` background color and Times New Roman font for header text, new chat text, date separator text, and item text. + +## Functionality + +What you're changing: Small functional customizations such as setting the user and toggling visibility of UI states. + +- **Where**: Activity or Fragment where you hold a reference to `CometChatAIAssistantChatHistory`. +- **Applies to**: `CometChatAIAssistantChatHistory`. +- **Default behavior**: All UI states are visible with default settings. +- **Override**: Call the corresponding method on the component instance. + +| Methods | Description | Code | +| --- | --- | --- | +| `setUser` | Sets the user whose chat histories with the AI assistant need to be fetched. This is a required property for the component to function. The user's role must be `@agentic`. | `.setUser(user);` | +| `setErrorStateVisibility` | Toggles the visibility of the error state of the component | `.setErrorStateVisibility(View.GONE);` | +| `setEmptyStateVisibility` | Toggles the visibility of the empty state of the component | `.setEmptyStateVisibility(View.GONE);` | + +- **Verify**: After calling `setUser(user)`, confirm the component fetches and displays the AI assistant chat histories for that user. After calling a visibility method, confirm the corresponding UI state is shown or hidden. + +## Customization Matrix + +| What you want to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Component background color | `themes.xml` | `cometChatAIAssistantChatHistoryBackgroundColor` | `#FFFAF6` | +| Header background color | `themes.xml` | `cometChatAIAssistantChatHistoryHeaderBackgroundColor` | `#FFFAF6` | +| Header text color | `themes.xml` | `cometChatAIAssistantChatHistoryHeaderTextColor` | `?attr/cometchatTextColorPrimary` | +| Header text appearance | `themes.xml` | `cometChatAIAssistantChatHistoryHeaderTextAppearance` | `@style/textStyleTimesNewRoman` | +| New chat background color | `themes.xml` | `cometChatAIAssistantChatHistoryNewChatBackgroundColor` | `#FFFAF6` | +| New chat text color | `themes.xml` | `cometChatAIAssistantChatHistoryNewChatTextColor` | `?attr/cometchatTextColorPrimary` | +| New chat text appearance | `themes.xml` | `cometChatAIAssistantChatHistoryNewChatTextAppearance` | `@style/textStyleTimesNewRoman` | +| Date separator text appearance | `themes.xml` | `cometChatAIAssistantChatHistoryDateSeparatorTextAppearance` | `@style/textStyleTimesNewRoman` | +| Date separator text color | `themes.xml` | `cometChatAIAssistantChatHistoryDateSeparatorTextColor` | `?attr/cometchatTextColorTertiary` | +| Date separator background color | `themes.xml` | `cometChatAIAssistantChatHistoryDateSeparatorBackgroundColor` | `#FFFAF6` | +| Item background color | `themes.xml` | `cometChatAIAssistantChatHistoryItemBackgroundColor` | `#FFFAF6` | +| Item text appearance | `themes.xml` | `cometChatAIAssistantChatHistoryItemTextAppearance` | `@style/textStyleTimesNewRoman` | +| Item text color | `themes.xml` | `cometChatAIAssistantChatHistoryItemTextColor` | `?attr/cometchatTextColorPrimary` | +| Apply a custom style | Activity/Fragment | `setStyle(int styleRes)` | `binding.cometchatAiAssistantChatHistory.setStyle(R.style.CustomAIAssistantChatHistoryStyle);` | +| Set the user for fetching history | Activity/Fragment | `setUser(User)` | `.setUser(user);` | +| Error state visibility | Activity/Fragment | `setErrorStateVisibility(int)` | `.setErrorStateVisibility(View.GONE);` | +| Empty state visibility | Activity/Fragment | `setEmptyStateVisibility(int)` | `.setEmptyStateVisibility(View.GONE);` | + +## Next Steps + + + + Display messages in a conversation + + + Browse recent conversations + + + Browse and search available users + + + Search across conversations and messages + + \ No newline at end of file diff --git a/ui-kit/android/ai-features.mdx b/ui-kit/android/ai-features.mdx index fa995487c..d4cfd7993 100644 --- a/ui-kit/android/ai-features.mdx +++ b/ui-kit/android/ai-features.mdx @@ -1,20 +1,32 @@ --- -title: "AI" +title: "Smart Chat Features" +description: "Integrate AI-powered conversation starters, smart replies, and conversation summaries into your Android chat app." --- -## Overview + -CometChat's AI capabilities greatly enhance user interaction and engagement in your application. Let's understand how the Android UI Kit achieves these features. +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Required setup | `CometChatUIKit.init()` then `CometChatUIKit.login()` + AI features enabled in [CometChat Dashboard](/fundamentals/ai-user-copilot/overview) | +| AI features | Conversation Starter, Smart Replies, Conversation Summary | +| Key components | `CometChatMessageList` → [Message List](/ui-kit/android/message-list) (Conversation Starter), `CometChatMessageComposer` → [Message Composer](/ui-kit/android/message-composer) (Smart Replies, Summary) | +| Activation | Enable each AI feature from the CometChat Dashboard — UI Kit auto-integrates them, no additional code required | +| Related | [Core Features](/ui-kit/android/core-features), [Extensions](/ui-kit/android/extensions), [AI Agent Guide](/ui-kit/android/guide-ai-agent) | + + + +CometChat's AI capabilities greatly enhance user interaction and engagement in your application. Here's how the Android UI Kit integrates these features. -## Conversation Starters +## Conversation Starter -When a user initiates a new chat, the UI kit displays a list of suggested opening lines that users can select, making it easier for them to start a conversation. These suggestions are powered by CometChat's AI, which predicts contextually relevant conversation starters. +When a user initiates a new chat, the UI kit displays a list of suggested opening lines that users can select, making it easier for them to start a conversation. These suggestions are powered by CometChat's AI, which predicts contextually relevant conversation starter options. -For a comprehensive understanding and guide on implementing and using the Conversation Starters, refer to our specific guide on the [Conversation Starter](/fundamentals/ai-user-copilot/conversation-starter). +For a comprehensive understanding and guide on implementing and using the Conversation Starter, refer to our specific guide on the [Conversation Starter](/fundamentals/ai-user-copilot/conversation-starter). Once you have successfully activated the [Conversation Starter](/fundamentals/ai-user-copilot/conversation-starter) from your CometChat Dashboard, the feature will automatically be incorporated into the [MessageList](/ui-kit/android/message-list) Component of UI Kits. @@ -40,7 +52,7 @@ The Conversation Summary feature provides concise summaries of long conversation For a comprehensive understanding and guide on implementing and using the Conversation Summary, refer to our specific guide on the [Conversation Summary](/fundamentals/ai-user-copilot/conversation-summary). -Once you have successfully activated the [Smart Replies](/fundamentals/ai-user-copilot/smart-replies) from your CometChat Dashboard, the feature will automatically be incorporated into the Action sheet of [MessageComposer](/ui-kit/android/message-composer) Component of UI Kits. +Once you have successfully activated the [Conversation Summary](/fundamentals/ai-user-copilot/conversation-summary) from your CometChat Dashboard, the feature will automatically be incorporated into the Action sheet of [MessageComposer](/ui-kit/android/message-composer) Component of UI Kits. diff --git a/ui-kit/android/android-conversation.mdx b/ui-kit/android/android-conversation.mdx index 4bebefe49..d11348004 100644 --- a/ui-kit/android/android-conversation.mdx +++ b/ui-kit/android/android-conversation.mdx @@ -1,37 +1,50 @@ --- title: "Building A Conversation List + Message View" sidebarTitle: "Conversation List + Message View" +description: "Build a conversation list with a full-screen message view using a sequential navigation pattern." --- -The **Conversation List + Message View** layout offers a seamless **two-panel chat interface**, commonly used in modern messaging applications like **WhatsApp Web, Slack, and Microsoft Teams**. + -This design enables users to switch between conversations effortlessly while keeping the chat window open, ensuring a **smooth, real-time messaging experience**. +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Components | `CometChatConversations`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Sequential navigation — conversation list → full-screen message view | +| Prerequisite | Complete [Integration](/ui-kit/android/getting-started) Steps 1–4 first | +| Pattern | WhatsApp, Slack, Telegram | -*** + -## **User Interface Preview** +This guide builds a sequential navigation chat layout — conversation list as the entry point, tap a conversation to open a full-screen message view. Users see their conversation list and tap any conversation to open the chat. + +This assumes you've already completed [Integration](/ui-kit/android/getting-started) (project created, dependencies installed, init + login working, theme set up). + +--- + +## What You're Building -### **Key Components** +Three sections working together: -1. **Chat Header** – Displays user/group name, profile image, and status. -2. **Message List** – Shows chat history and new messages. -3. **Message Composer** – Allows users to send messages, media, and reactions. +1. **Conversation list** — shows all active conversations (users and groups) +2. **Message header** — displays user/group name, avatar, and status +3. **Message list + composer** — chat history with real-time updates and text input -*** +This implementation uses Android's standard Activity navigation: `ConversationActivity` displays the list, user taps a conversation, `MessageActivity` launches with the selected user/group data via Intent extras. -## **Step-by-Step Guide** +--- -### **Step 1: Set Up Conversation Activity** -Create an Activity - `ConversationActivity.kt` to manage and display the chat UI. +### Step 1: Set Up Conversation Activity +Create a new Activity called `ConversationActivity` to display the list of conversations. -#### **Layout** -Define the layout using the `CometChatConversations` component: +#### Layout +Define the layout using the `CometChatConversations` component in `activity_conversations.xml`: -```xml activity_conversations.xml +```xml activity_conversations.xml lines ``` -#### **Activity** +#### Activity -Initialize and handle conversation clicks: +Initialize the `CometChatConversations` component and handle conversation item clicks to navigate to the message screen: -```kotlin ConversationActivity.kt +```kotlin ConversationActivity.kt lines import android.content.Intent import android.os.Bundle @@ -117,7 +130,7 @@ class ConversationActivity : AppCompatActivity() { -```java ConversationActivity.java +```java ConversationActivity.java lines import android.content.Intent; import android.os.Bundle; @@ -186,14 +199,16 @@ This is necessary to properly manage the **UI Kit's lifecycle events**. -*** +--- + +### Step 2: Set Up Message Activity +Create a new Activity - `MessageActivity` to display the chat interface. -### **Step 2: Set Up Message Activity** -Create an Activity - `MessageActivity.kt` to manage and display the chat UI. +#### Layout -#### **Layout** +Define the layout with `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` in `activity_message.xml`: -```xml activity_message.xml +```xml activity_message.xml lines ``` -#### **Activity** +#### Activity -Use the user/group passed from the conversation click: +Retrieve the user/group ID from the Intent extras and configure the message components: -```kotlin MessageActivity.kt +```kotlin MessageActivity.kt lines import android.os.Bundle import android.util.Log import android.widget.Toast @@ -344,7 +359,7 @@ class MessageActivity : AppCompatActivity() { -```java MessageActivity.java +```java MessageActivity.java lines import android.os.Bundle; import android.util.Log; import android.widget.Toast; @@ -456,13 +471,14 @@ public class MessageActivity extends AppCompatActivity { *** -### **Step 3: Update MainActivity** +### Step 3: Update MainActivity -Update the `MainActivity` to navigate to the `MessageActivity`: +Update your `MainActivity` to launch `ConversationActivity` after successful login: -```kotlin MainActivity.kt +```kotlin MainActivity.kt highlight={16-18, 47-48} lines +import android.content.Intent import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity @@ -524,7 +540,7 @@ class MainActivity : ComponentActivity() { -```java MainActivity.java +```java MainActivity.java highlight={15-17, 51-52} lines import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -593,24 +609,39 @@ public class MainActivity extends ComponentActivity { -*** - -## **Running the Project** +--- -Once the components are configured, build and run the app: +## Running the Application -```sh -gradle build -``` +Once you've completed the setup, build and run your Android application: -Ensure you've added the necessary permissions and initialized CometChat in your `Application` class. -*** + +**Required Permissions** -## **Next Steps** +Ensure you've added the necessary permissions in your `AndroidManifest.xml`: -### **Enhance the User Experience** +```xml lines + + +``` + -* **[Advanced Customizations](/ui-kit/android/theme-introduction)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Explore all available UI Kit components and their customization options + + + Customize colors, fonts, and styles to match your brand + + + Back to the main setup guide + + + Add capabilities like threaded messages, blocking, and group management + + diff --git a/ui-kit/android/android-one-to-one-chat.mdx b/ui-kit/android/android-one-to-one-chat.mdx index 4308e76e4..cece2dd38 100644 --- a/ui-kit/android/android-one-to-one-chat.mdx +++ b/ui-kit/android/android-one-to-one-chat.mdx @@ -1,36 +1,51 @@ --- title: "Building A One To One/Group Chat Experience" sidebarTitle: "One To One/Group Chat" +description: "Launch a direct one-on-one or group chat screen without a conversation list for focused messaging." --- -The **One-to-One Chat** feature provides a streamlined **direct messaging interface**, making it ideal for **support chats, dating apps, and private messaging platforms**. This setup eliminates distractions by focusing solely on a **dedicated chat window**. + -*** +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Components | `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Single chat window — no conversation list | +| Prerequisite | Complete [Integration](/ui-kit/android/getting-started) Steps 1–4 first | +| Pattern | Support chat, embedded widgets, focused messaging | -## **User Interface Preview** + + +This guide builds a single chat window — no sidebar, no conversation list. Users go directly into a one-to-one or group chat. Good for support chat, dating apps, or notification-driven flows. + +This assumes you've already completed [Integration](/ui-kit/android/getting-started) (project created, dependencies installed, init + login working, theme set up). + +--- + +## What You're Building -### **Key Components** +Three components stacked vertically: -1. **Chat Header** – Displays user/group name, profile image, and status. -2. **Message List** – Shows chat history and new messages. -3. **Message Composer** – Allows users to send messages, media, and reactions. +1. **Message header** — displays user/group name, avatar, and status +2. **Message list** — real-time chat history with scrolling +3. **Message composer** — text input with media and attachments -*** +The user or group ID is passed via Intent extras when launching the Activity — ideal for launching from a user profile, support button, or notification. -## **Step-by-Step Guide** +--- -### **Step 1: Set Up Message Activity** -Create an Activity - `MessageActivity.kt` to manage and display the chat UI. +### Step 1: Set Up Message Activity +Create an Activity - `MessageActivity` to display the full-screen chat interface. -#### **Layout** +#### Layout -Define the layout using CometChat UI Kit components: +Define the layout with `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` in `activity_message.xml`: -```xml activity_message.xml +```xml activity_message.xml lines ``` -#### **Activity** +#### Activity + +Retrieve the user or group ID from the Intent extras and configure the message components: -```kotlin MessageActivity.kt +```kotlin MessageActivity.kt lines import android.os.Bundle import android.util.Log import android.widget.Toast @@ -179,7 +196,7 @@ class MessageActivity : AppCompatActivity() { -```java MessageActivity.java +```java MessageActivity.java lines import android.os.Bundle; import android.util.Log; import android.widget.Toast; @@ -301,15 +318,26 @@ This is necessary to properly manage the **UI Kit's lifecycle events**. -*** +--- + +### Step 2: Launch MessageActivity from Your App -### **Step 2: Update MainActivity** +Update your `MainActivity` (or any other Activity) to launch `MessageActivity` with the appropriate user or group ID: -Update the `MainActivity` to navigate to the `MessageActivity`: + +**Passing Data via Intent** + +You can pass either: +- `uid` (String) - for one-to-one chats +- `guid` (String) - for group chats + +The `MessageActivity` will automatically detect which type of chat to display based on the Intent extras. + -```kotlin MainActivity.kt +```kotlin MainActivity.kt highlight={16-18, 20-21, 50-53} lines +import android.content.Intent import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity @@ -328,6 +356,9 @@ class MainActivity : ComponentActivity() { private val region = "REGION" // Replace with your App Region private val authKey = "AUTH_KEY" // Replace with your Auth Key or leave blank if you are authenticating using Auth Token + private val uid = "cometchat-uid-1" // Replace with the UID of the user you want to chat with + private val target_uid = "cometchat-uid-2" // Replace with the UID of the user you want to chat with + private val uiKitSettings = UIKitSettings.UIKitSettingsBuilder() .setRegion(region) .setAppId(appID) @@ -352,12 +383,12 @@ class MainActivity : ComponentActivity() { } private fun loginUser() { - CometChatUIKit.login("cometchat-uid-1", object : CometChat.CallbackListener() { + CometChatUIKit.login(uid, object : CometChat.CallbackListener() { override fun onSuccess(user: User) { // Launch One-to-One or Group Chat Screen val intent = Intent(this@MainActivity, MessageActivity::class.java) - intent.putExtra("uid", "cometchat-uid-1") + intent.putExtra("uid", target_uid) // Pass the UID of the user you want to chat with startActivity(intent) } @@ -373,7 +404,7 @@ class MainActivity : ComponentActivity() { -```java MainActivity.java +```java MainActivity.java highlight={15-17, 19-20, 54-57} lines import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -392,6 +423,9 @@ public class MainActivity extends ComponentActivity { private final String region = "REGION"; // Replace with your App Region private final String authKey = "AUTH_KEY"; // Replace with your Auth Key + private final String uid = "cometchat-uid-1"; // Replace with the UID of the user you want to chat with + private final String target_uid = "cometchat-uid-2"; // Replace with the UID of the user you want to chat with + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -419,14 +453,14 @@ public class MainActivity extends ComponentActivity { } private void loginUser() { - CometChatUIKit.login("cometchat-uid-1", new CometChat.CallbackListener() { + CometChatUIKit.login(uid, new CometChat.CallbackListener() { @Override public void onSuccess(User user) { Log.d(TAG, "Login successful for user: " + user.getUid()); // Launch One-to-One or Group Chat Screen Intent intent = new Intent(MainActivity.this, MessageActivity.class); - intent.putExtra("uid", "cometchat-uid-1"); + intent.putExtra("uid", target_uid); startActivity(intent); } @@ -443,24 +477,43 @@ public class MainActivity extends ComponentActivity { -*** +--- -## **Running the Project** +## Running the Project -Once the components are configured, build and run the app: +Once you've completed the setup, build and run the app: -```sh +```sh lines gradle build ``` -Ensure you've added the necessary permissions and initialized CometChat in your `Application` class. - -*** + +**Required Permissions** -## **Next Steps** +Ensure you've added the necessary permissions in your `AndroidManifest.xml` and initialized CometChat in your `Application` class. +: -### **Enhance the User Experience** +```xml lines + + +``` + -* **[Advanced Customizations](/ui-kit/android/theme-introduction)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Explore all available UI Kit components and their customization options + + + Customize colors, fonts, and styles to match your brand + + + Back to the main setup guide + + + Add capabilities like threaded messages, blocking, and group management + + diff --git a/ui-kit/android/android-tab-based-chat.mdx b/ui-kit/android/android-tab-based-chat.mdx index 87ad56890..da09fcb84 100644 --- a/ui-kit/android/android-tab-based-chat.mdx +++ b/ui-kit/android/android-tab-based-chat.mdx @@ -1,43 +1,57 @@ --- -title: "Building A Messaging UI With Tabs, Sidebar, And Message View" +title: "Building A Tab-Based Messaging UI" sidebarTitle: "Tab Based Chat Experience" +description: "Create a tab-based messaging UI with BottomNavigationView for Chats, Calls, Users, and Groups." --- -This guide walks you through creating a **tab-based messaging UI** using **React** and **CometChat UIKit**. The UI will include different sections for **Chats, Calls, Users, and Groups**, allowing seamless navigation. + -*** +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Components | `CometChatConversations`, `CometChatCallLogs`, `CometChatUsers`, `CometChatGroups`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Tabbed bottom navigation (Chats, Calls, Users, Groups) + fragment container | +| Prerequisite | Complete [Integration](/ui-kit/android/getting-started) Steps 1–4 first | +| Pattern | Full-featured messaging app with multiple sections | -## **User Interface Preview** + + +This guide builds a tabbed messaging UI — Chats, Calls, Users, and Groups tabs via `BottomNavigationView`, with each tab loading its CometChat component in a fragment container. + +This assumes you've already completed [Integration](/ui-kit/android/getting-started) (project created, dependencies installed, init + login working, theme set up). + +--- + +## What You're Building -This layout consists of: +Three sections working together: -1. **Sidebar (Conversation List)** – Displays recent conversations with active users and groups. -2. **Message View** – Shows the selected chat with real-time messages. -3. **Message Input Box** – Allows users to send messages seamlessly. +1. **Bottom navigation bar** — switches between Chats, Calls, Users, and Groups +2. **Fragment container** — renders the CometChat component for the active tab +3. **Dynamic content** — each tab loads its respective Fragment with real-time data -*** +This uses Android's `BottomNavigationView` pattern: `TabbedActivity` hosts the navigation and fragment container, user taps a tab, the corresponding Fragment loads. -## **Step-by-Step Guide** - -### **Step 1: Create a Tab Component** +--- -To manage navigation, let's build a **`CometChatTabs`** component. This component will render different tabs and allow switching between sections dynamically. +### Step 1: Set Up Tabbed Activity +Create a new Activity called `TabbedActivity` with **BottomNavigationView** to manage tab navigation. -#### **Folder Structure** +#### Project Structure -Create a `TabbedActivity` inside your `src` directory and add the following files: +Create the following files in your Android project: -```txt +```txt lines src/main/java/your-package-name/ -├── TabbedActivity.kt -├── ChatsFragment.kt -├── CallLogsFragment.kt -├── UsersFragment.kt -├── GroupsFragment.kt +├── TabbedActivity.kt (or .java) +├── ChatsFragment.kt (or .java) +├── CallLogsFragment.kt (or .java) +├── UsersFragment.kt (or .java) +└── GroupsFragment.kt (or .java) src/main/java/your-package-name/ ├── res/ @@ -51,16 +65,19 @@ src/main/java/your-package-name/ │ └── bottom_nav_menu.xml ``` -#### **Download the Icons** +#### Vector Drawable Icons + +Download the navigation icons from the **CometChat UI Kit repository**: -These icons are available in the **CometChat UI Kit res folder**. You can find them at:\ -🔗 [GitHub Assets Folder](https://github.com/cometchat/cometchat-uikit-android/tree/v5/sample-app-java/src/main/res/drawable) +🔗 [GitHub Drawable Resources](https://github.com/cometchat/cometchat-uikit-android/tree/v5/sample-app-java/src/main/res/drawable) -#### **Implementation** +Place the icon files (`ic_chats.xml`, `ic_calls.xml`, `ic_user.xml`, `ic_group.xml`) in your `res/drawable/` directory. + +#### Implementation -```kotlin TabbedActivity.kt +```kotlin TabbedActivity.kt highlight={} lines import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity @@ -131,7 +148,7 @@ class TabbedActivity : AppCompatActivity() { -```java TabbedActivity.java +```java TabbedActivity.java lines import android.os.Bundle; import android.view.View; import android.view.WindowInsets; @@ -217,7 +234,7 @@ public class TabbedActivity extends AppCompatActivity { -```xml activity_tabbed.xml +```xml activity_tabbed.xml lines ``` -```xml res/menu/bottom_nav_menu.xml +```xml res/menu/bottom_nav_menu.xml lines ``` -```xml res/menu/ic_chats.xml +```xml res/drawable/ic_chats.xml lines ``` -```xml res/menu/ic_calls.xml +```xml res/drawable/ic_calls.xml lines ``` -```xml res/menu/ic_user.xml +```xml res/drawable/ic_user.xml lines ``` -```xml res/menu/ic_group.xml +```xml res/drawable/ic_group.xml lines -*** +--- -### **Step 3: Create Fragments for Chat, Calls, Users and Groups** +### Step 2: Create Fragments for Each Tab + +Each tab displays a different CometChat UI component wrapped in a Fragment. #### Chats Fragment -```kotlin ChatsFragment.kt +```kotlin ChatsFragment.kt lines import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -381,7 +400,7 @@ class ChatsFragment : Fragment() { -```java ChatsFragment.java +```java ChatsFragment.java lines import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -407,7 +426,7 @@ public class ChatsFragment extends Fragment { -```xml res/layout/fragment_chats.xml +```xml res/layout/fragment_chats.xml lines -```kotlin CallLogsFragment.kt +```kotlin CallLogsFragment.kt lines import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -462,7 +481,7 @@ class CallLogsFragment : Fragment() { -```java CallLogsFragment.java +```java CallLogsFragment.java lines import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -486,7 +505,7 @@ public class CallLogsFragment extends Fragment { -```xml res/layout/fragment_call_logs.xml +```xml res/layout/fragment_call_logs.xml lines -```kotlin UsersFragment.kt +```kotlin UsersFragment.kt lines import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -534,7 +553,7 @@ class UsersFragment : Fragment() { -```java UsersFragment.java +```java UsersFragment.java lines import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -559,7 +578,7 @@ public class UsersFragment extends Fragment { -```xml res/layout/fragment_users.xml +```xml res/layout/fragment_users.xml lines -```kotlin GroupsFragment.kt +```kotlin GroupsFragment.kt lines import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -610,7 +629,7 @@ class GroupsFragment : Fragment() { -```java GroupsFragment.java +```java GroupsFragment.java lines import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -635,7 +654,7 @@ public class GroupsFragment extends Fragment { -```xml res/layout/fragment_groups.xml +```xml res/layout/fragment_groups.xml lines -*** +--- -### **Step 3: Update MainActivity** +### Step 3: Launch TabbedActivity from Your App -Update the `MainActivity` to navigate to the `MessageActivity`: +Update your `MainActivity` to launch `TabbedActivity` after successful login: -```kotlin MainActivity.kt +```kotlin MainActivity.kt highlight={16-18, 20} lines +import android.content.Intent import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity @@ -683,6 +703,8 @@ class MainActivity : ComponentActivity() { private val region = "REGION" // Replace with your App Region private val authKey = "AUTH_KEY" // Replace with your Auth Key or leave blank if you are authenticating using Auth Token + private val uid = "cometchat-uid-1" // Replace with the UID of the user you want to log in + private val uiKitSettings = UIKitSettings.UIKitSettingsBuilder() .setRegion(region) .setAppId(appID) @@ -707,7 +729,7 @@ class MainActivity : ComponentActivity() { } private fun loginUser() { - CometChatUIKit.login("cometchat-uid-1", object : CometChat.CallbackListener() { + CometChatUIKit.login(uid, object : CometChat.CallbackListener() { override fun onSuccess(user: User) { // Launch Tab-Based Chat Experience (Chats, Calls, Users, Groups) @@ -726,7 +748,7 @@ class MainActivity : ComponentActivity() { -```java MainActivity.java +```java MainActivity.java highlight={17-19, 21} lines package com.example.uikitsexamples; import android.content.Intent; @@ -747,6 +769,8 @@ public class MainActivity extends ComponentActivity { private final String region = "REGION"; // Replace with your App Region private final String authKey = "AUTH_KEY"; // Replace with your Auth Key + private final String uid = "cometchat-uid-1"; // Replace with the UID of the user you want to log in + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -774,7 +798,7 @@ public class MainActivity extends ComponentActivity { } private void loginUser() { - CometChatUIKit.login("cometchat-uid-1", new CometChat.CallbackListener() { + CometChatUIKit.login(uid, new CometChat.CallbackListener() { @Override public void onSuccess(User user) { Log.d(TAG, "Login successful for user: " + user.getUid()); @@ -796,24 +820,50 @@ public class MainActivity extends ComponentActivity { -*** +--- -## **Running the Project** +## Running the Application -Once the components are configured, build and run the app: +Once you've completed the setup, build and run your Android application: -```sh +```sh lines gradle build ``` -Ensure you've added the necessary permissions and initialized CometChat in your `Application` class. + +**Required Permissions** -*** +Ensure you've added the necessary permissions in your `AndroidManifest.xml`and initialized CometChat in your `Application` class: -## **Next Steps** +```xml lines + + +``` + +**For Call Features**, also add: -### **Enhance the User Experience** +```xml lines + + + +``` + -* **[Advanced Customizations](/ui-kit/android/theme-introduction)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Explore all available UI Kit components and their customization options + + + Customize colors, fonts, and styles to match your brand + + + Back to the main setup guide + + + Add capabilities like threaded messages, blocking, and group management + + diff --git a/ui-kit/android/call-buttons.mdx b/ui-kit/android/call-buttons.mdx index 9700f50de..8f53443d6 100644 --- a/ui-kit/android/call-buttons.mdx +++ b/ui-kit/android/call-buttons.mdx @@ -1,184 +1,309 @@ --- title: "Call Buttons" +description: "Voice and video call buttons that initiate calls for a given user or group." --- + + +```json +{ + "component": "CometChatCallButtons", + "package": "com.cometchat.chatuikit.calls.callbutton", + "xmlElement": "", + "description": "Voice and video call buttons that initiate calls for a given user or group.", + "primaryOutput": { + "method": "setOnVoiceCallClick / setOnVideoCallClick", + "type": "OnClick" + }, + "methods": { + "data": { + "setUser": { + "type": "User", + "default": "null", + "note": "Sets the user to call. Required for 1-on-1 calls." + }, + "setGroup": { + "type": "Group", + "default": "null", + "note": "Sets the group to call. Required for group calls." + } + }, + "callbacks": { + "setOnVoiceCallClick": "OnClick — void onClick(User user, Group group)", + "setOnVideoCallClick": "OnClick — void onClick(User user, Group group)" + }, + "visibility": { + "setVoiceCallButtonVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" }, + "setVideoCallButtonVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" }, + "setButtonTextVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" }, + "setButtonIconVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" } + }, + "viewSlots": { + "getVoiceCallButton": "CometChatButton — direct access to the voice call button for customization", + "getVideoCallButton": "CometChatButton — direct access to the video call button for customization" + }, + "advanced": { + "setOutgoingCallConfiguration": "OutgoingCallConfiguration — configures the outgoing call screen", + "setCallSettingsBuilder": "Function3 — custom call settings per call type", + "setMarginBetweenButtons": "@Dimension int — spacing between voice and video buttons", + "setVoiceButtonText": "String — custom text for the voice call button", + "setVideoButtonText": "String — custom text for the video call button", + "disposeObservers": "void — removes lifecycle observers" + }, + "style": { + "setStyle": { + "type": "@StyleRes int", + "parent": "CometChatCallButtonsStyle" + } + } + }, + "events": [ + { + "name": "CometChatCallEvents.ccOutgoingCall", + "payload": "Call", + "description": "An outgoing call was initiated" + }, + { + "name": "CometChatCallEvents.ccCallAccepted", + "payload": "Call", + "description": "A call was accepted by the recipient" + }, + { + "name": "CometChatCallEvents.ccCallRejected", + "payload": "Call", + "description": "A call was rejected by the recipient" + }, + { + "name": "CometChatCallEvents.ccCallEnded", + "payload": "Call", + "description": "A call was ended" + } + ], + "sdkListeners": [] +} +``` -## Overview + -The `CometChatCallButtons` is a [Component](/ui-kit/android/components-overview#components) provides users with the ability to make calls, access call-related functionalities, and control call settings. Clicking this button typically triggers the call to be placed to the desired recipient. +## Where It Fits - - - +`CometChatCallButtons` is a utility component. It renders voice and video call buttons and initiates calls for the bound `User` or `Group`. Wire it into a `CometChatMessageHeader` or place it anywhere a call action is needed. -*** + + +```kotlin ChatActivity.kt lines +class ChatActivity : AppCompatActivity() { -## Usage + private lateinit var messageHeader: CometChatMessageHeader + private lateinit var callButtons: CometChatCallButtons -### Integration + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_chat) -`CometChatCallButtons` can be used inside another widget or can be launched to a new screen by adding the following code snippet into the XML layout file. + messageHeader = findViewById(R.id.message_header) + callButtons = findViewById(R.id.call_buttons) - - -```xml - + // Bind the same user to both components + val user: User = intent.getParcelableExtra("user")!! + messageHeader.setUser(user) + callButtons.setUser(user) + } +} ``` - - - -If you're defining the `CometChatCallButtons` within the XML code or in your activity or fragment then you'll need to extract them and set them on the User object using the appropriate method. - - -```java -CometChatCallButtons cometchatCallButtons = binding.callButton; // 'binding' is a view binding instance. Initialize it with `binding = YourXmlFileNameBinding.inflate(getLayoutInflater());` to use views like `binding.callButton` after enabling view binding. +```java ChatActivity.java lines +public class ChatActivity extends AppCompatActivity { -if (userObject != null) { -cometchatCallButtons.setUser(userObject); //Required - CometChat User object -} else if (groupObject != null) { -cometchatCallButtons.setGroup(groupObject); //Required - CometChat Group object -} -``` + private CometChatMessageHeader messageHeader; + private CometChatCallButtons callButtons; - + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat); - -```kotlin -val cometchatCallButtons: CometChatCallButtons = binding.callButton // 'binding' is a view binding instance. Initialize it with `binding = YourXmlFileNameBinding.inflate(layoutInflater)` to use views like `binding.callButton` after enabling view binding. + messageHeader = findViewById(R.id.message_header); + callButtons = findViewById(R.id.call_buttons); -if (userObject != null) { - cometchatCallButtons.setUser(userObject) //Required - CometChat User object -} else if (groupObject != null) { - cometchatCallButtons.setGroup(groupObject) //Required - CometChat Group object + // Bind the same user to both components + User user = getIntent().getParcelableExtra("user"); + messageHeader.setUser(user); + callButtons.setUser(user); + } } ``` - - -*** +## Quick Start -### Actions +Add the component to your layout XML: -[Actions](/ui-kit/android/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +```xml layout_activity.xml lines + +``` -##### setOnVoiceCallClick +Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()`, a user logged in, and the `cometchat-chat-uikit-android` dependency added. -The `setOnVoiceCallClick` action is usually invoked when a voice call is initiated, executing predefined actions. However, by utilizing the provided code snippet, you can effortlessly tailor or override this default behavior to suit your unique requirements. +To add programmatically in an Activity: - -```java -cometchatCallButtons.setOnVoiceCallClick(new CometChatCallButtons.OnClick() { - @Override - public void onClick(User user, Group group) { - //TODO - } -}); + +```kotlin YourActivity.kt lines +override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val callButtons = CometChatCallButtons(this) + callButtons.setUser(user) + setContentView(callButtons) +} ``` - - -```kotlin -cometchatCallButtons.setOnVoiceCallClick(CometChatCallButtons.OnClick { user, group -> - //TODO -}) + +```java YourActivity.java lines +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + CometChatCallButtons callButtons = new CometChatCallButtons(this); + callButtons.setUser(user); + setContentView(callButtons); +} ``` - - -##### setOnVideoCallClick - -The `setOnVideoCallClick` action is typically triggered when a video call is initiated, executing default actions. However, with the provided code snippet, you have the flexibility to easily customize or override this default behavior according to your specific preferences or requirements. +Or in a Fragment: - -```java -cometchatCallButtons.setOnVideoCallClick(new CometChatCallButtons.OnClick() { - @Override - public void onClick(User user, Group group) { - //TODO - } -}); + +```kotlin YourFragment.kt lines +override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val callButtons = CometChatCallButtons(requireContext()) + callButtons.setUser(user) + return callButtons +} ``` - - -```kotlin -cometchatCallButtons.setOnVideoCallClick(CometChatCallButtons.OnClick { user, group -> - //TODO -}) + +```java YourFragment.java lines +@Override +public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + CometChatCallButtons callButtons = new CometChatCallButtons(getContext()); + callButtons.setUser(user); + return callButtons; +} ``` - - -##### setOnError +> You must call `setUser(User)` or `setGroup(Group)` before the buttons can initiate a call. Without a target, button clicks have no effect. -You can customize this behavior by using the provided code snippet to override the `setOnError` and improve error handling. +## Actions and Events + +### Callback Methods + +#### `setOnVoiceCallClick` + +Fires when the voice call button is tapped. Replaces the default behavior of initiating an audio call. + +```kotlin YourActivity.kt lines +callButtons.setOnVoiceCallClick { user, group -> + // Custom voice call logic +} +``` + + -```java -cometchatCallButtons.setOnError(new OnError() { - @Override - public void onError(CometChatException e) { - //TODO - } +```java YourActivity.java lines +callButtons.setOnVoiceCallClick((user, group) -> { + // Custom voice call logic }); ``` - + +> **What this does:** Replaces the default voice call initiation. When a user taps the voice call button, your custom lambda executes instead of the built-in call flow. The `OnClick` interface provides `void onClick(User user, Group group)`. + +#### `setOnVideoCallClick` + +Fires when the video call button is tapped. Replaces the default behavior of initiating a video call. + + -```kotlin -cometchatCallButtons.setOnError(OnError { e -> - //TODO -}) +```kotlin YourActivity.kt lines +callButtons.setOnVideoCallClick { user, group -> + // Custom video call logic +} ``` - + +```java YourActivity.java lines +callButtons.setOnVideoCallClick((user, group) -> { + // Custom video call logic +}); +``` + -*** +- **Verify**: After setting a callback, tap the corresponding button and confirm your custom logic executes instead of the default call initiation. -### Filters +### Global UI Events (CometChatCallEvents) -**Filters** allow you to customize the data displayed in a list within a Component. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using RequestBuilders of Chat SDK. +`CometChatCallEvents` emits events subscribable from anywhere in the application. Add a listener and remove it when no longer needed. -The CallButton component does not have any exposed filters. +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccOutgoingCall` | An outgoing call is initiated | `Call` | +| `ccCallAccepted` | A call is accepted by the recipient | `Call` | +| `ccCallRejected` | A call is rejected by the recipient | `Call` | +| `ccCallEnded` | A call is ended | `Call` | -*** + + +```kotlin Add Listener lines +CometChatCallEvents.addListener("CALL_LISTENER_TAG", object : CometChatCallEvents() { + override fun ccOutgoingCall(call: Call?) { + super.ccOutgoingCall(call) + } -### Events + override fun ccCallAccepted(call: Call?) { + super.ccCallAccepted(call) + } -[Events](/ui-kit/android/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. + override fun ccCallRejected(call: Call?) { + super.ccCallRejected(call) + } -Events emitted by the Call buttons component are as follows. + override fun ccCallEnded(call: Call?) { + super.ccCallEnded(call) + } +}) +``` -| Event | Description | -| ------------------ | -------------------------------------------- | -| **ccCallAccepted** | Triggers when the outgoing call is accepted. | -| **ccCallRejected** | Triggers when the outgoing call is rejected. | +Remove Listener -Add `CometChatCallEvents` +``` +CometChatCallEvents.removeListener("CALL_LISTENER_TAG") +``` + - -```java -CometChatCallEvents.addListener("UNIQUE_ID", new CometChatCallEvents() { +```java Add Listener lines +CometChatCallEvents.addListener("CALL_LISTENER_TAG", new CometChatCallEvents() { + @Override + public void ccOutgoingCall(Call call) { + super.ccOutgoingCall(call); + } + @Override public void ccCallAccepted(Call call) { super.ccCallAccepted(call); @@ -189,145 +314,347 @@ CometChatCallEvents.addListener("UNIQUE_ID", new CometChatCallEvents() { super.ccCallRejected(call); } + @Override + public void ccCallEnded(Call call) { + super.ccCallEnded(call); + } }); ``` - +Remove Listener - -```kotlin ``` - +CometChatCallEvents.removeListener("CALL_LISTENER_TAG"); +``` - -Remove `CometChatCallEvents` +### SDK Events - - -```java -CometChatCallEvents.removeListener("LISTENER_ID_USED_FOR_ADDING_THIS_LISTENER"); -``` +The component uses an internal `CallButtonsViewModel` that observes call initiation and direct call events. No manual SDK listener attachment is needed — the component handles call lifecycle internally. - +## Functionality + +Small functional customizations such as toggling visibility of UI elements and configuring button spacing. + +| Method | Description | Code | +| --- | --- | --- | +| `setVoiceCallButtonVisibility` | Toggles visibility of the voice call button | `.setVoiceCallButtonVisibility(View.GONE);` | +| `setVideoCallButtonVisibility` | Toggles visibility of the video call button | `.setVideoCallButtonVisibility(View.GONE);` | +| `setButtonTextVisibility` | Toggles visibility of text labels on both buttons | `.setButtonTextVisibility(View.GONE);` | +| `setButtonIconVisibility` | Toggles visibility of icons on both buttons | `.setButtonIconVisibility(View.GONE);` | +| `setMarginBetweenButtons` | Sets the spacing between voice and video buttons | `.setMarginBetweenButtons(24);` | + +- **Verify**: After calling a visibility method, confirm the corresponding UI element is shown or hidden. +## Custom View Slots + +`CometChatCallButtons` exposes direct access to its two internal `CometChatButton` instances. Use these to customize icons, text, colors, and other properties on each button individually. + +| Slot | Method | Returns | +| --- | --- | --- | +| Voice call button | `getVoiceCallButton()` | `CometChatButton` | +| Video call button | `getVideoCallButton()` | `CometChatButton` | + + -```kotlin -CometChatCallEvents.removeListener("LISTENER_ID_USED_FOR_ADDING_THIS_LISTENER") +```kotlin lines +// Access the voice call button and customize it +val voiceBtn = callButtons.getVoiceCallButton() +voiceBtn.setButtonText("Audio") + +// Access the video call button and customize it +val videoBtn = callButtons.getVideoCallButton() +videoBtn.setButtonText("Video") ``` - + +```java lines +// Access the voice call button and customize it +CometChatButton voiceBtn = callButtons.getVoiceCallButton(); +voiceBtn.setButtonText("Audio"); + +// Access the video call button and customize it +CometChatButton videoBtn = callButtons.getVideoCallButton(); +videoBtn.setButtonText("Video"); +``` + -*** +- **Verify**: After accessing a button via `getVoiceCallButton()` or `getVideoCallButton()`, confirm your customizations render correctly on the corresponding button. -## Customization +## Common Patterns -To fit your app's design requirements, you can customize the appearance of the conversation component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. +### Video-only buttons -### Style + + +```kotlin lines +callButtons.setVoiceCallButtonVisibility(View.GONE) +``` + -Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component. + +```java lines +callButtons.setVoiceCallButtonVisibility(View.GONE); +``` + + - - - +### Voice-only buttons -```xml themes.xml - + + +```kotlin lines +callButtons.setVideoCallButtonVisibility(View.GONE) ``` + - -```java -cometChatCallButtons.setStyle(R.style.CustomCallButtonStyle); +```java lines +callButtons.setVideoCallButtonVisibility(View.GONE); ``` - + + +### Custom button text + -```kotlin -cometChatCallButtons.setStyle(R.style.CustomCallButtonStyle) +```kotlin lines +callButtons.setVoiceButtonText("Audio Call") +callButtons.setVideoButtonText("Video Call") ``` - + +```java lines +callButtons.setVoiceButtonText("Audio Call"); +callButtons.setVideoButtonText("Video Call"); +``` + -*** +### Icon-only buttons -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_buttons.xml). + + +```kotlin lines +callButtons.setButtonTextVisibility(View.GONE) +``` + -### Functionality + +```java lines +callButtons.setButtonTextVisibility(View.GONE); +``` + + -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. +## Advanced Methods -Below is a list of customizations along with corresponding code snippets +### `setUser` / `setGroup` -| Property | Description | Code | -| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| **setUser** | Used to set User object to the call button | `.setUser(User user)` | -| **setGroup** | Used to set Group object to the call button | `.setGroup(group)` | -| **setVideoCallButtonVisibility** | Used to hide video call button | `.setVideoCallButtonVisibility(View.GONE)` | -| **setVoiceCallButtonVisibility** | Used to hide voice call button | `.setVoiceCallButtonVisibility(View.GONE)` | -| **setCallSettingsBuilder** | Sets the call settings builder callback function. This callback is responsible for configuring the call settings based on the user, group, and call type (audio/video). | `.setCallSettingsBuilder(Function3 callSettingsBuilder)` | -| **setOutgoingCallConfiguration** | Sets the configurations for outgoing call component. | `.setOutgoingCallConfiguration(new OutgoingCallConfiguration)` | +Binds the component to a specific user or group. Required before calls can be initiated. -### Advanced + + +```kotlin lines +// For 1-on-1 calls +callButtons.setUser(user) -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. +// For group calls +callButtons.setGroup(group) +``` + -The `CometChatCallButtons` component does not provide additional functionalities beyond this level of customization. + +```java lines +// For 1-on-1 calls +callButtons.setUser(user); -*** +// For group calls +callButtons.setGroup(group); +``` + + -## Configurations +### `setOutgoingCallConfiguration` -[Configurations](/ui-kit/android/components-overview#configurations) offer the ability to customize the properties of each individual component within a Composite Component. +Configures the outgoing call screen that appears after a call is initiated. -* `Configurations` expose properties that are available in its individual components. + + +```kotlin lines +val config = OutgoingCallConfiguration() +callButtons.setOutgoingCallConfiguration(config) +``` + -*** + +```java lines +OutgoingCallConfiguration config = new OutgoingCallConfiguration(); +callButtons.setOutgoingCallConfiguration(config); +``` + + -#### Outgoing Call +### `setCallSettingsBuilder` -You can customize the properties of the Outgoing Call component by making use of the `OutgoingCallConfiguration`. You can accomplish this by employing the `OutgoingCallConfiguration` as demonstrated below: +Provides a callback to customize call settings per call. The callback receives the `User`, `Group`, and a `Boolean` indicating whether the call is audio (`true`) or video (`false`), and returns a `CometChatCalls.CallSettingsBuilder`. + +```kotlin lines +callButtons.setCallSettingsBuilder { user, group, isAudio -> + CometChatCalls.CallSettingsBuilder(this, true) + .setIsAudioOnly(isAudio) +} +``` + + -```java -OutgoingCallConfiguration outgoingCallConfiguration = new OutgoingCallConfiguration(); +```java lines +callButtons.setCallSettingsBuilder((user, group, isAudio) -> { + return new CometChatCalls.CallSettingsBuilder(this, true) + .setIsAudioOnly(isAudio); +}); +``` + + + +### `getVoiceCallButton` / `getVideoCallButton` + +Returns the internal `CometChatButton` instances for direct customization. -cometchatCallButtons.setOutgoingCallConfiguration(outgoingCallConfiguration); +| Method | Returns | Description | +| --- | --- | --- | +| `getVoiceCallButton()` | `CometChatButton` | The voice call button instance | +| `getVideoCallButton()` | `CometChatButton` | The video call button instance | + +### `disposeObservers` + +Removes lifecycle observers manually. Normally handled automatically when the view detaches from the window. + + + +```kotlin lines +callButtons.disposeObservers() ``` + + +```java lines +callButtons.disposeObservers(); +``` + - -```kotlin -val outgoingCallConfiguration = OutgoingCallConfiguration() +## Style + +The component uses XML theme styles. Define a custom style with parent `CometChatCallButtonsStyle` in `themes.xml`, then apply with `setStyle()`. -cometchatCallButtons.setOutgoingCallConfiguration(outgoingCallConfiguration) +```xml themes.xml lines + ``` + + +```kotlin lines +callButtons.setStyle(R.style.CustomCallButtonsStyle) +``` + +```java lines +callButtons.setStyle(R.style.CustomCallButtonsStyle); +``` + -All exposed properties of `OutgoingCallConfiguration` can be found under [Outgoing Call](/ui-kit/android/outgoing-call). Properties marked with the 🛑 symbol are not accessible within the Configuration Object. +### Programmatic Style Properties + +In addition to XML theme styles, the component exposes programmatic setters for fine-grained control: + +| Method | Type | Description | +| --- | --- | --- | +| `setVoiceCallIcon` | `Drawable` | Icon drawable for the voice call button | +| `setVideoCallIcon` | `Drawable` | Icon drawable for the video call button | +| `setVoiceCallIconTint` | `@ColorInt int` | Tint color for the voice call icon | +| `setVideoCallIconTint` | `@ColorInt int` | Tint color for the video call icon | +| `setVoiceCallTextColor` | `@ColorInt int` | Text color for the voice call button | +| `setVideoCallTextColor` | `@ColorInt int` | Text color for the video call button | +| `setVoiceCallTextAppearance` | `@StyleRes int` | Text appearance for the voice call button | +| `setVideoCallTextAppearance` | `@StyleRes int` | Text appearance for the video call button | +| `setVoiceCallBackgroundColor` | `@ColorInt int` | Background color for the voice call button | +| `setVideoCallBackgroundColor` | `@ColorInt int` | Background color for the video call button | +| `setVoiceCallCornerRadius` | `@Dimension int` | Corner radius for the voice call button | +| `setVideoCallCornerRadius` | `@Dimension int` | Corner radius for the video call button | +| `setVoiceCallIconSize` | `@Dimension int` | Icon size for the voice call button | +| `setVideoCallIconSize` | `@Dimension int` | Icon size for the video call button | +| `setVoiceCallStrokeWidth` | `@Dimension int` | Stroke width for the voice call button | +| `setVideoCallStrokeWidth` | `@Dimension int` | Stroke width for the video call button | +| `setVoiceCallStrokeColor` | `@ColorInt int` | Stroke color for the voice call button | +| `setVideoCallStrokeColor` | `@ColorInt int` | Stroke color for the video call button | +| `setVoiceCallButtonPadding` | `@Dimension int` | Padding for the voice call button | +| `setVideoCallButtonPadding` | `@Dimension int` | Padding for the video call button | + +## Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override voice call tap behavior | Activity/Fragment | `setOnVoiceCallClick` | `setOnVoiceCallClick((u, g) -> { ... })` | +| Override video call tap behavior | Activity/Fragment | `setOnVideoCallClick` | `setOnVideoCallClick((u, g) -> { ... })` | +| Hide voice call button | Activity/Fragment | `setVoiceCallButtonVisibility(int)` | `setVoiceCallButtonVisibility(View.GONE)` | +| Hide video call button | Activity/Fragment | `setVideoCallButtonVisibility(int)` | `setVideoCallButtonVisibility(View.GONE)` | +| Hide button text labels | Activity/Fragment | `setButtonTextVisibility(int)` | `setButtonTextVisibility(View.GONE)` | +| Hide button icons | Activity/Fragment | `setButtonIconVisibility(int)` | `setButtonIconVisibility(View.GONE)` | +| Change button spacing | Activity/Fragment | `setMarginBetweenButtons(int)` | `setMarginBetweenButtons(24)` | +| Set custom button text | Activity/Fragment | `setVoiceButtonText` / `setVideoButtonText` | `setVoiceButtonText("Audio Call")` | +| Change voice call icon | Activity/Fragment | `setVoiceCallIcon(Drawable)` | `setVoiceCallIcon(drawable)` | +| Change video call icon | Activity/Fragment | `setVideoCallIcon(Drawable)` | `setVideoCallIcon(drawable)` | +| Change icon tint colors | Activity/Fragment | `setVoiceCallIconTint` / `setVideoCallIconTint` | `setVoiceCallIconTint(Color.GREEN)` | +| Change text colors | Activity/Fragment | `setVoiceCallTextColor` / `setVideoCallTextColor` | `setVoiceCallTextColor(Color.BLACK)` | +| Change background colors | Activity/Fragment | `setVoiceCallBackgroundColor` / `setVideoCallBackgroundColor` | `setVoiceCallBackgroundColor(Color.WHITE)` | +| Change corner radius | Activity/Fragment | `setVoiceCallCornerRadius` / `setVideoCallCornerRadius` | `setVoiceCallCornerRadius(16)` | +| Change icon size | Activity/Fragment | `setVoiceCallIconSize` / `setVideoCallIconSize` | `setVoiceCallIconSize(48)` | +| Change stroke width | Activity/Fragment | `setVoiceCallStrokeWidth` / `setVideoCallStrokeWidth` | `setVoiceCallStrokeWidth(2)` | +| Change stroke color | Activity/Fragment | `setVoiceCallStrokeColor` / `setVideoCallStrokeColor` | `setVoiceCallStrokeColor(Color.GRAY)` | +| Change button padding | Activity/Fragment | `setVoiceCallButtonPadding` / `setVideoCallButtonPadding` | `setVoiceCallButtonPadding(12)` | +| Apply XML theme style | `themes.xml` | `CometChatCallButtonsStyle` | `#4CAF50` | +| Apply style programmatically | Activity/Fragment | `setStyle(int styleRes)` | `callButtons.setStyle(R.style.CustomCallButtonsStyle)` | +| Configure outgoing call screen | Activity/Fragment | `setOutgoingCallConfiguration` | `setOutgoingCallConfiguration(config)` | +| Custom call settings per call | Activity/Fragment | `setCallSettingsBuilder` | See `setCallSettingsBuilder` code above | +| Access internal buttons | Activity/Fragment | `getVoiceCallButton()` / `getVideoCallButton()` | `callButtons.getVoiceCallButton()` | + +## Accessibility + +The component renders two `CometChatButton` instances inside a `MaterialCardView`. Each button responds to tap gestures. The voice and video call icons include default content descriptions for screen readers. + +For custom icons set via `setVoiceCallIcon` or `setVideoCallIcon`, ensure you set `android:contentDescription` on the drawable or on the button view so TalkBack can announce the action. The default icons handle this automatically. + +Button text labels (when visible) provide additional context for assistive technologies. If you hide text with `setButtonTextVisibility(View.GONE)`, consider adding explicit content descriptions to the buttons via `getVoiceCallButton().setContentDescription(...)`. + +## Next Steps + + + + View call history + + + Display user/group info in the toolbar + + + Browse recent conversations + + + Incoming call notification with accept/reject + + \ No newline at end of file diff --git a/ui-kit/android/call-features.mdx b/ui-kit/android/call-features.mdx index a5deb296e..6cd893bf6 100644 --- a/ui-kit/android/call-features.mdx +++ b/ui-kit/android/call-features.mdx @@ -1,8 +1,20 @@ --- title: "Call" +description: "Add one-on-one and group audio/video calling to your Android app using the CometChat Calls SDK and UI Kit." --- -## Overview + + +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` + `com.cometchat:calls-sdk-android` (`implementation 'com.cometchat:calls-sdk-android:4.+.+'`) | +| Required setup | `CometChatUIKit.init()` then `CometChatUIKit.login()` — Calls SDK must also be installed | +| Call features | Incoming Call, Outgoing Call, Call Logs, Call Buttons | +| Key components | `CometChatCallButtons` → [Call Buttons](/ui-kit/android/call-buttons), `CometChatIncomingCall` → [Incoming Call](/ui-kit/android/incoming-call), `CometChatOutgoingCall` → [Outgoing Call](/ui-kit/android/outgoing-call), `CometChatCallLogs` → [Call Logs](/ui-kit/android/call-logs) | +| Auto-detection | UI Kit automatically detects the Calls SDK and enables call UI components | +| Related | [Getting Started](/ui-kit/android/getting-started), [Core Features](/ui-kit/android/core-features), [Call Log Details Guide](/ui-kit/android/guide-call-log-details) | + + CometChat's Calls feature is an advanced functionality that allows you to seamlessly integrate one-on-one as well as group audio and video calling capabilities into your application. This document provides a technical overview of these features, as implemented in the Android UI Kit. @@ -10,53 +22,121 @@ CometChat's Calls feature is an advanced functionality that allows you to seamle First, make sure that you've correctly integrated the UI Kit library into your project. If you haven't done this yet or are facing difficulties, refer to our [Getting Started](/ui-kit/android/getting-started) guide. This guide will walk you through a step-by-step process of integrating our UI Kit into your Android project. -Once you've successfully integrated the UI Kit, the next step is to add the CometChat Calls SDK to your project. This is necessary to enable the calling features in the UI Kit. Here's how you do it: +Once you've successfully integrated the UI Kit, the next step is to add the CometChat Calls SDK to your project. This is necessary to enable the calling features in the UI Kit. + +### Step 1: Add Calls SDK Dependency -Add the following dependency to your build.gradle file: +Add the following dependency to your `build.gradle` file: -```javascript +```gradle lines dependencies { implementation 'com.cometchat:calls-sdk-android:4.+.+' } ``` -After adding this dependency, the Android UI Kit will automatically detect it and activate the calling features. Now, your application supports both audio and video calling. You will see [CallButtons](/ui-kit/android/call-buttons) component rendered in [MessageHeader](/ui-kit/android/message-header) Component. +After adding this dependency, sync your project. The Android UI Kit will automatically detect the Calls SDK and activate the calling features. + +### Step 2: Verify Call Buttons Appear + +Once the Calls SDK is integrated, you will see the [CallButtons](/ui-kit/android/call-buttons) component automatically rendered in the [MessageHeader](/ui-kit/android/message-header) component. This provides users with quick access to initiate audio and video calls. -To start receive calls globally in your app you will need to add `CallListener`, This needs to be added before the you initialize CometChat UI kit, We sudgest you making a custom Application class and adding call listener. +### Step 3: Add Call Listener for Incoming Calls + +To receive incoming calls globally in your app, you will need to add a `CallListener`. This should be added before you initialize the CometChat UI Kit. We recommend creating a custom Application class and adding the call listener there. + +When an incoming call is received, you can display the `CometChatIncomingCall` component using the current activity context. + +```kotlin lines +class BaseApplication : Application() { + + companion object { + private val LISTENER_ID = "${BaseApplication::class.java.simpleName}${System.currentTimeMillis()}" + } + + override fun onCreate() { + super.onCreate() + + CometChat.addCallListener(LISTENER_ID, object : CometChat.CallListener { + override fun onIncomingCallReceived(call: Call) { + // Get the current activity context + val currentActivity = getCurrentActivity() // Implement this method + + currentActivity?.let { + // Create and display the incoming call component + val incomingCallView = CometChatIncomingCall(it) + incomingCallView.call = call + incomingCallView.fitsSystemWindows = true + incomingCallView.onError = OnError { exception -> + // Handle errors + } + + // Display the component (e.g., as dialog or snackbar) + } + } + + override fun onOutgoingCallAccepted(call: Call) { + // Handle outgoing call acceptance + } + + override fun onOutgoingCallRejected(call: Call) { + // Handle outgoing call rejection + } + + override fun onIncomingCallCancelled(call: Call) { + // Handle incoming call cancellation + } + }) + } +} +``` + + + -```java +```java lines public class BaseApplication extends Application { - private static String LISTENER_ID = BaseApplication.class.getSimpleName()+System.currentTimeMillis(); + private static final String LISTENER_ID = BaseApplication.class.getSimpleName() + System.currentTimeMillis(); @Override public void onCreate() { super.onCreate(); + CometChat.addCallListener(LISTENER_ID, new CometChat.CallListener() { @Override public void onIncomingCallReceived(Call call) { - CometChatCallActivity.launchIncomingCallScreen(BaseApplication.this, call, null); //pass null or IncomingCallConfiguration if need to configure CometChatIncomingCall component + // Get the current activity context + Activity currentActivity = getCurrentActivity(); // Implement this method + + if (currentActivity != null) { + // Create and display the incoming call component + CometChatIncomingCall incomingCallView = new CometChatIncomingCall(currentActivity); + incomingCallView.setCall(call); + incomingCallView.setFitsSystemWindows(true); + + // Display the component (e.g., as dialog or snackbar) + } } @Override public void onOutgoingCallAccepted(Call call) { - + // Handle outgoing call acceptance } @Override public void onOutgoingCallRejected(Call call) { - + // Handle outgoing call rejection } @Override public void onIncomingCallCancelled(Call call) { - + // Handle incoming call cancellation } }); } @@ -65,67 +145,54 @@ public class BaseApplication extends Application { - -```kotlin -class BaseApplication : Application() { - companion object { - private val LISTENER_ID = "${BaseApplication::class.java.simpleName}${System.currentTimeMillis()}" - } + - override fun onCreate() { - super.onCreate() - CometChat.addCallListener(LISTENER_ID, object : CometChat.CallListener { - override fun onIncomingCallReceived(call: Call) { - CometChatCallActivity.launchIncomingCallScreen(this@BaseApplication, call, null) - // Pass null or IncomingCallConfiguration if need to configure CometChatIncomingCall component - } +## Call Components - override fun onOutgoingCallAccepted(call: Call) { - // To be implemented - } +The CometChat Android UI Kit provides four main components for implementing calling features in your app. Each component handles a specific part of the calling experience. - override fun onOutgoingCallRejected(call: Call) { - // To be implemented - } +### Call Buttons - override fun onIncomingCallCancelled(call: Call) { - // To be implemented - } - }) - } -} -``` +The [Call Buttons](/ui-kit/android/call-buttons) component provides users with quick access to initiate audio and video calls. This component is automatically rendered in the [MessageHeader](/ui-kit/android/message-header) when the Calls SDK is integrated. - - - + + + -## Features +[Learn more about Call Buttons →](/ui-kit/android/call-buttons) ### Incoming Call -The [Incoming Call](/ui-kit/android/incoming-call) component of the CometChat UI Kit provides the functionality that lets users receive real-time audio and video calls in the app. - -When a call is made to a user, the Incoming Call component triggers and displays a call screen. This call screen typically displays the caller information and provides the user with options to either accept or reject the incoming call. +The [Incoming Call](/ui-kit/android/incoming-call) component displays when a user receives an incoming call. It provides a full-screen interface showing caller information and call controls. -### Outgoing Call +[Learn more about Incoming Call →](/ui-kit/android/incoming-call) -The [Outgoing Call](/ui-kit/android/outgoing-call) component of the CometChat UI Kit is designed to manage the outgoing call process within your application. When a user initiates an audio or video call to another user or group, this component displays an outgoing call screen, showcasing information about the recipient and the call status. +### Outgoing Call -Importantly, the Outgoing Call component is smartly designed to transition automatically into the ongoing call screen once the receiver accepts the call. This ensures a smooth flow from initiating the call to engaging in a conversation, without any additional steps required from the user. +The [Outgoing Call](/ui-kit/android/outgoing-call) component manages the outgoing call experience. It displays while waiting for the recipient to answer and automatically transitions to the active call screen once accepted. +[Learn more about Outgoing Call →](/ui-kit/android/outgoing-call) + ### Call Logs -[Call Logs](/ui-kit/android/call-logs) component provides you with the records call events such as who called who, the time of the call, and the duration of the call. This information can be fetched from the CometChat server and displayed in a structured format for users to view their past call activities. +The [Call Logs](/ui-kit/android/call-logs) component displays a history of all call activities, including missed, received, and dialed calls. Users can view call details and initiate new calls from the log. + + +[Learn more about Call Logs →](/ui-kit/android/call-logs) + +### Call Log Details + +For detailed information about individual calls, including participants, join/leave history, and recordings, see the [Call Log Details](/ui-kit/android/guide-call-log-details) guide. + diff --git a/ui-kit/android/call-logs.mdx b/ui-kit/android/call-logs.mdx index 6b3038497..e38f5223b 100644 --- a/ui-kit/android/call-logs.mdx +++ b/ui-kit/android/call-logs.mdx @@ -1,751 +1,949 @@ --- title: "Call Logs" +description: "Scrollable list of call logs for the logged-in user with caller names, avatars, call status, and timestamps." --- + + +```json +{ + "component": "CometChatCallLogs", + "package": "com.cometchat.chatuikit.calls.calllogs", + "xmlElement": "", + "description": "Scrollable list of call logs for the logged-in user with caller names, avatars, call status, and timestamps.", + "primaryOutput": { + "method": "setOnItemClick", + "type": "OnItemClick" + }, + "methods": { + "data": { + "setCallLogRequestBuilder": { + "type": "CallLogRequest.CallLogRequestBuilder", + "default": "SDK default", + "note": "Pass the builder, not the result of .build()" + } + }, + "callbacks": { + "setOnItemClick": "OnItemClick", + "setOnItemLongClick": "OnItemLongClick", + "setOnBackPressListener": "OnBackPress", + "setOnCallIconClickListener": "OnCallIconClick", + "setOnError": "OnCallError", + "setOnLoad": "OnLoad", + "setOnEmpty": "OnEmpty" + }, + "visibility": { + "setToolbarVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.VISIBLE" }, + "setBackIconVisibility": { "type": "int", "default": "View.GONE" }, + "setLoadingStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setErrorStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setEmptyStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setSeparatorVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setTitleVisibility": { "type": "int", "default": "View.VISIBLE" } + }, + "viewSlots": { + "setItemView": "CallLogsViewHolderListener — entire list item row", + "setLeadingView": "CallLogsViewHolderListener — avatar / left section", + "setTitleView": "CallLogsViewHolderListener — name / title text", + "setSubtitleView": "CallLogsViewHolderListener — subtitle text below name", + "setTrailingView": "CallLogsViewHolderListener — right section", + "setLoadingView": "@LayoutRes int — loading spinner", + "setEmptyView": "@LayoutRes int — empty state", + "setErrorView": "@LayoutRes int — error state", + "setOptions": "Function2> — long-press context menu (replaces defaults)", + "setAddOptions": "Function2> — long-press context menu (appends to defaults)" + }, + "advanced": { + "refreshCallLogs": "void — re-fetches call logs from the server", + "setDateFormat": "SimpleDateFormat — legacy date format setter", + "setDateTimeFormatter": "DateTimeFormatterCallback — custom date/time formatting", + "getBinding": "CometchatCallLogsBinding — root ViewBinding", + "getViewModel": "CallLogsViewModel — internal ViewModel access", + "getAdapter": "CallLogsAdapter — internal adapter access", + "setAdapter": "CallLogsAdapter — replace the default adapter" + }, + "style": { + "setStyle": { + "type": "@StyleRes int", + "parent": "CometChatCallLogsStyle" + } + } + }, + "events": [], + "sdkListeners": [] +} +``` -## Overview + -`CometChatCallLogs` is a [Component](/ui-kit/android/components-overview#components) that shows the list of Call Logs available. By default, names are shown for all listed users, along with their avatars if available. +## Where It Fits - - - +`CometChatCallLogs` is a list component. It renders all call logs for the logged-in user and emits the selected `CallLog` via `setOnItemClick`. Wire it to a call detail screen or use `setOnCallIconClickListener` to initiate a callback. -## Usage + + +```kotlin CallDetailActivity.kt lines +class CallDetailActivity : AppCompatActivity() { -### Integration + private lateinit var callLogs: CometChatCallLogs -`CometChatCallLogs` being a wrapper component, offers versatility in its integration. It can be seamlessly launched via button clicks or any user-triggered action, enhancing the overall user experience and facilitating smoother interactions within the application. + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_call_detail) -Since `CometChatCallLogs` can be launched by adding the following code snippet to the XML layout file. + callLogs = findViewById(R.id.call_log) - - -```xml - -``` + callLogs.setOnItemClick { view, position, callLog -> + // Navigate to call detail screen with the selected callLog + } + callLogs.setOnCallIconClickListener { view, holder, position, callLog -> + // Initiate a call using the callLog data + } + } +} +``` - + +```java CallDetailActivity.java lines +public class CallDetailActivity extends AppCompatActivity { -If you're defining the `CometChatCallLogs` within the XML code or in your activity or fragment then you'll need to extract them and set them on the User object using the appropriate method. + private CometChatCallLogs callLogs; - - -```java -CometChatCallLogs cometchatCallLogs = binding.callLog; // 'binding' is a view binding instance. Initialize it with `binding = YourXmlFileNameBinding.inflate(getLayoutInflater());` to use views like `binding.callLog` after enabling view binding. -``` + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_call_detail); - + callLogs = findViewById(R.id.call_log); - -```kotlin -val cometchatCallLogs: CometChatCallLogs = binding.callLog // 'binding' is a view binding instance. Initialize it with `binding = YourXmlFileNameBinding.inflate(layoutInflater)` to use views like `binding.callLog` after enabling view binding. -``` + callLogs.setOnItemClick((view, position, callLog) -> { + // Navigate to call detail screen with the selected callLog + }); + callLogs.setOnCallIconClickListener((view, holder, position, callLog) -> { + // Initiate a call using the callLog data + }); + } +} +``` - -##### Activity and Fragment +## Quick Start + +Add the component to your layout XML: + +```xml layout_activity.xml lines + +``` + + + + -You can integrate `CometChatCallLogs` into your Activity and Fragment by adding the following code snippets into the respective classes. +Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()`, a user logged in, and the `cometchat-chat-uikit-android` dependency added. + +To add programmatically in an Activity: - -```java YourActivity.java -CometChatCallLogs cometchatCallLogs; + +```kotlin YourActivity.kt lines +override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(CometChatCallLogs(this)) +} +``` + + +```java YourActivity.java lines @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - cometchatCallLogs = new CometChatCallLogs(this); - - setContentView(cometchatCallLogs); + setContentView(new CometChatCallLogs(this)); } ``` - + - -```kotlin YourActivity.kt -private lateinit var cometchatCallLogs: CometChatCallLogs - -override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - cometchatCallLogs = CometChatCallLogs(this); +Or in a Fragment: - setContentView(cometchatCallLogs) + + +```kotlin YourFragment.kt lines +override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return CometChatCallLogs(requireContext()) } ``` - - -```java YourFragment.java -CometChatCallLogs cometchatCallLogs; - + +```java YourFragment.java lines @Override -public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - - cometchatCallLogs = new CometChatCallLogs(requireContext()); - - return cometchatCallLogs; +public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return new CometChatCallLogs(getContext()); } ``` - + - -```kotlin YourFragment.kt -private lateinit var cometchatCallLogs: CometChatCallLogs - -override fun onCreateView( - inflater: LayoutInflater?, container: ViewGroup?, - savedInstanceState: Bundle? -): View { +## Filtering Call Logs - cometchatCallLogs = new CometChatCallLogs(requireContext()); +Pass a `CallLogRequest.CallLogRequestBuilder` to `setCallLogRequestBuilder`. Pass the builder instance — not the result of `.build()`. - return cometchatCallLogs -} + + +```kotlin lines +val builder = CallLogRequest.CallLogRequestBuilder() + .setLimit(20) + .setHasRecording(true) +cometchatCallLogs.setCallLogRequestBuilder(builder) ``` - + +```java lines +CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder() + .setLimit(20) + .setHasRecording(true); +cometchatCallLogs.setCallLogRequestBuilder(builder); +``` + -### Actions +### Filter Recipes -[Actions](/ui-kit/android/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +| Recipe | Code | +| --- | --- | +| Limit to 20 per page | `builder.setLimit(20)` | +| Audio calls only | `builder.setCallType(CometChatCallsConstants.CALL_TYPE_AUDIO)` | +| Video calls only | `builder.setCallType(CometChatCallsConstants.CALL_TYPE_VIDEO)` | +| Missed calls only | `builder.setCallStatus(CometChatCallsConstants.CALL_STATUS_MISSED)` | +| Calls with recordings | `builder.setHasRecording(true)` | +| Incoming calls only | `builder.setCallDirection("incoming")` | +| Outgoing calls only | `builder.setCallDirection("outgoing")` | +| Filter by user UID | `builder.setUid("uid1")` | +| Filter by group GUID | `builder.setGuid("guid1")` | +| Filter by call category | `builder.setCallCategory("call")` | -##### setOnItemClick +> The component uses infinite scroll — the next page loads as the user scrolls to the bottom. -Function invoked when a call log item is clicked, typically used to open a detailed chat screen. +## Actions and Events - - -```java YourActivity.java -cometchatCallLogs.setOnItemClick((view1, position, callLog) -> { - - }); -``` +### Callback Methods - +#### `setOnItemClick` + +Fires when a call log row is tapped. Primary navigation hook — use to open a call detail screen. + -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatCallLogs.onItemClick = OnItemClick { view, position, callLog -> - } +} ``` - + +```java YourActivity.java lines +cometchatCallLogs.setOnItemClick((view1, position, callLog) -> { + +}); +``` + -*** +> **What this does:** Replaces the default item-click behavior. When a user taps a call log entry, your custom lambda executes instead of the built-in navigation. -##### setOnItemLongClick +#### `setOnItemLongClick` -Function executed when a callLog item is long-pressed, allowing additional actions like delete or select. +Fires when a call log row is long-pressed. Use for additional actions like delete or call back. - -```java YourActivity.java -cometchatCallLogs.setOnItemLongClick((view1, position, callLog) -> { - - }); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatCallLogs.onItemLongClick = OnItemLongClick({ view, position, callLog -> - }) +}) ``` - - + +```java YourActivity.java lines +cometchatCallLogs.setOnItemLongClick((view1, position, callLog) -> { -*** +}); +``` + + -##### setOnBackPressListener +#### `setOnBackPressListener` -`OnBackPressListener` is triggered when you press the back button in the app bar. It has a predefined behavior; when clicked, it navigates to the previous activity. However, you can override this action using the following code snippet. +Fires when the user presses the back button in the app bar. Default: navigates to the previous activity. - -```java YourActivity.java -cometchatCallLogs.setOnBackPressListener(() -> { - - }); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatCallLogs.onBackPressListener = OnBackPress { - } +} ``` - + +```java YourActivity.java lines +cometchatCallLogs.setOnBackPressListener(() -> { + +}); +``` + -*** +#### `setOnCallIconClickListener` -##### OnError +Fires when the user taps the audio or video call icon on a call log item. Use to initiate a call or navigate to a call screen. -This action doesn't change the behavior of the component but rather listens for any errors that occur in the callLogs component. +Interface: `void onCallIconClick(View view, CallLogsAdapter.CallLogsViewHolder holder, int position, CallLog callLog)` - -```java YourActivity.java -cometchatCallLogs.setOnError(cometchatException -> { - - }); + +```kotlin YourActivity.kt lines +cometchatCallLogs.setOnCallIconClickListener { view, holder, position, callLog -> + // Handle call icon click +} ``` - - -```kotlin YourActivity.kt -cometchatCallLogs.setOnError { - - } + +```java YourActivity.java lines +cometchatCallLogs.setOnCallIconClickListener((view, holder, position, callLog) -> { + // Handle call icon click +}); ``` - - -*** +#### `setOnError` -##### setOnLoad - -Invoked when the list is successfully fetched and loaded, helping track component readiness. +Fires on internal errors (network failure, auth issue, SDK exception). + +```kotlin YourActivity.kt lines +cometchatCallLogs.setOnError { + +} +``` + + -```java YourActivity.java -cometchatCallLogs.setOnLoad(list -> { +```java YourActivity.java lines +cometchatCallLogs.setOnError(cometchatException -> { }); ``` - + + +#### `setOnLoad` +Fires when the list is successfully fetched and loaded. + + -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatCallLogs.setOnLoad(object : OnLoad { override fun onLoad(list: MutableList?) { } }) ``` - - + +```java YourActivity.java lines +cometchatCallLogs.setOnLoad(list -> { -*** +}); +``` + + -##### setOnEmpty +#### `setOnEmpty` -Called when the list is empty, enabling custom handling such as showing a placeholder message. +Fires when the list is empty, enabling custom handling such as showing a placeholder. - -```java YourActivity.java -cometchatCallLogs.setOnEmpty(() -> { + +```kotlin YourActivity.kt lines +cometchatCallLogs.setOnEmpty { - }); +} ``` - - -```kotlin YourActivity.kt -cometchatCallLogs.setOnEmpty{ + +```java YourActivity.java lines +cometchatCallLogs.setOnEmpty(() -> { - } +}); ``` - - -*** - -### Filters +- **Verify**: After setting an action callback, trigger the corresponding user interaction (tap, long-press, back, call icon) and confirm your custom logic executes instead of the default behavior. -**Filters** allow you to customize the data displayed in a list within a Component. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using RequestBuilders of Chat SDK. +### Global UI Events -##### 1. CallLogRequestBuilder +The `CometChatCallLogs` component does not have any exposed global UI events. -The [CallLogRequestBuilder](/sdk/android/call-logs) enables you to filter and customize the call list based on available parameters in CallLogRequestBuilder. This feature allows you to create more specific and targeted queries during the call. The following are the parameters available in [CallLogRequestBuilder](/sdk/android/call-logs) +### SDK Events (Real-Time, Automatic) -**Example** +The `CometChatCallLogs` component does not listen to any SDK events internally. Call logs are fetched on load and can be refreshed manually with `refreshCallLogs()`. -In the example below, we are applying a filter based on the limit and have a call recording. +## Functionality - - -```java -CallLogRequest.CallLogRequestBuilder callLogRequestBuilder = new CallLogRequest.CallLogRequestBuilder() - .setLimit(20) - .setHasRecording(true); - -cometchatCallLogs.setCallLogRequestBuilder(callLogRequestBuilder); -``` - - +Small functional customizations such as toggling visibility of UI elements. - -```kotlin -val callLogRequestBuilder = CallLogRequestBuilder() - .setLimit(20) - .setHasRecording(true) +| Methods | Description | Code | +| --- | --- | --- | +| `setToolbarVisibility` | Toggles visibility for the toolbar in the app bar | `.setToolbarVisibility(View.GONE);` | +| `setBackIconVisibility` | Toggles visibility for the back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | +| `setLoadingStateVisibility` | Hides the loading state while fetching call logs | `.setLoadingStateVisibility(View.GONE);` | +| `setErrorStateVisibility` | Hides the error state on fetching call logs | `.setErrorStateVisibility(View.GONE);` | +| `setEmptyStateVisibility` | Hides the empty state on fetching call logs | `.setEmptyStateVisibility(View.GONE);` | +| `setSeparatorVisibility` | Controls visibility of separators in the list view | `.setSeparatorVisibility(View.GONE);` | +| `setTitleVisibility` | Controls visibility of the title in the toolbar | `.setTitleVisibility(View.GONE);` | -cometchatCallLogs.setCallLogRequestBuilder(callLogRequestBuilder) -``` +- **Verify**: After calling a visibility method, confirm the corresponding UI element is shown or hidden. - +## Custom View Slots - +Each slot replaces a section of the default UI. Slots that accept a `CallLog` parameter receive the call log object for that row via the `CallLogsViewHolderListener` pattern (`createView` + `bindView`). -| Property | Description | Code | -| ------------------ | --------------------------------------------------- | ----------------------------------------- | -| **Limit** | Sets the limit for the call logs request | `.setLimit(int limit)` | -| **Call Type** | Sets the call type for the call logs request | `.setCallType(String callType)` | -| **Call Status** | Sets the call status for the call logs request | `.setCallStatus(String callStatus)` | -| **Has Recording** | Sets the recording status for the call logs request | `.setHasRecording(boolean hasRecording)` | -| **Call Direction** | Sets the call direction for the call logs request | `.setCallDirection(String callDirection)` | -| **UID** | Sets the user ID for the call logs request | `.setUid(String uid)` | -| **GUID** | Sets the group ID for the call logs request | `.setGuid(String guid)` | -| **Call Category** | Sets the call category for the call logs request | `.setCallCategory(String callCategory)` | -| **Auth Token** | Sets the auth token for the call logs request | `.setAuthToken(String authToken)` | +| Slot | Method | Replaces | +| --- | --- | --- | +| Leading view | `setLeadingView(CallLogsViewHolderListener)` | Avatar / left section | +| Title view | `setTitleView(CallLogsViewHolderListener)` | Name / title text | +| Subtitle view | `setSubtitleView(CallLogsViewHolderListener)` | Subtitle text below name | +| Trailing view | `setTrailingView(CallLogsViewHolderListener)` | Right section | +| Item view | `setItemView(CallLogsViewHolderListener)` | Entire list item row | +| Loading view | `setLoadingView(@LayoutRes int)` | Loading spinner | +| Empty view | `setEmptyView(@LayoutRes int)` | Empty state | +| Error view | `setErrorView(@LayoutRes int)` | Error state | +| Options (replace) | `setOptions(Function2)` | Long-press context menu (replaces defaults) | +| Options (append) | `setAddOptions(Function2)` | Long-press context menu (appends to defaults) | -*** +### `setLeadingView` -### Events +Replace the avatar / left section. -[Events](/ui-kit/android/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. + + +```kotlin lines +cometchatCallLogs.setLeadingView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return CometChatAvatar(context) + } -The `CometChatCallLogs` component does not have any exposed events. + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + } +}) +``` + -*** + +```java lines +cometchatCallLogs.setLeadingView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new CometChatAvatar(context); + } -## Customization + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { -To fit your app's design requirements, you can customize the appearance of the CallLog component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. + } +}); +``` + + -### Style +> **What this does:** Registers a `CallLogsViewHolderListener` that provides a custom view for the leading (left) area of each call log item. `createView` inflates your layout, and `bindView` populates it with call log data. -Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component. +Example with call direction icons: - + -```xml themes.xml - + + +```kotlin YourActivity.kt lines +cometchatCallLogs.setLeadingView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return CometChatAvatar(context) + } - + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + val avatar = createdView as CometChatAvatar + + if (callLog.initiator is CallUser) { + val initiator = callLog.initiator as CallUser + val isLoggedInUser = CallUtils.isLoggedInUser(initiator) + val isMissedOrUnanswered = callLog.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (callLog + .status + == CometChatCallsConstants.CALL_STATUS_MISSED) + + if (callLog.type == CometChatCallsConstants.CALL_TYPE_AUDIO || (callLog + .type + == CometChatCallsConstants.CALL_TYPE_VIDEO) || callLog.type == CometChatCallsConstants.CALL_TYPE_AUDIO_VIDEO + ) { + if (isLoggedInUser) { + avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.outgoing_voice_call, null)!!) + } else if (isMissedOrUnanswered) { + avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.miss_call, null)!!) + } else { + avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.incoming_voice_call, null)!!) + } + } + } + val layoutParams = LinearLayout.LayoutParams( + Utils.convertDpToPx(context, 50), + Utils.convertDpToPx(context, 50) + ) + avatar.layoutParams = layoutParams + } +}) ``` + - -```java -cometchatCallLogs.setStyle(R.style.CustomCallLogStyle); -``` - - +```java YourActivity.java lines +cometchatCallLogs.setLeadingView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new CometChatAvatar(context); + } - -```kotlin -cometchatCallLogs.setStyle(R.style.CustomCallLogStyle) + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { + CometChatAvatar avatar = (CometChatAvatar) createdView; + + if (callLog.getInitiator() instanceof CallUser) { + CallUser initiator = (CallUser) callLog.getInitiator(); + boolean isLoggedInUser = CallUtils.isLoggedInUser(initiator); + boolean isMissedOrUnanswered = callLog.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || callLog + .getStatus() + .equals(CometChatCallsConstants.CALL_STATUS_MISSED); + + if (callLog.getType().equals(CometChatCallsConstants.CALL_TYPE_AUDIO) || callLog + .getType() + .equals(CometChatCallsConstants.CALL_TYPE_VIDEO) || callLog.getType().equals(CometChatCallsConstants.CALL_TYPE_AUDIO_VIDEO)) { + + if (isLoggedInUser) { + avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.outgoing_voice_call, null)); + } else if (isMissedOrUnanswered) { + avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.miss_call, null)); + } else { + avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.incoming_voice_call, null)); + } + } + } + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + Utils.convertDpToPx(context, 50), + Utils.convertDpToPx(context, 50) + ); + avatar.setLayoutParams(layoutParams); + } +}); ``` - - -*** - -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_logs.xml). - -### Functionality - -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. - -| Methods | Description | Code | -| ------------------------- | --------------------------------------------------------- | ---------------------------------------- | -| setBackIconVisibility | Used to toggle visibility for back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | -| setToolbarVisibility | Used to toggle visibility for back button in the app bar | `.setToolbarVisibility(View.GONE);` | -| setLoadingStateVisibility | Used to hide loading state while fetching Users | `.setLoadingStateVisibility(View.GONE);` | -| setErrorStateVisibility | Used to hide error state on fetching conversations | `.setErrorStateVisibility(View.GONE);` | -| setEmptyStateVisibility | Used to hide empty state on fetching conversations | `.setEmptyStateVisibility(View.GONE);` | -| setSeparatorVisibility | Used to control visibility of Separators in the list view | `.setSeparatorVisibility(View.GONE);` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -#### setOptions +### `setTitleView` -Defines the available actions users can perform on a call log entry, such as deleting, marking as spam, or calling back. +Replace the name / title text. -Use Cases: + + +```kotlin lines +cometchatCallLogs.setTitleView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return TextView(context) + } -* Provide quick call-back options. -* Allow users to block a number. -* Enable deleting multiple call logs. + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + } +}) +``` + - -```java -cometchatConversations.setOptions((context, conversation) -> Collections.emptyList()); -``` +```java lines +cometchatCallLogs.setTitleView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new TextView(context); + } - + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { - -```kotlin -cometchatConversations.options = Function2?> { context, conversation -> emptyList() } + } +}); ``` - - -*** - -#### addOptions +Inline call duration example: -Adds custom actions to the existing call log options. - -Use Cases: - -* Add favorite/star call log option. -* Integrate a "Send Message" option. -* Provide an archive feature. + + + - -```java -cometchatConversations.addOptions((context, conversation) -> Collections.emptyList()); -``` + +```kotlin YourActivity.kt lines +cometchatCallLogs.setTitleView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return TextView(context) + } + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + val textView = createdView as TextView + textView.setTextAppearance(CometChatTheme.getTextAppearanceHeading4Regular(context)) + textView.setTextColor(CometChatTheme.getTextColorPrimary(context)) + CallUtils.getCallLogUserName(callLog) + if (callLog.totalDurationInMinutes > 0) { + val duration = callLog.totalDurationInMinutes.toString() + textView.text = CallUtils.getCallLogUserName(callLog) + " • \uD83D\uDD5A\uFE0F " + duration + .substring(0, if (duration.length > 4) 4 else 3) + " mins" + } else textView.text = CallUtils.getCallLogUserName(callLog) + } +}) +``` - -```kotlin -cometchatConversations.addOptions { context, conversation -> emptyList() } -``` + +```java YourActivity.java lines +cometchatCallLogs.setTitleView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new TextView(context); + } + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { + TextView textView = (TextView) createdView; + textView.setTextAppearance(CometChatTheme.getTextAppearanceHeading4Regular(context)); + textView.setTextColor(CometChatTheme.getTextColorPrimary(context)); + CallUtils.getCallLogUserName(callLog); + if (callLog.getTotalDurationInMinutes() > 0) { + String duration = String.valueOf(callLog.getTotalDurationInMinutes()); + textView.setText(CallUtils.getCallLogUserName(callLog) + " • \uD83D\uDD5A\uFE0F " + duration + .substring(0, duration.length() > 4 ? 4 : 3) + " mins"); + } else textView.setText(CallUtils.getCallLogUserName(callLog)); + } +}); +``` - -*** - -#### setDateTimeFormatter - -By providing a custom implementation of the DateTimeFormatterCallback, you can configure how time and date values are displayed. This ensures consistent formatting for labels such as "Today", "Yesterday", "X minutes ago", and more. +### `setSubtitleView` -Each method in the interface corresponds to a specific case: - -`time(long timestamp)` → Custom full timestamp format - -`today(long timestamp)` → Called when a message is from today - -`yesterday(long timestamp)` → Called for yesterday’s messages - -`lastWeek(long timestamp)` → Messages from the past week - -`otherDays(long timestamp)` → Older messages - -`minute(long timestamp)` / `hour(long timestamp)` → Exact time unit - -`minutes(long diffInMinutesFromNow, long timestamp)` → e.g., "5 minutes ago" - -`hours(long diffInHourFromNow, long timestamp)` → e.g., "2 hours ago" +Replace the subtitle text below the caller's name. - -```java -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - - -cometchatCallLogs.setDateTimeFormatter(new DateTimeFormatterCallback() { - - private final SimpleDateFormat fullTimeFormatter = new SimpleDateFormat("hh:mm a", Locale.getDefault()); - private final SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()); - - @Override - public String time(long timestamp) { - return fullTimeFormatter.format(new Date(timestamp)); - } - - @Override - public String today(long timestamp) { - return "Today"; - } - - @Override - public String yesterday(long timestamp) { - return "Yesterday"; - } - - @Override - public String lastWeek(long timestamp) { - return "Last Week"; - } - - @Override - public String otherDays(long timestamp) { - return dateFormatter.format(new Date(timestamp)); - } - - @Override - public String minutes(long diffInMinutesFromNow, long timestamp) { - return diffInMinutesFromNow + " mins ago"; - } + +```kotlin lines +cometchatCallLogs.setSubtitleView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return TextView(context) + } - @Override - public String hours(long diffInHourFromNow, long timestamp) { - return diffInHourFromNow + " hrs ago"; - } - }); + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + } +}) ``` - - -```kotlin -import java.text.SimpleDateFormat -import java.util.* - -cometchatCallLogs.setDateTimeFormatterCallback(object : DateTimeFormatterCallback { + +```java lines +cometchatCallLogs.setSubtitleView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new TextView(context); + } - private val fullTimeFormatter = SimpleDateFormat("hh:mm a", Locale.getDefault()) - private val dateFormatter = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()) + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { - override fun time(timestamp: Long): String { - return fullTimeFormatter.format(Date(timestamp)) - } + } +}); +``` + + - override fun today(timestamp: Long): String { - return "Today" - } +Example with call direction text: - override fun yesterday(timestamp: Long): String { - return "Yesterday" - } + + + - override fun lastWeek(timestamp: Long): String { - return "Last Week" - } + + +```kotlin YourActivity.kt lines +cometchatCallLogs.setSubtitleView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return TextView(context) + } - override fun otherDays(timestamp: Long): String { - return dateFormatter.format(Date(timestamp)) + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + val textView = createdView as TextView + val callUser = callLog.initiator as CallUser + val isInitiator = callUser.uid == CometChat.getLoggedInUser().uid + if (callLog.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (callLog + .status + == CometChatCallsConstants.CALL_STATUS_MISSED) + ) { + textView.text = "Missed Call" + } else { + if (isInitiator) { + textView.text = "Outgoing Call" + } else { + textView.text = "Incoming Call" + } } + } +}) +``` + - override fun minutes(diffInMinutesFromNow: Long, timestamp: Long): String { - return "$diffInMinutesFromNow mins ago" - } + +```java YourActivity.java lines +cometchatCallLogs.setSubtitleView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new TextView(context); + } - override fun hours(diffInHourFromNow: Long, timestamp: Long): String { - return "$diffInHourFromNow hrs ago" + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { + TextView textView = (TextView) createdView; + CallUser callUser = (CallUser) callLog.getInitiator(); + boolean isInitiator = callUser.getUid().equals(CometChat.getLoggedInUser().getUid()); + if (callLog.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || callLog + .getStatus() + .equals(CometChatCallsConstants.CALL_STATUS_MISSED)) { + textView.setText("Missed Call"); + } else { + if (isInitiator) { + textView.setText("Outgoing Call"); + } else { + textView.setText("Incoming Call"); + } } - }); + } +}); ``` - - -*** - -#### setLoadingView - -Allows setting a custom loading view when fetching call logs. +### `setTrailingView` -Use Cases: - -* Display a spinner animation while loading. -* Show a "Fetching Call History..." message. -* Use a shimmer effect for better UI experience. +Replace the right section of each call log item. - -```java -cometchatConversations.setLoadingView(R.layout.your_loading_view); -``` - - - -```kotlin -cometchatConversations.loadingView = R.layout.your_loading_view -``` +```kotlin lines +cometchatCallLogs.setTrailingView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return TextView(context) + } + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + } +}) +``` - - -*** - -#### setEmptyView - -Defines a custom view when no call logs are available. - -Use Cases: - -* Show a friendly message like "No calls yet!". -* Offer quick actions like "Make a Call". -* Display an illustration/image. - - -```java -cometchatConversations.setEmptyView(R.layout.your_empty_view); -``` +```java lines +cometchatCallLogs.setTrailingView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new TextView(context); + } - + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { - -```kotlin -cometchatConversations.emptyView = R.layout.your_empty_view + } +}); ``` - - -*** - -#### setErrorView - -Allows setting a custom error state view when fetching call logs fails. +Timestamp example: -Use Cases: - -* Display a retry button. -* Show a network issue message. -* Provide a troubleshooting guide. + + + - -```java -cometchatConversations.setErrorView(R.layout.your_empty_view); -``` + +```kotlin YourActivity.kt lines +cometchatCallLogs.setTrailingView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return TextView(context) + } + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + val textView = createdView as TextView + textView.text = SimpleDateFormat("dd MMM, hh:mm a").format(callLog.initiatedAt * 1000) + } +}) +``` - -```kotlin -cometchatConversations.errorView = R.layout.your_error_view -``` + +```java YourActivity.java lines +cometchatCallLogs.setTrailingView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return new TextView(context); + } + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { + TextView textView = (TextView) createdView; + textView.setText(new SimpleDateFormat("dd MMM, hh:mm a").format(callLog.getInitiatedAt() * 1000)); + } +}); +``` - -*** +### `setItemView` -#### setItemView - -Allows setting a custom layout for each call log item. - -Use Cases: - -* Customize the entire call log card. -* Display additional contact details. -* Use a two-column design for better readability. +Replace the entire list item row. - -```java - cometChatCallLog.setItemView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return super.createView(context, listItem); - } - - @Override - public void bindView(Context context, - View createdView, - CallLog call, - RecyclerView.ViewHolder holder, - List callList, - int position) { + +```kotlin lines +cometchatCallLogs.setItemView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View? { + return null + } - super.bindView(context, createdView, call, holder, callList, position); - } - }); + override fun bindView( + context: Context, + createdView: View, + callLog: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + } +}) ``` - - -```kotlin - cometChatCallLog.setItemView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + +```java lines +cometchatCallLogs.setItemView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return null; + } - } + @Override + public void bindView(Context context, View createdView, CallLog callLog, RecyclerView.ViewHolder holder, List callList, int position) { - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - } - }) + } +}); ``` - - +Example with custom call log layout: + -```xml call_log_list_item.xml +Create a `call_log_list_item.xml` custom layout file: + +```xml call_log_list_item.xml lines - @@ -782,662 +980,567 @@ Use Cases: + android:layout_height="wrap_content" /> ``` - -```java - cometChatCallLog.setItemView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.call_log_list_item, null); - } + +```kotlin YourActivity.kt lines +cometchatCallLogs.setItemView(object : CallLogsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.call_log_list_item, null) + } - @Override - public void bindView(Context context, - View createdView, - CallLog call, - RecyclerView.ViewHolder holder, - List callList, - int position) { - CometChatAvatar avatar = view.findViewById(R.id.avatar); - TextView name = view.findViewById(R.id.tv_title); - TextView subTitle = view.findViewById(R.id.tv_subtitle); - TextView date = view.findViewById(R.id.tv_date_call_log); - - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT - ); - - view.setLayoutParams(layoutParams); - CallUser callUser = (CallUser) call.getInitiator(); - CallUser callUser1 = (CallUser) call.getReceiver(); - boolean isInitiator = callUser.getUid().equals(CometChat.getLoggedInUser().getUid()); - date.setText(new SimpleDateFormat("dd MMM, hh:mm a").format(call.getInitiatedAt() * 1000)); - if (call.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || call - .getStatus() - .equals(CometChatCallsConstants.CALL_STATUS_MISSED)) { - avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_missed_call, null)); - subTitle.setText("Missed Call"); - } else { - if (isInitiator) { - avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_outgoing_call, null)); - subTitle.setText("Outgoing Call"); - name.setText(callUser1.getName()); - } else { - avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_incoming_call, null)); - subTitle.setText("Incoming Call"); - name.setText(callUser.getName()); - } - } + override fun bindView( + context: Context, + createdView: View, + call: CallLog, + holder: RecyclerView.ViewHolder, + callList: List, + position: Int + ) { + val avatar: CometChatAvatar = createdView.findViewById(R.id.avatar) + val name: TextView = createdView.findViewById(R.id.tv_title) + val subTitle: TextView = createdView.findViewById(R.id.tv_subtitle) + val date: TextView = createdView.findViewById(R.id.tv_date_call_log) + + val layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT + ) + + createdView.layoutParams = layoutParams + val callUser = call.initiator as CallUser + val callUser1 = call.receiver as CallUser + val isInitiator = callUser.uid == CometChat.getLoggedInUser().uid + date.text = SimpleDateFormat("dd MMM, hh:mm a").format(call.initiatedAt * 1000) + if (call.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (call + .status + == CometChatCallsConstants.CALL_STATUS_MISSED) + ) { + avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_missed_call, null)!!) + subTitle.text = "Missed Call" + } else { + if (isInitiator) { + avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_outgoing_call, null)!!) + subTitle.text = "Outgoing Call" + name.text = callUser1.name + } else { + avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_incoming_call, null)!!) + subTitle.text = "Incoming Call" + name.text = callUser.name } - }); + } + } +}) ``` - - -```kotlin - cometChatCallLog.setItemView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.call_log_list_item, null) - } + +```java YourActivity.java lines +cometchatCallLogs.setItemView(new CallLogsViewHolderListener() { + @Override + public View createView(Context context, CometchatCallLogsItemsBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.call_log_list_item, null); + } - override fun bindView( - context: Context, - createdView: View, - call: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - val avatar: CometChatAvatar = view.findViewById(R.id.avatar) - val name: TextView = view.findViewById(R.id.tv_title) - val subTitle: TextView = view.findViewById(R.id.tv_subtitle) - val date: TextView = view.findViewById(R.id.tv_date_call_log) - - val layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT - ) - - view.setLayoutParams(layoutParams) - val callUser = call.initiator as CallUser - val callUser1 = call.receiver as CallUser - val isInitiator = callUser.uid == CometChat.getLoggedInUser().uid - date.text = SimpleDateFormat("dd MMM, hh:mm a").format(call.initiatedAt * 1000) - if (call.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (call - .status - == CometChatCallsConstants.CALL_STATUS_MISSED) - ) { - avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_missed_call, null)!!) - subTitle.text = "Missed Call" - } else { - if (isInitiator) { - avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_outgoing_call, null)!!) - subTitle.text = "Outgoing Call" - name.text = callUser1.name - } else { - avatar.setAvatar(ResourcesCompat.getDrawable(resources, R.drawable.ic_incoming_call, null)!!) - subTitle.text = "Incoming Call" - name.text = callUser.name - } - } + @Override + public void bindView(Context context, View createdView, CallLog call, RecyclerView.ViewHolder holder, List callList, int position) { + CometChatAvatar avatar = createdView.findViewById(R.id.avatar); + TextView name = createdView.findViewById(R.id.tv_title); + TextView subTitle = createdView.findViewById(R.id.tv_subtitle); + TextView date = createdView.findViewById(R.id.tv_date_call_log); + + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT + ); + + createdView.setLayoutParams(layoutParams); + CallUser callUser = (CallUser) call.getInitiator(); + CallUser callUser1 = (CallUser) call.getReceiver(); + boolean isInitiator = callUser.getUid().equals(CometChat.getLoggedInUser().getUid()); + date.setText(new SimpleDateFormat("dd MMM, hh:mm a").format(call.getInitiatedAt() * 1000)); + if (call.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || call + .getStatus() + .equals(CometChatCallsConstants.CALL_STATUS_MISSED)) { + avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_missed_call, null)); + subTitle.setText("Missed Call"); + } else { + if (isInitiator) { + avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_outgoing_call, null)); + subTitle.setText("Outgoing Call"); + name.setText(callUser1.getName()); + } else { + avatar.setAvatar(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_incoming_call, null)); + subTitle.setText("Incoming Call"); + name.setText(callUser.getName()); } - }) + } + } +}); ``` - - -#### setTitleView +### `setOptions` -Allows setting a custom title view, typically used for the caller’s name or number. - -Use Cases: - -* Display caller’s full name. -* Show a business label for saved contacts. -* Use bold text for unknown numbers. +Replace the long-press context menu entirely. - -```java - cometChatCallLog.setTitleView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return super.createView(context, listItem); - } - - @Override - public void bindView(Context context, - View createdView, - CallLog call, - RecyclerView.ViewHolder holder, - List callList, - int position) { - - super.bindView(context, createdView, call, holder, callList, position); - } - }); + +```kotlin lines +cometchatCallLogs.setOptions { context, callLog -> emptyList() } ``` + + +```java lines +cometchatCallLogs.setOptions((context, callLog) -> Collections.emptyList()); +``` + - -```kotlin - cometChatCallLog.setTitleView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { +### `setAddOptions` - } +Append to the long-press context menu without removing defaults. - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - } - }) + + +```kotlin lines +cometchatCallLogs.setAddOptions { context, callLog -> emptyList() } ``` - + +```java lines +cometchatCallLogs.setAddOptions((context, callLog) -> Collections.emptyList()); +``` + -**Example** +### `setLoadingView` - - - +Sets a custom loading view displayed when data is being fetched. - -```java YourActivity.java - cometChatcallLog.setTitleView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return new TextView(context); - } - - @Override - public void bindView(Context context, - View createdView, - CallLog callLog, - RecyclerView.ViewHolder holder, - List callList, - int position) { - - TextView textView = (TextView) createdView; - textView.setTextAppearance(CometChatTheme.getTextAppearanceHeading4Regular(context)); - textView.setTextColor(CometChatTheme.getTextColorPrimary(context)); - CallUtils.getCallLogUserName(callLog); - if (callLog.getTotalDurationInMinutes() > 0) { - String duration = String.valueOf(callLog.getTotalDurationInMinutes()); - textView.setText(CallUtils.getCallLogUserName(callLog) + " • \uD83D\uDD5A\uFE0F " + duration - .substring(0, duration.length() > 4 ? 4 : 3) + " mins"); - } else textView.setText(CallUtils.getCallLogUserName(callLog)); - } - }); + +```kotlin lines +cometchatCallLogs.setLoadingView(R.layout.your_loading_view) ``` - - -```kotlin YourActivity.kt - cometChatCallLog.setTitleView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { - return TextView(context) - } - - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - val textView = createdView as TextView - textView.setTextAppearance(CometChatTheme.getTextAppearanceHeading4Regular(context)) - textView.setTextColor(CometChatTheme.getTextColorPrimary(context)) - CallUtils.getCallLogUserName(callLog) - if (callLog.totalDurationInMinutes > 0) { - val duration = callLog.totalDurationInMinutes.toString() - textView.text = CallUtils.getCallLogUserName(callLog) + " • \uD83D\uDD5A\uFE0F " + duration - .substring(0, if (duration.length > 4) 4 else 3) + " mins" - } else textView.text = CallUtils.getCallLogUserName(callLog) - } - }) + +```java lines +cometchatCallLogs.setLoadingView(R.layout.your_loading_view); ``` - - -*** +### `setEmptyView` -#### setLeadingView - -Customizes the leading view, usually the caller’s avatar or profile picture. - -Use Cases: - -* Display a profile picture. -* Show a call type icon (missed, received, dialed). -* Indicate call status (e.g., missed calls in red). +Configures a custom view displayed when there are no call logs in the list. - -```java - cometChatCallLog.setLeadingView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return super.createView(context, listItem); - } - - @Override - public void bindView(Context context, - View createdView, - CallLog call, - RecyclerView.ViewHolder holder, - List callList, - int position) { - - super.bindView(context, createdView, call, holder, callList, position); - } - }); + +```kotlin lines +cometchatCallLogs.setEmptyView(R.layout.your_empty_view) ``` + + +```java lines +cometchatCallLogs.setEmptyView(R.layout.your_empty_view); +``` + - -```kotlin - cometChatCallLog.setLeadingView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { +### `setErrorView` - } +Defines a custom error state view that appears when an issue occurs while loading call logs. - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - } - }) + + +```kotlin lines +cometchatCallLogs.setErrorView(R.layout.your_error_view) ``` - + +```java lines +cometchatCallLogs.setErrorView(R.layout.your_error_view); +``` + -**Example** +- **Verify**: After setting any custom view slot, confirm the custom view renders in the correct position within the call log list item, and the data binding populates correctly for each call log entry. - - - +## Common Patterns - - -```java YourActivity.java -cometChatcallLog.setLeadingView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return new CometChatAvatar(context); - } +### Hide all chrome — minimal list - @Override - public void bindView(Context context, - View createdView, - CallLog callLog, - RecyclerView.ViewHolder holder, - List callList, - int position) { - CometChatAvatar avatar = (CometChatAvatar) createdView; - - if (callLog.getInitiator() instanceof CallUser) { - CallUser initiator = (CallUser) callLog.getInitiator(); - boolean isLoggedInUser = CallUtils.isLoggedInUser(initiator); - boolean isMissedOrUnanswered = callLog.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || callLog - .getStatus() - .equals(CometChatCallsConstants.CALL_STATUS_MISSED); - - if (callLog.getType().equals(CometChatCallsConstants.CALL_TYPE_AUDIO) || callLog - .getType() - .equals(CometChatCallsConstants.CALL_TYPE_VIDEO) || callLog.getType().equals(CometChatCallsConstants.CALL_TYPE_AUDIO_VIDEO)) { - - if (isLoggedInUser) { - avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.outgoing_voice_call, null)); - } else if (isMissedOrUnanswered) { - avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.miss_call, null)); - - } else { - avatar.setAvatar(ResourcesCompat.getDrawable(context.getResources(), R.drawable.incoming_voice_call, null)); - } - } - } - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - Utils.convertDpToPx(context, 50), - Utils.convertDpToPx(context, 50) - ); - avatar.setLayoutParams(layoutParams); - } - }); + + +```kotlin lines +cometchatCallLogs.setSeparatorVisibility(View.GONE) +cometchatCallLogs.setToolbarVisibility(View.GONE) ``` + + +```java lines +cometchatCallLogs.setSeparatorVisibility(View.GONE); +cometchatCallLogs.setToolbarVisibility(View.GONE); +``` + +### Missed calls only + + -```kotlin YourActivity.kt -cometChatCallLog.setLeadingView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { - return CometChatAvatar(context) - } +```kotlin lines +val builder = CallLogRequest.CallLogRequestBuilder() + .setCallStatus(CometChatCallsConstants.CALL_STATUS_MISSED) +cometchatCallLogs.setCallLogRequestBuilder(builder) +``` + - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - val avatar = createdView as CometChatAvatar - - if (callLog.initiator is CallUser) { - val initiator = callLog.initiator as CallUser - val isLoggedInUser = CallUtils.isLoggedInUser(initiator) - val isMissedOrUnanswered = callLog.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (callLog - .status - == CometChatCallsConstants.CALL_STATUS_MISSED) - - if (callLog.type == CometChatCallsConstants.CALL_TYPE_AUDIO || (callLog - .type - == CometChatCallsConstants.CALL_TYPE_VIDEO) || callLog.type == CometChatCallsConstants.CALL_TYPE_AUDIO_VIDEO - ) { - if (isLoggedInUser) { - avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.outgoing_voice_call, null)!!) - } else if (isMissedOrUnanswered) { - avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.miss_call, null)!!) - } else { - avatar.setAvatar(ResourcesCompat.getDrawable(context.resources, R.drawable.incoming_voice_call, null)!!) - } - } - } - val layoutParams = LinearLayout.LayoutParams( - Utils.convertDpToPx(context, 50), - Utils.convertDpToPx(context, 50) - ) - avatar.layoutParams = layoutParams - } - }) + +```java lines +CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder() + .setCallStatus(CometChatCallsConstants.CALL_STATUS_MISSED); +cometchatCallLogs.setCallLogRequestBuilder(builder); ``` + + + +### Calls with recordings only + + +```kotlin lines +val builder = CallLogRequest.CallLogRequestBuilder() + .setHasRecording(true) +cometchatCallLogs.setCallLogRequestBuilder(builder) +``` + +```java lines +CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder() + .setHasRecording(true); +cometchatCallLogs.setCallLogRequestBuilder(builder); +``` + -*** +### Audio calls only -#### setSubtitleView + + +```kotlin lines +val builder = CallLogRequest.CallLogRequestBuilder() + .setCallType(CometChatCallsConstants.CALL_TYPE_AUDIO) +cometchatCallLogs.setCallLogRequestBuilder(builder) +``` + -Enables customizing the subtitle view, usually used for additional call details. + +```java lines +CallLogRequest.CallLogRequestBuilder builder = new CallLogRequest.CallLogRequestBuilder() + .setCallType(CometChatCallsConstants.CALL_TYPE_AUDIO); +cometchatCallLogs.setCallLogRequestBuilder(builder); +``` + + -Use Cases: +## Advanced Methods -* Display call type (Missed, Received, Outgoing). -* Show network strength indicators. -* Include call duration in a more readable format. +### `refreshCallLogs` - - -```java - cometChatCallLog.setSubtitleView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return super.createView(context, listItem); - } +Forces a refresh of the call log list, re-fetching data from the server. - @Override - public void bindView(Context context, - View createdView, - CallLog call, - RecyclerView.ViewHolder holder, - List callList, - int position) { - - super.bindView(context, createdView, call, holder, callList, position); - } - }); + + +```kotlin lines +cometchatCallLogs.refreshCallLogs() ``` + + +```java lines +cometchatCallLogs.refreshCallLogs(); +``` + - -```kotlin - cometChatCallLog.setSubtitleView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { +### `setDateFormat` - } +Sets a legacy `SimpleDateFormat` for call log timestamps. - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - } - }) + + +```kotlin lines +cometchatCallLogs.setDateFormat(SimpleDateFormat("dd/MM/yyyy, HH:mm:ss", Locale.getDefault())) ``` - + +```java lines +cometchatCallLogs.setDateFormat(new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss", Locale.getDefault())); +``` + -**Example** +### `setDateTimeFormatter` - - - +Provides a custom implementation of `DateTimeFormatterCallback` to configure how time and date values are displayed. Each method corresponds to a specific case: -You can create and return a view from `setSubtitleView` which will be loaded in call log item. +- `time(long timestamp)` — Custom full timestamp format +- `today(long timestamp)` — Called when a call log is from today +- `yesterday(long timestamp)` — Called for yesterday's call logs +- `lastWeek(long timestamp)` — Call logs from the past week +- `otherDays(long timestamp)` — Older call logs +- `minutes(long diffInMinutesFromNow, long timestamp)` — e.g., "5 minutes ago" +- `hours(long diffInHourFromNow, long timestamp)` — e.g., "2 hours ago" - -```java YourActivity.java - cometChatCallLog.setSubtitleView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return new TextView(context); - } + +```kotlin lines +import java.text.SimpleDateFormat +import java.util.* - @Override - public void bindView(Context context, - View createdView, - CallLog callLog, - RecyclerView.ViewHolder holder, - List callList, - int position) { - TextView textView = (TextView) createdView; - CallUser callUser = (CallUser) callLog.getInitiator(); - boolean isInitiator = callUser.getUid().equals(CometChat.getLoggedInUser().getUid()); - if (callLog.getStatus().equals(CometChatCallsConstants.CALL_STATUS_UNANSWERED) || callLog - .getStatus() - .equals(CometChatCallsConstants.CALL_STATUS_MISSED)) { - textView.setText("Missed Call"); - } else { - if (isInitiator) { - textView.setText("Outgoing Call"); - } else { - textView.setText("Incoming Call"); - } - } - } - }); -``` +cometchatCallLogs.setDateTimeFormatter(object : DateTimeFormatterCallback { - + private val fullTimeFormatter = SimpleDateFormat("hh:mm a", Locale.getDefault()) + private val dateFormatter = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()) - -```kotlin YourActivity.kt - cometChatCallLog.setSubtitleView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { - return TextView(context) - } + override fun time(timestamp: Long): String { + return fullTimeFormatter.format(Date(timestamp)) + } - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - val textView = createdView as TextView - val callUser = callLog.initiator as CallUser - val isInitiator = callUser.uid == CometChat.getLoggedInUser().uid - if (callLog.status == CometChatCallsConstants.CALL_STATUS_UNANSWERED || (callLog - .status - == CometChatCallsConstants.CALL_STATUS_MISSED) - ) { - textView.text = "Missed Call" - } else { - if (isInitiator) { - textView.text = "Outgoing Call" - } else { - textView.text = "Incoming Call" - } - } - } - }) -``` + override fun today(timestamp: Long): String { + return "Today" + } + + override fun yesterday(timestamp: Long): String { + return "Yesterday" + } + + override fun lastWeek(timestamp: Long): String { + return "Last Week" + } + + override fun otherDays(timestamp: Long): String { + return dateFormatter.format(Date(timestamp)) + } + + override fun minutes(diffInMinutesFromNow: Long, timestamp: Long): String { + return "$diffInMinutesFromNow mins ago" + } + override fun hours(diffInHourFromNow: Long, timestamp: Long): String { + return "$diffInHourFromNow hrs ago" + } +}) +``` - + +```java lines +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; -*** +cometchatCallLogs.setDateTimeFormatter(new DateTimeFormatterCallback() { -#### setTrailingView + private final SimpleDateFormat fullTimeFormatter = new SimpleDateFormat("hh:mm a", Locale.getDefault()); + private final SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()); -Customizes the trailing section, typically for call duration or actions. + @Override + public String time(long timestamp) { + return fullTimeFormatter.format(new Date(timestamp)); + } -Use Cases: + @Override + public String today(long timestamp) { + return "Today"; + } -* Display call duration. -* Add a "Call Again" button. -* Show call timestamps. + @Override + public String yesterday(long timestamp) { + return "Yesterday"; + } - - -```java - cometChatCallLog.setTrailingView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return super.createView(context, listItem); - } + @Override + public String lastWeek(long timestamp) { + return "Last Week"; + } - @Override - public void bindView(Context context, - View createdView, - CallLog call, - RecyclerView.ViewHolder holder, - List callList, - int position) { + @Override + public String otherDays(long timestamp) { + return dateFormatter.format(new Date(timestamp)); + } - super.bindView(context, createdView, call, holder, callList, position); - } - }); -``` + @Override + public String minutes(long diffInMinutesFromNow, long timestamp) { + return diffInMinutesFromNow + " mins ago"; + } + @Override + public String hours(long diffInHourFromNow, long timestamp) { + return diffInHourFromNow + " hrs ago"; + } +}); +``` + - -```kotlin - cometChatCallLog.setTrailingView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { +### Internal Access - } +These methods provide direct access to internal components for advanced use cases. - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - } - }) -``` +| Method | Returns | Description | +| --- | --- | --- | +| `getBinding()` | `CometchatCallLogsBinding` | The ViewBinding for the component's root layout | +| `getViewModel()` | `CallLogsViewModel` | The ViewModel managing call log data and state | +| `getAdapter()` | `CallLogsAdapter` | The adapter powering the RecyclerView | +| `setAdapter(CallLogsAdapter)` | `void` | Replaces the default adapter with a custom one | - +> Use these only when the standard API is insufficient. Directly manipulating the adapter or ViewModel may conflict with the component's internal state management. - +## Style -**Example** +The component uses XML theme styles. Define a custom style with parent `CometChatCallLogsStyle` in `themes.xml`, then apply with `setStyle()`. - + -You can create and return a view from setTail which will be loaded in call log item. +```xml themes.xml lines + + +``` - -```java YourActivity.java - cometChatcallLog.setTrailingView(new CallLogsViewHolderListener() { - @Override - public View createView(Context context, CometchatCallLogsItemsBinding listItem) { - return new TextView(context); - } - - @Override - public void bindView(Context context, - View createdView, - CallLog callLog, - RecyclerView.ViewHolder holder, - List callList, - int position) { - TextView textView = (TextView) createdView; - textView.setText(new SimpleDateFormat("dd MMM, hh:mm a").format(callLog.getInitiatedAt() * 1000)); - } - }); + +```kotlin lines +cometchatCallLogs.setStyle(R.style.CustomCallLogStyle) ``` - - -```kotlin YourActivity.kt - cometChatCallLog.setTrailingView(object : CallLogsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatCallLogsItemsBinding?): View { - return TextView(context) - } - - override fun bindView( - context: Context, - createdView: View, - callLog: CallLog, - holder: RecyclerView.ViewHolder, - callList: List, - position: Int - ) { - val textView = createdView as TextView - textView.text = SimpleDateFormat("dd MMM, hh:mm a").format(callLog.initiatedAt * 1000) - } - }) + +```java lines +cometchatCallLogs.setStyle(R.style.CustomCallLogStyle); ``` - - + +To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_logs.xml). + +### Programmatic Style Properties + +In addition to XML theme styles, the component exposes programmatic setters for fine-grained control: + +| Method | Type | Description | +| --- | --- | --- | +| `setBackgroundColor` | `@ColorInt int` | Background color of the component | +| `setCornerRadius` | `@Dimension int` | Corner radius of the component | +| `setStrokeColor` | `@ColorInt int` | Stroke color of the component border | +| `setStrokeWidth` | `@Dimension int` | Stroke width of the component border | +| `setBackIcon` | `Drawable` | Custom back icon drawable | +| `setBackIconTint` | `@ColorInt int` | Tint color for the back icon | +| `setTitleTextColor` | `@ColorInt int` | Title text color in the toolbar | +| `setTitleTextAppearance` | `@StyleRes int` | Title text appearance in the toolbar | +| `setItemTitleTextColor` | `@ColorInt int` | Text color for call log item titles | +| `setItemTitleTextAppearance` | `@StyleRes int` | Text appearance for call log item titles | +| `setItemSubtitleTextColor` | `@ColorInt int` | Text color for call log item subtitles | +| `setItemSubtitleTextAppearance` | `@StyleRes int` | Text appearance for call log item subtitles | +| `setSeparatorColor` | `@ColorInt int` | Color of list item separators | +| `setItemIncomingCallIcon` | `Drawable` | Icon for incoming call indicators | +| `setItemIncomingCallIconTint` | `@ColorInt int` | Tint for incoming call icon | +| `setItemOutgoingCallIcon` | `Drawable` | Icon for outgoing call indicators | +| `setItemOutgoingCallIconTint` | `@ColorInt int` | Tint for outgoing call icon | +| `setItemMissedCallIcon` | `Drawable` | Icon for missed call indicators | +| `setItemMissedCallIconTint` | `@ColorInt int` | Tint for missed call icon | +| `setItemMissedCallTitleColor` | `@ColorInt int` | Title text color for missed call entries | +| `setItemAudioCallIcon` | `Drawable` | Icon for audio call action button | +| `setItemAudioCallIconTint` | `@ColorInt int` | Tint for audio call action icon | +| `setItemVideoCallIcon` | `Drawable` | Icon for video call action button | +| `setItemVideoCallIconTint` | `@ColorInt int` | Tint for video call action icon | +| `setAvatarStyle` | `@StyleRes int` | Style for call log avatars | +| `setDateStyle` | `@StyleRes int` | Style for date/time display | +| `setEmptyStateTitleTextAppearance` | `@StyleRes int` | Title text appearance for the empty state | +| `setEmptyStateTitleTextColor` | `@ColorInt int` | Title text color for the empty state | +| `setEmptyStateSubtitleTextAppearance` | `@StyleRes int` | Subtitle text appearance for the empty state | +| `setEmptyStateSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the empty state | +| `setErrorTitleTextAppearance` | `@StyleRes int` | Title text appearance for the error state | +| `setErrorTitleTextColor` | `@ColorInt int` | Title text color for the error state | +| `setErrorSubtitleTextAppearance` | `@StyleRes int` | Subtitle text appearance for the error state | +| `setErrorSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the error state | + +## Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Activity/Fragment | `setOn` callbacks | `setOnItemClick((v, pos, cl) -> { ... })` | +| Filter which call logs appear | Activity/Fragment | `setCallLogRequestBuilder` | `setCallLogRequestBuilder(builder)` | +| Toggle visibility of UI elements | Activity/Fragment | `setVisibility(int)` | `setSeparatorVisibility(View.GONE)` | +| Replace a section of the list item | Activity/Fragment | `setView` | `setLeadingView(listener)` | +| Change colors, fonts, spacing | `themes.xml` | `CometChatCallLogsStyle` | `#F76808` | +| Avatar style (corner radius, background) | `themes.xml` | `cometchatCallLogsAvatarStyle` | `8dp` | +| Apply a custom style | Activity/Fragment | `setStyle(int styleRes)` | `cometchatCallLogs.setStyle(R.style.CustomCallLogStyle);` | +| Back button visibility | Activity/Fragment | `setBackIconVisibility(int)` | `.setBackIconVisibility(View.VISIBLE);` | +| Toolbar visibility | Activity/Fragment | `setToolbarVisibility(int)` | `.setToolbarVisibility(View.GONE);` | +| Title visibility | Activity/Fragment | `setTitleVisibility(int)` | `.setTitleVisibility(View.GONE);` | +| Error state visibility | Activity/Fragment | `setErrorStateVisibility(int)` | `.setErrorStateVisibility(View.GONE);` | +| Empty state visibility | Activity/Fragment | `setEmptyStateVisibility(int)` | `.setEmptyStateVisibility(View.GONE);` | +| Loading state visibility | Activity/Fragment | `setLoadingStateVisibility(int)` | `.setLoadingStateVisibility(View.GONE);` | +| Separator visibility | Activity/Fragment | `setSeparatorVisibility(int)` | `.setSeparatorVisibility(View.GONE);` | +| Date/time formatting | Activity/Fragment | `setDateTimeFormatter(DateTimeFormatterCallback)` | See `setDateTimeFormatter` code above | +| Legacy date format | Activity/Fragment | `setDateFormat(SimpleDateFormat)` | `setDateFormat(new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss"))` | +| Long-press options (replace) | Activity/Fragment | `setOptions(Function2)` | See `setOptions` code above | +| Long-press options (append) | Activity/Fragment | `setAddOptions(Function2)` | See `setAddOptions` code above | +| Loading view | Activity/Fragment | `setLoadingView(int)` | `.setLoadingView(R.layout.your_loading_view);` | +| Empty view | Activity/Fragment | `setEmptyView(int)` | `.setEmptyView(R.layout.your_empty_view);` | +| Error view | Activity/Fragment | `setErrorView(int)` | `.setErrorView(R.layout.your_error_view);` | +| Leading view (avatar area) | Activity/Fragment | `setLeadingView(CallLogsViewHolderListener)` | See `setLeadingView` code above | +| Title view | Activity/Fragment | `setTitleView(CallLogsViewHolderListener)` | See `setTitleView` code above | +| Subtitle view | Activity/Fragment | `setSubtitleView(CallLogsViewHolderListener)` | See `setSubtitleView` code above | +| Trailing view | Activity/Fragment | `setTrailingView(CallLogsViewHolderListener)` | See `setTrailingView` code above | +| Entire list item | Activity/Fragment | `setItemView(CallLogsViewHolderListener)` | See `setItemView` code above | +| Call icon click listener | Activity/Fragment | `setOnCallIconClickListener(OnCallIconClick)` | See `setOnCallIconClickListener` code above | +| Refresh call logs | Activity/Fragment | `refreshCallLogs()` | `.refreshCallLogs();` | +| Internal adapter access | Activity/Fragment | `getAdapter()` / `setAdapter()` | Advanced use only | + +## Accessibility + +The component renders a scrollable `RecyclerView` of interactive call log items. Each call log row responds to tap and long-press gestures. Avatar images include the caller name as content description. Call status icons (incoming, outgoing, missed) provide visual indicators for call direction. + +For custom views provided via `setLeadingView`, `setTitleView`, `setTrailingView`, or `setItemView`, ensure you set `android:contentDescription` on visual-only elements so TalkBack can announce them. The default views handle this automatically. + +Call direction icons and status indicators are visual-only by default. If screen reader descriptions are needed, provide them via a custom view with appropriate `contentDescription` attributes. + +## Next Steps + + + + Voice and video call initiation buttons + + + Browse recent conversations + + + Browse and search available users + + + Incoming call notification with accept/reject + + \ No newline at end of file diff --git a/ui-kit/android/color-resources.mdx b/ui-kit/android/color-resources.mdx index ac2e6b556..bcda58111 100644 --- a/ui-kit/android/color-resources.mdx +++ b/ui-kit/android/color-resources.mdx @@ -1,32 +1,77 @@ --- title: "Color Resources" +description: "Review and override the default UI Kit color palette for consistent light and dark mode styling." --- -## Overview - -Color resources in CometChat allow you to maintain a consistent visual identity across your application, providing predefined colors for various UI elements such as text, buttons, backgrounds, alerts, and more. These color definitions adapt seamlessly to light and dark themes, ensuring an optimal user experience across different modes. - -The color resources are divided into the following categories: - -* **Primary Colors**: Define the main theme of the application. -* **Neutral Colors**: Used for backgrounds, strokes, and secondary UI elements. -* **Alert Colors**: Highlight states like success, warning, error, or information. -* **Text Colors**: Used for typography. -* **Icon Colors**: Define icon appearances. -* **Button Colors**: Customize button backgrounds, icons, and text. - -CometChat provides separate color definitions for **light mode** and **dark mode**, enabling automatic theme adaptation. - -*** - -## Usage - -### Default Colors - -CometChat includes predefined color sets for light and dark modes in the `res/values` and `res/values-night` directories, respectively. These ensure proper visual contrast and accessibility.\ -Example: Light Mode Color Resources - -```html + + +| Field | Value | +| --- | --- | +| Goal | Review and override the default UI Kit color palette for light and dark modes | +| Light mode | `app/src/main/res/values/color.xml` | +| Dark mode | `app/src/main/res/values-night/color.xml` | +| Override via theme | Set `cometchatPrimaryColor` in `themes.xml` | +| Constraints | App theme must extend `CometChatTheme.DayNight` | +| Related | [Theme Introduction](/ui-kit/android/theme-introduction) \| [Component Styling](/ui-kit/android/component-styling) | + + + +Use CometChat UI Kit color resources to keep a consistent visual identity in light and dark modes. + +## When to use this +- You want to review the default UI Kit color palette. +- You need consistent colors across text, buttons, backgrounds, and icons. +- You want to override the primary brand color via theming. +- You want light and dark mode color consistency. + +## Prerequisites +- CometChat UI Kit for Android is installed and initialized. +- You can edit `app/src/main/res/values/color.xml` and `app/src/main/res/values-night/color.xml`. +- You can edit `app/src/main/res/values/themes.xml`. +- Your app theme extends `CometChatTheme.DayNight`. + +## Quick start + + +File: `app/src/main/res/values/color.xml`. + + +File: `app/src/main/res/values-night/color.xml`. + + +File: `app/src/main/res/values/themes.xml`. Set `cometchatPrimaryColor`. + + +File: `AndroidManifest.xml`. Set `android:theme` on ``. + + +Run the app and confirm UI Kit screens match your palette in light and dark mode. + + + +## Core concepts +- Primary colors define the main theme of the UI. +- Neutral colors are used for backgrounds, strokes, and secondary elements. +- Alert colors highlight success, warning, error, or info states. +- Text and icon colors control typography and icon appearance. +- Light mode colors live in `res/values/color.xml` and dark mode colors in `res/values-night/color.xml`. + +## Implementation + +### Review the default light mode colors +What you're changing: The color resources used in light mode. + +- **Where to change it**: `app/src/main/res/values/color.xml`. + +- **Applies to**: Light mode only. + +- **Default behavior**: UI Kit uses its predefined light mode palette. + +- **Override**: Edit the values or reference them in your theme. + +- **Code**: + +```xml color.xml lines #6852D6 @@ -37,9 +82,24 @@ Example: Light Mode Color Resources ``` -Example: Night Mode Color Resources +- **What this does**: Shows the default light mode color definitions used by UI Kit. -```html +- **Verify**: Light mode UI Kit screens match these colors. + +### Review the default dark mode colors +What you're changing: The color resources used in dark mode. + +- **Where to change it**: `app/src/main/res/values-night/color.xml`. + +- **Applies to**: Dark mode only. + +- **Default behavior**: UI Kit uses its predefined dark mode palette. + +- **Override**: Edit the values or reference them in your theme. + +- **Code**: + +```xml values-night/color.xml lines #6852D6 @@ -50,25 +110,70 @@ Example: Night Mode Color Resources ``` -To view the complete list of colors for both light and dark modes, [Light mode colors](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/color.xml) & [Dark mode colors](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values-night/color.xml). +- **What this does**: Shows the default dark mode color definitions used by UI Kit. + +- **Verify**: Dark mode UI Kit screens match these colors. + + +To view the complete list of colors for both light and dark modes, use the [Light mode colors](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/color.xml) and [Dark mode colors](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values-night/color.xml). + -## Customizing Colors +### Override the primary color via your theme +What you're changing: The UI Kit primary color. -You can override the default colors to align them with your application's branding. +- **Where to change it**: `app/src/main/res/values/themes.xml`. -Example: Changing the Primary Color Define your custom color in your themes.xml: +- **Applies to**: All UI Kit components. -```html +- **Default behavior**: UI Kit uses the default primary color. + +- **Override**: Set `cometchatPrimaryColor` in your app theme. + +- **Code**: + +```xml themes.xml lines ``` -To know more such attributes, visit the [theme attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_theme.xml). +- **What this does**: Replaces the UI Kit primary color with your custom value. + +- **Verify**: Buttons and highlights use the new primary color. + +### Apply your theme in the manifest +What you're changing: The theme applied to your app. + +- **Where to change it**: `AndroidManifest.xml`. + +- **Applies to**: All activities unless overridden. + +- **Default behavior**: The application theme is not set to your UI Kit theme. + +- **Override**: Set `android:theme` on the `` element. + +- **Code**: + +```xml AndroidManifest.xml lines + + +``` + +- **What this does**: Applies your theme to all app activities. + +- **Verify**: UI Kit screens use your updated theme colors. + +## Customization matrix +| What you want to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Light mode palette | `app/src/main/res/values/color.xml` | `cometchat_color_primary` | `#6852D6` | +| Dark mode palette | `app/src/main/res/values-night/color.xml` | `cometchat_color_primary` | `#6852D6` | +| Primary color override | `app/src/main/res/values/themes.xml` | `cometchatPrimaryColor` | `#F76808` | +| Apply theme | `AndroidManifest.xml` | `android:theme` | `android:theme="@style/AppTheme"` | + diff --git a/ui-kit/android/component-styling.mdx b/ui-kit/android/component-styling.mdx index 529c1fee9..39947a5cb 100644 --- a/ui-kit/android/component-styling.mdx +++ b/ui-kit/android/component-styling.mdx @@ -1,23 +1,115 @@ --- title: "Component Styling" +description: "Style CometChat UI Kit components in Android using XML themes and drawable overrides." --- -## Overview + -CometChat UIKit enables developers to seamlessly integrate customizable components into their applications. Each component is designed to ensure a consistent user experience while offering flexibility to adapt to your app’s design system. You can modify attributes such as colors, fonts, sizes, icons, and more using XML or programmatically. Below is a detailed guide for styling individual components within the UIKit. +| Field | Value | +| --- | --- | +| Goal | Customize UI Kit component appearance (colors, fonts, icons) via XML theme attributes | +| Where | `app/src/main/res/values/themes.xml` — applied via `android:theme` in `AndroidManifest.xml` | +| Pattern | Create a custom style extending the component's parent style → assign it to `AppTheme` via the component's theme attribute | +| Example | `CometChatConversationsStyle` → `cometchatConversationsStyle`, `CometChatUsersStyle` → `cometchatUsersStyle` | +| Constraints | Must extend `CometChatTheme.DayNight` as parent theme; rebuild after updating styles | +| Related | [Theme Introduction](/ui-kit/android/theme-introduction) \| [Color Resources](/ui-kit/android/color-resources) \| [Message Bubble Styling](/ui-kit/android/message-bubble-styling) | -## Components + -### Conversations +This page shows how to style CometChat UI Kit components in Android by overriding XML theme attributes. It is written for Android developers customizing UI Kit v5. -The `CometChatConversations` Component provides a list of recent chats, showing participants, message previews, and timestamps. It supports default themes while offering deep customization for text appearance, icons, and overall layout. With this component, you can create an intuitive and visually appealing chat list that matches your app’s branding. +## When to use this + +- You want UI Kit screens (lists, headers, and message UI) to match your brand colors and typography. +- You need to customize calling and AI UI components without rebuilding UI from scratch. +- You prefer centralized styling through `res/values/themes.xml`. +- You want consistent iconography by supplying your own vector drawables. +- You need a repeatable pattern that an AI coding agent can apply across components. + +## Prerequisites + +- CometChat Android UI Kit v5 installed in your app. +- Your app theme extends `CometChatTheme.DayNight`. +- You can edit `res/values/themes.xml` in your Android module. +- You can add drawable resources to `res/drawable/` when needed. +- You rebuild or sync Gradle after updating styles. + +## Quick start + +1. Open `res/values/themes.xml`. +2. Create a custom style that extends the component's parent style (for example, `CometChatConversationsStyle`). +3. Assign your custom style to `AppTheme` using the component's theme attribute (for example, `cometchatConversationsStyle`). +4. Sync Gradle and rebuild the app. +5. Navigate to the screen that uses the component and confirm the visual change. + +```xml res/values/themes.xml lines + + + + + + + +``` + +- **What this does**: applies a custom avatar style to the Conversations list through your app theme. + +- **Verify**: open the Conversations screen and confirm the avatar background and stroke radius changed. + +## Core concepts + +- `AppTheme` is the single place where UI Kit style hooks are wired. +- Each UI Kit component has a parent style (for example, `CometChatMessageListStyle`) and a theme attribute (for example, `cometchatMessageListStyle`). +- Custom styles must extend the correct parent style to inherit default behavior. +- Drawable overrides (for example, custom icons) live in `res/drawable/` and are referenced from styles. +- Fonts can be set once at the theme level and reused across components. + +```xml res/values/themes.xml lines + + + +``` + +- **What this does**: sets UI Kit typography once so you do not repeat font assignments in every component. + +## Implementation + +Use the following sections to style each component. Each section lists what changes, where to change it, the exact code to paste, and how to verify the result. + +### Chat lists and messaging UI + +#### Conversations + +The `CometChatConversations` component renders the recent chats list. -```html - +What you're changing: avatar and badge styling in the conversation list. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatConversations` + +- **Default behavior**: UI Kit default avatar and badge styles. + +- **Override**: set `cometchatConversationsStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + -``` -```html - + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_conversations.xml). +- **What this does**: applies custom avatar and badge styles to conversation list items. + +- **Verify**: the Conversations list shows updated avatar backgrounds and badge colors. + +Attribute references: +- [Conversations attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_conversations.xml) +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) +- [Badge attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_badge.xml) -### Users +#### Users -The `CometChatUsers` Component displays a scrollable list of users. It is ideal for showcasing available contacts for messaging, calls, or group creation. Developers can style elements like user avatars, status indicators, and list backgrounds to align with their design guidelines. +The `CometChatUsers` component renders a list of users for selection or navigation. -```html +What you're changing: user list avatar and separator styling. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatUsers` + +- **Default behavior**: UI Kit default avatar and list styling. + +- **Override**: set `cometchatUsersStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + -``` -```html - + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_users.xml). +- **What this does**: applies avatar and separator color overrides to the user list. + +- **Verify**: the Users list shows updated avatar backgrounds and separator color. + +Attribute references: +- [Users attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_users.xml) +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) -### Groups +#### Groups -The `CometChatGroups` Component allows you to display and interact with chat groups. Each group item highlights key details like the group name, participant count, and last active time. Customization options include avatar styles, fonts, borders, and background colors, ensuring the component blends seamlessly with your app. +The `CometChatGroups` component renders group items and their summary data. -```html +What you're changing: group list avatar and typography colors. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatGroups` + +- **Default behavior**: UI Kit default group item styling. + +- **Override**: set `cometchatGroupsStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + -``` -```html - + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_groups.xml). +- **What this does**: styles group avatars and separators in the Groups list. + +- **Verify**: the Groups list shows the updated avatar background and title color. + +Attribute references: +- [Groups attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_groups.xml) +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) -### Message Header +#### Message Header -The `CometChatMessageHeader` Component provides essential information about the active chat, such as the recipient's name, avatar, and status (online/offline). It often includes options like back navigation, search, or menu buttons. Customization options allow you to style the header background, text appearance, and icons to match your app's overall design. +The `CometChatMessageHeader` component renders the title, avatar, and action icons for a chat. -```html +What you're changing: title text color, avatar styling, and call button icons. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatMessageHeader` + +- **Default behavior**: UI Kit default header typography and icons. + +- **Override**: set `cometchatMessageHeaderStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + -``` -```html - + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_header.xml). +- **What this does**: applies custom title color, avatar styling, and call button tints in the message header. + +- **Verify**: open a conversation and check the header text and call button icons. -### Message List +Attribute references: +- [Message Header attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_header.xml) +- [Call Buttons attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_buttons.xml) -The `CometChatMessageList` Component displays the sequence of messages in a conversation, supporting text, media, reactions, and more. It includes smooth scrolling, timestamps, and grouping for better readability. Developers can customize bubble colors, text appearance, timestamps, and alignment to provide a tailored chat experience. +#### Message List + +The `CometChatMessageList` component renders conversation messages and their bubble styles. -```xml themes.xml +What you're changing: message list background and outgoing bubble styling. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatMessageList` + +- **Default behavior**: UI Kit default message list background and bubble colors. + +- **Override**: set `cometchatMessageListStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + @@ -166,28 +312,41 @@ The `CometChatMessageList` Component displays the sequence of messages in a conv #FEEDE1 @style/CustomOutgoingMessageBubbleStyle -``` -```html + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_list.xml). +- **What this does**: changes the message list background and outgoing bubble color. + +- **Verify**: open a conversation and check outgoing message bubble colors. + +Attribute references: +- [Message List attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_list.xml) +- [Message Bubble attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_bubble.xml) -### Message Composer +#### Message Composer -The `CometChatMessageComposer` Component enables users to compose and send messages, including text, attachments, and stickers. This highly interactive component supports customization of input box styles, button appearances, and interaction feedback, ensuring it blends seamlessly with your app’s chat UI. +The `CometChatMessageComposer` component renders the input box and action buttons. -```xml drawable/active_send_button +What you're changing: send button icon and composer icon tints. + +- **Where to change it**: `res/drawable/active_send_button.xml` and `res/values/themes.xml` + +- **Applies to**: `CometChatMessageComposer` + +- **Default behavior**: UI Kit default composer icons and send button drawable. + +- **Override**: set `cometchatMessageComposerStyle` in `AppTheme` and reference a custom drawable. + +- **Code**: +```xml res/drawable/active_send_button.xml lines ``` -```xml themes.xml +- **What this does**: defines a custom circular send button drawable. +- **Code**: +```xml res/values/themes.xml lines + -``` -```xml themes.xml + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_composer.xml). +- **What this does**: applies custom icon tints and the active send button drawable to the composer. + +- **Verify**: the composer shows the custom send button and tinted icons. -### Group Members +Attribute references: +- [Message Composer attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_composer.xml) -The `CometChatGroupMembers` Component lists participants in a chat group with details like names, avatars, and roles (e.g., admin or member). It supports customizable styles for list items, fonts, and background colors, ensuring it integrates with your app's group management interface. +#### Group Members + +The `CometChatGroupMembers` component lists users inside a group. -```html - - @@ -251,33 +423,47 @@ The `CometChatGroupMembers` Component lists participants in a chat group with de #F76808 #F76808 -``` -```xml themes.xml - + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_group_members.xml). +- **What this does**: applies custom avatar and separator styling to the group members list. + +- **Verify**: the group members screen shows updated avatar and separator colors. -### Thread Header +Attribute references: +- [Group Members attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_group_members.xml) +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) -The `CometChatThreadHeader` is used in threaded message views, displaying information about the parent message and its context. It provides a seamless way to navigate between the thread and the main conversation while maintaining context. +#### Thread Header + +The `CometChatThreadHeader` component renders the parent message preview in threaded views. -```xml theme.xml +What you're changing: thread header bubble colors and reply count styling. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatThreadHeader` + +- **Default behavior**: UI Kit default thread header styling. + +- **Override**: set `cometchatThreadHeaderStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + @@ -289,642 +475,1021 @@ The `CometChatThreadHeader` is used in threaded message views, displaying inform #F76808 #FEEDE1 -``` -```xml themes.xml + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_thread_header.xml). +- **What this does**: customizes thread header bubble colors and reply count styling. + +- **Verify**: open a thread and confirm the header background and reply count colors. -### Call Logs +Attribute references: +- [Thread Header attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_thread_header.xml) +- [Message Bubble attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_bubble.xml) -The `CometChatCallLogs` Component provides a list of recent calls (voice or video), showing details like call type, duration, participants, and timestamps. Developers can style text, icons, and background elements, making it easy to match the app’s design system. +#### Search + +The `CometChatSearch` component provides cross-conversation and message search UI. - + -```xml themes.xml - -``` -```xml themes.xml - - @font/times_new_roman_bold - @font/times_new_roman - @font/times_new_roman + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_logs.xml). +- **What this does**: applies custom search colors and text styles across search UI sections. + +- **Verify**: open Search and check section headers, chips, and list items. -### Incoming Call +Attribute references: +- [Search attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_search.xml) -The `CometChatIncomingCall` component displays a notification for an incoming call. It typically includes caller details like name, avatar, and call type (audio/video), along with buttons to accept or decline the call. +#### Message Information + +The `CometChatMessageInformation` component displays message metadata such as delivery and read status. - + -```xml themes.xml - +What you're changing: message information styling for metadata views. - -``` +- **Where to change it**: `res/values/themes.xml` -```xml themes.xml - + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_incoming_call.xml). +- **What this does**: wires a custom Message Information style so you can override specific metadata attributes. -### Outgoing Call +- **Verify**: open Message Information and confirm your overrides apply. -The `CometChatOutgoingCall` component displays a status view for calls initiated by the user, showing the recipient's details, call type, and call status (e.g., ringing or connecting). +Attribute references: +- [Message Information attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_information.xml) + +#### Message Option Sheet + +The `CometChatMessageOptionSheet` component is the action menu for message-level actions. - + -```xml themes.xml +What you're changing: option sheet background and icon tint. - - -``` +- **Where to change it**: `res/values/themes.xml` -```xml themes.xml +- **Applies to**: `CometChatMessageOptionSheet` - + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_outgoing_call.xml). +- **What this does**: updates message option sheet icon tint and background color. + +- **Verify**: long-press a message and confirm the option sheet styling. -### Call Button +Attribute references: +- [Message Option Sheet attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_option_sheet.xml) -The `CometChatCallButton` Component initiates voice or video calls with a single click. It supports various customization options for button color and icon styles, making it adaptable to different screen layouts and themes. These components further enhance the versatility of CometChat UIKit, ensuring that all aspects of messaging and calling functionality are cohesive, user-friendly, and fully customizable. +#### Attachment Option Sheet + +The `CometChatAttachmentOptionSheet` component renders the attachment picker. - + -```xml themes.xml - -``` - -```xml themes.xml - -``` +What you're changing: attachment option sheet background and icon tint. -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_buttons.xml). +- **Where to change it**: `res/values/themes.xml` -### AI Assistant Chat History +- **Applies to**: `CometChatAttachmentOptionSheet` -The `CometChatAIAssistantChatHistory` component displays the history of interactions with an AI assistant. It provides a seamless way to view past conversations, ensuring users can easily reference previous AI responses. +- **Default behavior**: UI Kit default attachment sheet styling. - - - +- **Override**: set `cometchatAttachmentOptionSheetStyle` in `AppTheme`. -```xml themes.xml - - + ``` -```xml themes.xml - -``` +- **What this does**: applies custom colors to the attachment picker sheet. + +- **Verify**: open the attachment menu and confirm background and icons. -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_assistant_chat_history.xml). +Attribute references: +- [Attachment Option Sheet attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_attachment_option_sheet.xml) -### Search +#### Mentions -The `CometChatSearch` component allows users to search through conversations and messages. It provides a user-friendly interface for finding specific content quickly, with customizable styles for various elements such as background colors, text appearances, and section headers. +The `CometChatMentions` styling controls how user mentions appear inside messages. - + -```xml themes.xml - - @style/textStyleTimesNewRoman + - -``` -```xml themes.xml - + + + + ``` -*** +- **What this does**: customizes mention colors for incoming and outgoing message bubbles. + +- **Verify**: send a mention in a chat and check the mention highlight colors. -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_search.xml). +Attribute references: +- [Mentions attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_mentions.xml) +- [Message Bubble attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_bubble.xml) -## Base Component +### Calling UI -### Avatar +#### Call Logs -The `CometChatAvatar` Component is used across the UIKit to represent users, groups, or placeholders visually. This highly reusable component supports various shapes (circle or square), sizes, borders, and fallback icons, allowing complete design consistency for profile or group images. +The `CometChatCallLogs` component renders recent call history. - + -```xml themes.xml - -``` +What you're changing: call log list separators and title colors. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatCallLogs` -```xml themes.xml - +- **Default behavior**: UI Kit default call log styling. + +- **Override**: set `cometchatCallLogsStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml). +- **What this does**: applies custom avatar and text colors to the call logs list. + +- **Verify**: open Call Logs and confirm the separator and title colors. + +Attribute references: +- [Call Logs attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_logs.xml) -### Status indicator +#### Incoming Call -The `CometChatStatusIndicator` visually represents user presence (online, offline, or custom states). It can be styled for different shapes, sizes, and colors to reflect your app’s visual preferences while maintaining clarity in conveying status information. +The `CometChatIncomingCall` component renders the incoming call UI. - + -```xml drawable/online_indicator_drawable - - - -``` +What you're changing: incoming call background, buttons, and avatar styling. -```xml themes.xml - -``` +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatIncomingCall` + +- **Default behavior**: UI Kit default incoming call layout and colors. + +- **Override**: set `cometchatIncomingCallStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + -```xml themes.xml - + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_status_indicator.xml). +- **What this does**: customizes the incoming call screen background and action buttons. + +- **Verify**: trigger an incoming call and confirm the background and button colors. -### Badge +Attribute references: +- [Incoming Call attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_incoming_call.xml) +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) -The `CometChatBadge` Component displays notifications or counts, such as unread messages. It can be styled for background colors, border radius, text size, and colors, allowing you to create visually distinct indicators for different notifications. +#### Outgoing Call + +The `CometChatOutgoingCall` component renders the outgoing call UI. - + -```xml themes.xml - -``` +What you're changing: outgoing call avatar styling. + +- **Where to change it**: `res/values/themes.xml` -```xml themes.xml - +- **Applies to**: `CometChatOutgoingCall` + +- **Default behavior**: UI Kit default outgoing call styling. + +- **Override**: set `cometchatOutgoingCallStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_badge.xml). +- **What this does**: applies a custom avatar style to the outgoing call screen. -### Date +- **Verify**: place a call and confirm the avatar styling. -The `CometChatDate` Component formats and displays timestamps in conversation lists and message threads. It ensures time-related information is clear and consistent. Developers can customize its text appearance, alignment, and colors to fit various contexts. +Attribute references: +- [Outgoing Call attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_outgoing_call.xml) +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) + +#### Call Buttons + +The `CometChatCallButton` component renders voice and video call buttons. - + -```xml themes.xml - -``` +What you're changing: button background, stroke, and icon tint. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatCallButtons` + +- **Default behavior**: UI Kit default call button styling. + +- **Override**: set `cometchatCallButtonsStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + -```xml themes.xml - + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_date.xml). +- **What this does**: customizes call button padding, background, and icon colors. + +- **Verify**: open a chat header and confirm button styling. + +Attribute references: +- [Call Buttons attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_call_buttons.xml) -### Receipts +### AI UI -The `CometChatReceipts` Component indicates message delivery and read statuses using intuitive icons. These can be styled for icon size, tint, and alignment, ensuring they remain clear and consistent with your app’s UI. +#### AI Assistant Chat History + +The `CometChatAIAssistantChatHistory` component renders the AI conversation history view. - + -```xml drawable/read_receipts - +What you're changing: background, header, and list typography. - - -``` +- **Where to change it**: `res/values/themes.xml` -```xml themes.xml - -``` +- **Applies to**: `CometChatAIAssistantChatHistory` + +- **Default behavior**: UI Kit default AI history styling. -```xml themes.xml - +- **Override**: set `cometChatAIAssistantChatHistoryStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_receipt.xml). +- **What this does**: applies custom colors and font styling to the AI Assistant history screen. + +- **Verify**: open AI Assistant history and confirm background and header styling. -### Media Recorder +Attribute references: +- [AI Assistant Chat History attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_assistant_chat_history.xml) -The `CometChatMediaRecorder` Component facilitates the recording of audio and video messages. It supports full customization of its recording controls, including button sizes, shapes, and colors, making it an integral part of your media-rich chat experience. +#### AI Option Sheet + +The `CometChatAIOptionSheet` component renders AI action options. - + -```xml themes.xml -] -``` +What you're changing: AI option sheet background and icon tint. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatAIOptionSheet` + +- **Default behavior**: UI Kit default AI option sheet styling. -```xml themes.xml - +- **Override**: set `cometchatAIOptionSheetStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_media_recorder.xml). +- **What this does**: customizes AI option sheet colors. -### Sticker Keyboard +- **Verify**: open AI actions and confirm the option sheet styling. -The `CometChatStickerKeyboard` simplifies the integration of sticker-based messaging. Customize the background, grid layout, and sticker display styles to align with your chat experience. This component provides a visually rich and interactive way to enhance conversations. +Attribute references: +- [AI Option Sheet attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_option_sheet.xml) + +#### Conversation Starter + +The `CometChatConversationStarter` component renders AI-powered conversation starters. - + -```xml themes.xml - -``` +What you're changing: conversation starter item backgrounds. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatConversationStarter` + +- **Default behavior**: UI Kit default conversation starter styling. + +- **Override**: set `cometchatAIConversationStarterStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + -```xml themes.xml - + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_sticker_keyboard.xml). +- **What this does**: applies a custom background color to AI conversation starter items. + +- **Verify**: open a new chat and confirm the conversation starter chip color. + +Attribute references: +- [AI Conversation Starter attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_conversation_starter.xml) -### Reaction list +#### Conversation Summary -The `CometChatReactionList` Component provides a visual representation of emoji reactions on messages. It supports customization for reaction sizes, spacing, and colors, enabling you to build an engaging and personalized messaging environment. +The `CometChatConversationSummary` component renders AI-generated summaries of chats. - + -```xml themes.xml - -``` +What you're changing: conversation summary background color. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatConversationSummary` -```xml themes.xml - +- **Default behavior**: UI Kit default conversation summary styling. + +- **Override**: set `cometchatAIConversationSummaryStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_reaction_list.xml). +- **What this does**: applies a custom background color to conversation summary cards. -### Conversation Starter +- **Verify**: open a chat summary and confirm the background color. -The `CometChatConversationStarter` Component offers AI-based suggestions or reply options to initiate a chat. Developers can customize the background, text styles, and button appearances to ensure seamless integration with the app’s visual language. +Attribute references: +- [AI Conversation Summary attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_conversation_summary.xml) + +#### Smart Replies + +The `CometChatSmartReplies` component renders AI-generated reply suggestions. - + -```xml themes.xml - -``` +What you're changing: smart reply background, item color, and stroke. -```xml themes.xml - +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatSmartReplies` + +- **Default behavior**: UI Kit default smart replies styling. + +- **Override**: set `cometchatAISmartRepliesStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_conversation_starter.xml). +- **What this does**: customizes smart reply container and chip styling. + +- **Verify**: open a conversation with smart replies enabled and confirm chip styling. + +Attribute references: +- [AI Smart Replies attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_smart_replies.xml) -### Conversation Summary +### Base components -The `CometChatConversationSummary` Component highlights the essence of a conversation, including participant details, last message, and timestamp. Customize text sizes, colors, and spacing to create visually distinct summaries that improve readability and engagement. +#### Avatar + +The `CometChatAvatar` component is used across lists and headers. - + -```xml themes.xml - -``` +What you're changing: avatar shape and background color. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatAvatar` -```xml themes.xml - +- **Default behavior**: UI Kit default avatar styling. + +- **Override**: set `cometchatAvatarStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_conversation_summary.xml). +- **What this does**: applies a consistent avatar style across UI Kit components. + +- **Verify**: open any list with avatars and confirm the style. -### Smart Replies +Attribute references: +- [Avatar attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_avatar.xml) -The `CometChatSmartReplies` Component provides AI-driven suggestions for quick message replies. Fully customizable for button styles, padding, and colors, this component enables a streamlined and modern chat experience for users. +#### Status Indicator + +The `CometChatStatusIndicator` component shows user presence status. - + -```xml themes.xml - +What you're changing: status indicator icon shape and drawable. + +- **Where to change it**: `res/drawable/online_indicator_drawable.xml` and `res/values/themes.xml` + +- **Applies to**: `CometChatStatusIndicator` + +- **Default behavior**: UI Kit default presence icon. + +- **Override**: set `cometchatStatusIndicatorStyle` in `AppTheme` and reference a custom drawable. + +- **Code**: +```xml res/drawable/online_indicator_drawable.xml lines + + + ``` -```xml themes.xml - +- **What this does**: defines a custom online indicator drawable. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_smart_replies.xml). +- **What this does**: applies the custom status indicator drawable in UI Kit components. + +- **Verify**: check any user list to confirm the presence icon. + +Attribute references: +- [Status Indicator attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_status_indicator.xml) -### Message Information +#### Badge -The `CometChatMessageInformation` Component displays metadata for messages, such as delivery timestamps, sender details, and read receipts. Customization options include text styles, colors, and alignment, making it adaptable to various app layouts. +The `CometChatBadge` component shows unread or notification counts. - + -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_information.xml). +What you're changing: badge background, text color, and corner radius. -### Message option sheet +- **Where to change it**: `res/values/themes.xml` -The `CometChatMessageOptionSheet` Component is a context menu for performing actions on messages, such as replying, forwarding, or deleting. Developers can style its background, icons, and text to match the app’s menu system. +- **Applies to**: `CometChatBadge` + +- **Default behavior**: UI Kit default badge styling. + +- **Override**: set `cometchatBadgeStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + +``` + +- **What this does**: applies a custom badge appearance across UI Kit lists. + +- **Verify**: check any unread badge to confirm colors and radius. + +Attribute references: +- [Badge attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_badge.xml) + +#### Date + +The `CometChatDate` component formats timestamps in lists and message threads. - + -```xml themes.xml - -``` +What you're changing: date text color. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatDate` + +- **Default behavior**: UI Kit default date styling. -```xml themes.xml - +- **Override**: set `cometchatDateStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_option_sheet.xml). +- **What this does**: customizes date text color in UI Kit lists and headers. + +- **Verify**: check any timestamp and confirm the color. -### Attachment option sheet +Attribute references: +- [Date attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_date.xml) -The `CometChatAttachmentOptionSheet` Component provides a sleek interface for users to attach media, documents, or other files. It supports icon and text customizations to create a cohesive attachment experience. +#### Receipts + +The `CometChatReceipts` component renders read and delivered status icons. - + -```xml themes.xml - +What you're changing: read receipt icon drawable. + +- **Where to change it**: `res/drawable/read_receipts.xml` and `res/values/themes.xml` + +- **Applies to**: `CometChatReceipts` + +- **Default behavior**: UI Kit default receipt icons. + +- **Override**: set `cometchatMessageReceiptStyle` in `AppTheme` and reference a custom drawable. + +- **Code**: +```xml res/drawable/read_receipts.xml lines + + + + ``` -```xml themes.xml - +- **What this does**: defines a custom read receipt icon. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_attachment_option_sheet.xml). +- **What this does**: applies the custom receipt icon to message status indicators. -### AIOption Sheet +- **Verify**: send a message and check the receipt icon for read status. -The `CometChatAIOptionSheet` Component offers AI-powered action options, like generating replies or initiating voice-to-text commands. It allows developers to style icons, colors, and interaction elements for a polished and user-friendly interface. +Attribute references: +- [Message Receipt attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_message_receipt.xml) + +#### Media Recorder + +The `CometChatMediaRecorder` component controls audio and video message recording. - + -```xml themes.xml - +What you're changing: recorder icon sizes and recording button background color. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatMediaRecorder` + +- **Default behavior**: UI Kit default media recorder styling. + +- **Override**: set `cometchatMediaRecorderStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -```xml themes.xml - +- **What this does**: applies custom sizing and color to the media recorder UI. + +- **Verify**: open the recorder and check icon sizes and record button color. + +Attribute references: +- [Media Recorder attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_media_recorder.xml) + +#### Sticker Keyboard + +The `CometChatStickerKeyboard` component renders the sticker picker UI. + + + + + +What you're changing: sticker keyboard background color. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatStickerKeyboard` + +- **Default behavior**: UI Kit default sticker keyboard styling. + +- **Override**: set `cometchatStickerKeyboardStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + ``` -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_ai_option_sheet.xml). +- **What this does**: applies a custom background color to the sticker keyboard. -### Mentions +- **Verify**: open the sticker keyboard and confirm the background color. -The `CometChatMentions` Component highlights referenced users or groups within messages. With customizable styles for text color and background, you can ensure mentions stand out clearly in chats while maintaining a cohesive visual theme. +Attribute references: +- [Sticker Keyboard attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_sticker_keyboard.xml) + +#### Reaction List + +The `CometChatReactionList` component renders reactions on messages. - + -```xml themes.xml - - - - - - - -``` - -```html - -``` - -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_mentions.xml). +What you're changing: active tab color in the reaction list. + +- **Where to change it**: `res/values/themes.xml` + +- **Applies to**: `CometChatReactionList` + +- **Default behavior**: UI Kit default reaction list styling. + +- **Override**: set `cometchatReactionListStyle` in `AppTheme`. + +- **Code**: +```xml res/values/themes.xml lines + + + + + +``` + +- **What this does**: applies a custom active tab color in the reaction list. + +- **Verify**: open reactions and confirm the active tab color. + +Attribute references: +- [Reaction List attributes](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_reaction_list.xml) + +## Customization matrix + +| What you want to change | Where | Property or API | Example | +| --- | --- | --- | --- | +| Conversations avatar and badge | `res/values/themes.xml` | `cometchatConversationsStyle` | `cometchatConversationsBadgeStyle` | +| Users list separators | `res/values/themes.xml` | `cometchatUsersStyle` | `cometchatUsersSeparatorColor` | +| Group list titles | `res/values/themes.xml` | `cometchatGroupsStyle` | `cometchatGroupsTitleTextColor` | +| Header call icons | `res/values/themes.xml` | `cometchatMessageHeaderStyle` | `cometchatMessageHeaderCallButtonsStyle` | +| Message list background | `res/values/themes.xml` | `cometchatMessageListStyle` | `cometchatMessageListBackgroundColor` | +| Composer send button | `res/drawable/active_send_button.xml` | `cometchatMessageComposerActiveSendButtonDrawable` | `@drawable/active_send_button` | +| Search UI typography | `res/values/themes.xml` | `cometchatSearchStyle` | `cometchatSearchBarTextAppearance` | +| Call buttons styling | `res/values/themes.xml` | `cometchatCallButtonsStyle` | `cometchatCallButtonsVideoCallBackgroundColor` | +| AI smart replies chip style | `res/values/themes.xml` | `cometchatAISmartRepliesStyle` | `cometchatAISmartRepliesItemStrokeColor` | +| Mentions highlight colors | `res/values/themes.xml` | `cometchatMessageBubbleMentionsStyle` | `cometchatMentionTextColor` | + diff --git a/ui-kit/android/components-overview.mdx b/ui-kit/android/components-overview.mdx index 5b41f2aa8..7740ee216 100644 --- a/ui-kit/android/components-overview.mdx +++ b/ui-kit/android/components-overview.mdx @@ -1,43 +1,224 @@ --- title: "Overview" +description: "Browse all prebuilt UI components in the CometChat Android UI Kit — conversations, messages, users, groups, calls, search, and AI." --- -CometChat's **UI Kit** is a set of pre-built UI components that allows you to easily craft an in-app chat with all the essential messaging features. + -## Type of Components +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Required setup | `CometChatUIKit.init()` + `CometChatUIKit.login()` before rendering any component | +| Callback actions | `.setOn { }` or `.setOn(listener)` | +| Data filtering | `.setRequestBuilder(builder)` | +| Toggle features | `.setVisibility(View.VISIBLE / View.GONE)` | +| Custom rendering | `.setView(ViewHolderListener)` or `.setView(@LayoutRes int)` | +| Style overrides | `.setStyle(@StyleRes int)` targeting `CometChatStyle` | +| Calling | Requires separate `com.cometchat:calls-sdk-android` package | -UI components based on the behaviour and functionality can be categorized into three types: Base Components and Components + -### Base Components +## Architecture -Base Components form the building blocks of your app's user interface (UI). They focus solely on presenting visual elements based on input data, without handling any business logic. These components provide the foundational appearance and behavior for your UI. +The UI Kit is a set of independent Android Views that compose into chat layouts. A typical chat layout uses four core components: -### Components +- `CometChatConversations` — list of recent conversations (users and groups) +- `CometChatMessageHeader` — toolbar showing avatar, name, online status, and typing indicator +- `CometChatMessageList` — scrollable message feed with reactions, receipts, and threads +- `CometChatMessageComposer` — rich input with attachments, mentions, and voice notes -Components build upon Base Components by incorporating business logic. They not only render UI elements but also manage data loading, execute specific actions, and respond to events. This combination of visual presentation and functional capabilities makes Components essential for creating dynamic and interactive UIs. +Data flow: selecting a conversation in `CometChatConversations` yields a `User` or `Group` object via `setOnItemClick`. That object is passed to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` using `.setUser()` or `.setGroup()`. The message components use the SDK internally — `CometChatMessageComposer` sends messages, `CometChatMessageList` receives them via real-time listeners. -## Actions +Components communicate through a publish/subscribe event bus (`CometChatMessageEvents`, `CometChatConversationEvents`, `CometChatGroupEvents`, etc.). A component emits events that other components or application code can subscribe to without direct references. See [Events](/ui-kit/android/events) for the full list. -Actions direct the operational behavior of a component. They are split into two categories: Predefined Actions and User-Defined Actions. +Each component accepts callback methods (`.setOn`), view slot methods (`.setView`) for replacing UI sections, `RequestBuilder` methods for data filtering, and `@StyleRes` overrides via `.setStyle()`. -### Predefined Actions +--- + +## Component Catalog -These are actions that are inherently programmed into a UI component. They are ingrained in thecomponent itself by default, and they execute automatically in response to user interaction,without needing any additional user input. +All components are from the `com.cometchat:chat-uikit-android` package. -### User-Defined Actions +### Conversations and Lists -These are actions that must be explicitly specified by the user. They are not innately part ofthe component like predefined actions. Instead, they must be developed based on the unique needsof the user or the application. User-defined actions provide adaptability and allow for thecreation of custom behaviors that align with the individual needs of the application. +| Component | Purpose | Key Methods | Page | +| --- | --- | --- | --- | +| CometChatConversations | Scrollable list of recent conversations | `setConversationsRequestBuilder`, `setOnItemClick`, `setOnError` | [Conversations](/ui-kit/android/conversations) | +| CometChatUsers | Scrollable list of users | `setUsersRequestBuilder`, `setOnItemClick`, `setOnError` | [Users](/ui-kit/android/users) | +| CometChatGroups | Scrollable list of groups | `setGroupsRequestBuilder`, `setOnItemClick`, `setOnError` | [Groups](/ui-kit/android/groups) | +| CometChatGroupMembers | Scrollable list of group members | `setGroup`, `setGroupMembersRequestBuilder`, `setOnItemClick` | [Group Members](/ui-kit/android/group-members) | -To customize the behavior of a component, actions must be overridden by the user. This provides the user with control over how the component responds to specific events or interactions. +### Messages -Both Components and Composite Components expose actions to the user, which means that users can interact with these types of components through predefined or user-defined actions. On the otherhand, Base Components do not expose actions to the user as they are the foundational buildingblocks mainly responsible for rendering the user interface and do not carry any business logic oractions. +| Component | Purpose | Key Methods | Page | +| --- | --- | --- | --- | +| CometChatMessageHeader | Toolbar with avatar, name, status, typing indicator | `setUser`, `setGroup`, `setOnBackButtonPressed` | [Message Header](/ui-kit/android/message-header) | +| CometChatMessageList | Scrollable message list with reactions, receipts, threads | `setUser`, `setGroup`, `setMessagesRequestBuilder` | [Message List](/ui-kit/android/message-list) | +| CometChatMessageComposer | Rich input with attachments, mentions, voice notes | `setUser`, `setGroup`, `setOnSendButtonClick` | [Message Composer](/ui-kit/android/message-composer) | +| CometChatThreadHeader | Parent message bubble and reply count for threaded view | `setParentMessage` | [Threaded Messages Header](/ui-kit/android/threaded-messages-header) | -## Events +### Calling -Events allow for a decoupled, flexible architecture where different parts of the application can interact without having to directly reference each other. This makes it easier to create complex, interactive experiences, as well as to extend and customize the functionality provided by the CometChat UI Kit. +| Component | Purpose | Key Methods | Page | +| --- | --- | --- | --- | +| CometChatCallButtons | Voice and video call initiation buttons | `setUser`, `setGroup`, `setOnVoiceCallClick`, `setOnVideoCallClick` | [Call Buttons](/ui-kit/android/call-buttons) | +| CometChatIncomingCall | Incoming call notification with accept/reject | `setCall`, `setOnAcceptClick`, `setOnRejectClick` | [Incoming Call](/ui-kit/android/incoming-call) | +| CometChatOutgoingCall | Outgoing call screen with end-call control | `setCall`, `setOnEndCallClick` | [Outgoing Call](/ui-kit/android/outgoing-call) | +| CometChatCallLogs | Scrollable list of call history | `setCallLogRequestBuilder`, `setOnItemClick` | [Call Logs](/ui-kit/android/call-logs) | -Both Components and Composite Components have the ability to emit events. These events are dispatched in response to certain changes or user interactions within the component. By emitting events, these components allow other parts of the application to react to changes or interactions, thus enabling dynamic and interactive behavior within the application. +### Search and AI -## Configurations +| Component | Purpose | Key Methods | Page | +| --- | --- | --- | --- | +| CometChatSearch | Real-time search across conversations and messages | `setOnConversationClicked`, `setOnMessageClicked`, `setUid`, `setGuid` | [Search](/ui-kit/android/search) | +| CometChatAIAssistantChatHistory | AI assistant conversation history | `setOnItemClick`, `setNewChatButtonClick` | [AI Assistant Chat History](/ui-kit/android/ai-assistant-chat-history) | + +--- + +## Component API Pattern + +All components share a consistent API surface. + +### Actions + +Actions control component behavior. They split into two categories: + +Predefined actions are built into the component and execute automatically on user interaction (e.g., tapping send dispatches the message). No configuration needed. + +User-defined actions are callback methods that fire on specific events. Override them to customize behavior: + + + +```kotlin lines +messageList.setOnThreadRepliesClick { message, context, view -> + openThreadPanel(message) +} +messageList.setOnError { error -> + logError(error) +} +``` + + +```java lines +messageList.setOnThreadRepliesClick((message, context, view) -> { + openThreadPanel(message); +}); +messageList.setOnError(error -> { + logError(error); +}); +``` + + + +### Events + +Events enable decoupled communication between components. A component emits events that other parts of the application can subscribe to without direct references. + + + +```kotlin lines +CometChatMessageEvents.addListener("LISTENER_ID", object : CometChatMessageEvents() { + override fun ccMessageSent(message: BaseMessage, status: Int) { + // react to sent message + } +}) + +// cleanup +CometChatMessageEvents.removeListener("LISTENER_ID") +``` + + +```java lines +CometChatMessageEvents.addListener("LISTENER_ID", new CometChatMessageEvents() { + @Override + public void ccMessageSent(BaseMessage message, int status) { + // react to sent message + } +}); + +// cleanup +CometChatMessageEvents.removeListener("LISTENER_ID"); +``` + + + +Each component page documents its emitted events in the Events section. + +### Filters + +List-based components accept `RequestBuilder` methods to control which data loads: + + + +```kotlin lines +messageList.setMessagesRequestBuilder( + MessagesRequest.MessagesRequestBuilder().setLimit(20) +) +``` + + +```java lines +messageList.setMessagesRequestBuilder( + new MessagesRequest.MessagesRequestBuilder().setLimit(20) +); +``` + + + +### Custom View Slots + +Components expose named view slot methods to replace sections of the default UI: + + + +```kotlin lines +messageHeader.setTitleView { context, user, group -> + // return custom View +} +messageHeader.setSubtitleView { context, user, group -> + // return custom View +} +``` + + +```java lines +messageHeader.setTitleView((context, user, group) -> { + // return custom View +}); +messageHeader.setSubtitleView((context, user, group) -> { + // return custom View +}); +``` + + + +### Style Overrides + +Every component supports a `setStyle(@StyleRes int)` method for style customization: + +```xml styles.xml lines + +``` + +See [Component Styling](/ui-kit/android/component-styling) for the full styling guide. + +--- -Configurations offer the ability to customize the properties of each individual component within a Composite Component. If a Composite Component includes multiple components, each of these components will have its own set of properties that can be configured. This means multiple sets of configurations are available, one for each constituent component. This allows for fine-tuned customization of the Composite Component, enabling you to tailor its behavior and appearance to match specific requirements in a granular manner. +## Next Steps + + + + Chat features included out of the box + + + Customize colors, fonts, and styles + + + Add-on features like polls, stickers, and translation + + + Task-oriented tutorials for common patterns + + diff --git a/ui-kit/android/conversations.mdx b/ui-kit/android/conversations.mdx index ddf400633..057f155a3 100644 --- a/ui-kit/android/conversations.mdx +++ b/ui-kit/android/conversations.mdx @@ -1,927 +1,684 @@ --- title: "Conversations" +description: "Scrollable list of recent one-on-one and group conversations for the logged-in user." --- + + +```json +{ + "component": "CometChatConversations", + "package": "com.cometchat.chatuikit.conversations", + "xmlElement": "", + "description": "Scrollable list of recent one-on-one and group conversations for the logged-in user.", + "primaryOutput": { + "method": "setOnItemClick", + "type": "OnItemClick" + }, + "methods": { + "data": { + "setConversationsRequestBuilder": { + "type": "ConversationsRequest.ConversationsRequestBuilder", + "default": "SDK default (30 per page)", + "note": "Pass the builder, not the result of .build()" + }, + "setDateTimeFormatter": { + "type": "DateTimeFormatterCallback", + "default": "Component default (hh:mm a today, Yesterday, dd MMM yyyy)" + }, + "setDateFormat": { + "type": "SimpleDateFormat", + "default": "Component default" + } + }, + "callbacks": { + "setOnItemClick": "OnItemClick", + "setOnItemLongClick": "OnItemLongClick", + "setOnBackPressListener": "OnBackPress", + "setOnSelect": "OnSelection", + "setOnError": "OnError", + "setOnLoad": "OnLoad", + "setOnEmpty": "OnEmpty", + "setOnSearchClickListener": "OnSearchClick" + }, + "visibility": { + "setBackIconVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.GONE" }, + "setToolbarVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setLoadingStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setDeleteConversationOptionVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setErrorStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setEmptyStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setSeparatorVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setUserStatusVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setGroupTypeVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setReceiptsVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setSearchBoxVisibility": { "type": "int", "default": "View.VISIBLE" } + }, + "sound": { + "disableSoundForMessages": { "type": "boolean", "default": false }, + "setCustomSoundForMessages": { "type": "@RawRes int", "default": "built-in" } + }, + "selection": { + "setSelectionMode": { + "type": "UIKitConstants.SelectionMode", + "values": ["NONE", "SINGLE", "MULTIPLE"], + "default": "NONE" + } + }, + "viewSlots": { + "setItemView": "ConversationsViewHolderListener — entire list item row", + "setLeadingView": "ConversationsViewHolderListener — avatar / left section", + "setTitleView": "ConversationsViewHolderListener — name / title text", + "setSubtitleView": "ConversationsViewHolderListener — last message preview", + "setTrailingView": "ConversationsViewHolderListener — timestamp / badge / right section", + "setLoadingView": "@LayoutRes int — loading spinner", + "setEmptyView": "@LayoutRes int — empty state", + "setErrorView": "@LayoutRes int — error state", + "setOverflowMenu": "View — toolbar menu", + "setOptions": "Function2> — long-press context menu (replaces defaults)", + "addOptions": "Function2> — long-press context menu (appends to defaults)" + }, + "formatting": { + "setTextFormatters": { + "type": "List", + "default": "default formatters from data source" + } + }, + "advanced": { + "selectConversation": "Conversation, SelectionMode — programmatic selection", + "clearSelection": "void — clears all selected conversations", + "getSelectedConversations": "List — returns selected items", + "getRecyclerView": "RecyclerView — internal RecyclerView access", + "getViewModel": "ConversationsViewModel — internal ViewModel access", + "getConversationsAdapter": "ConversationsAdapter — internal adapter access", + "setAdapter": "ConversationsAdapter — replace the default adapter", + "getBinding": "CometchatConversationsListViewBinding — root ViewBinding", + "hideReceipts": "boolean — hide/show read receipts at adapter level", + "setMentionAllLabelId": "String id, String label — mention-all label" + }, + "style": { + "setStyle": { + "type": "@StyleRes int", + "parent": "CometChatConversationsStyle" + } + } + }, + "events": [ + { + "name": "CometChatConversationEvents.ccConversationDeleted", + "payload": "Conversation", + "description": "Conversation deleted from list" + } + ], + "sdkListeners": [ + "onTextMessageReceived", + "onMediaMessageReceived", + "onCustomMessageReceived", + "onTypingStarted", + "onTypingEnded", + "onMessagesDelivered", + "onMessagesRead", + "onMessagesDeliveredToAll", + "onMessagesReadByAll", + "onUserOnline", + "onUserOffline", + "onGroupMemberJoined", + "onGroupMemberLeft", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onMemberAddedToGroup" + ], + "compositionExample": { + "description": "Sidebar conversations wired to message view", + "components": [ + "CometChatConversations", + "CometChatMessageHeader", + "CometChatMessageList", + "CometChatMessageComposer" + ], + "flow": "setOnItemClick emits Conversation -> extract User/Group via getConversationWith() -> pass to MessageHeader, MessageList, MessageComposer" + } +} +``` -## Overview + -The Conversations is a [Component](/ui-kit/android/components-overview#components), That shows all conversations related to the currently logged-in user, +## Where It Fits - - - +`CometChatConversations` is a list component. It renders recent conversations and emits the selected `Conversation` via `setOnItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a standard chat layout. + + + +```kotlin ChatActivity.kt lines +class ChatActivity : AppCompatActivity() { + + private lateinit var conversations: CometChatConversations + private lateinit var messageHeader: CometChatMessageHeader + private lateinit var messageList: CometChatMessageList + private lateinit var messageComposer: CometChatMessageComposer + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_chat) + + conversations = findViewById(R.id.conversations) + messageHeader = findViewById(R.id.message_header) + messageList = findViewById(R.id.message_list) + messageComposer = findViewById(R.id.message_composer) + + conversations.setOnItemClick { view, position, conversation -> + if (conversation.conversationType == CometChatConstants.CONVERSATION_TYPE_USER) { + val user = conversation.conversationWith as User + messageHeader.setUser(user) + messageList.setUser(user) + messageComposer.setUser(user) + } else { + val group = conversation.conversationWith as Group + messageHeader.setGroup(group) + messageList.setGroup(group) + messageComposer.setGroup(group) + } + } + } +} +``` + + + +```java ChatActivity.java lines +public class ChatActivity extends AppCompatActivity { + + private CometChatConversations conversations; + private CometChatMessageHeader messageHeader; + private CometChatMessageList messageList; + private CometChatMessageComposer messageComposer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat); + + conversations = findViewById(R.id.conversations); + messageHeader = findViewById(R.id.message_header); + messageList = findViewById(R.id.message_list); + messageComposer = findViewById(R.id.message_composer); + + conversations.setOnItemClick((view, position, conversation) -> { + if (CometChatConstants.CONVERSATION_TYPE_USER.equals(conversation.getConversationType())) { + User user = (User) conversation.getConversationWith(); + messageHeader.setUser(user); + messageList.setUser(user); + messageComposer.setUser(user); + } else { + Group group = (Group) conversation.getConversationWith(); + messageHeader.setGroup(group); + messageList.setGroup(group); + messageComposer.setGroup(group); + } + }); + } +} +``` + + + +```xml activity_chat.xml lines + + + + + + + + + + + + + + + + + +``` + + -## Usage +> On phones, you'd typically use separate Activities instead of a side-by-side layout — see the [Conversation List + Message View](/ui-kit/android/android-conversation) getting started guide. -### Integration +## Quick Start -There are multiple ways in which you can use Conversations in your app. **Layout File**: To use Conversations in your \`layout\_activity.xml, use the following code snippet. +Add the component to your layout XML: -```xml layout_activity.xml +```xml layout_activity.xml lines ``` -2. **Activity**: To use Conversations in your Activity, use the following code snippet. + + + + +Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()`, a user logged in, and the `cometchat-chat-uikit-android` dependency added. + +To add programmatically in an Activity: + +```kotlin YourActivity.kt lines + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(CometChatConversations(this)) +} +``` + + -```java YourActivity.java +```java YourActivity.java lines @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new CometChatConversations(this)); } ``` - + + +Or in a Fragment: + -```kotlin YourActivity.kt - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(CometChatConversations(this)) +```kotlin YourFragment.kt lines + override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View { + return CometChatConversations(requireContext()) } ``` - - - -3. **Fragment**: To use `Conversations` in your `Fragment`, use the following code snippet. - - -```java YourFragment.java +```java YourFragment.java lines @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return new CometChatConversations(getContext()); } ``` - + + +## Filtering Conversations +Pass a `ConversationsRequest.ConversationsRequestBuilder` to `setConversationsRequestBuilder`. Pass the builder instance — not the result of `.build()`. + + -```kotlin YourFragment.kt - override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View { - return CometChatConversations(requireContext()) -} -``` +```kotlin lines +val builder = ConversationsRequest.ConversationsRequestBuilder() + builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER) + builder.setLimit(50) +cometChatConversations.setConversationsRequestBuilder(builder) +``` + +```java lines +ConversationsRequest.ConversationsRequestBuilder builder = new ConversationsRequest.ConversationsRequestBuilder(); + builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER); + builder.setLimit(50); + +cometChatConversations.setConversationsRequestBuilder(builder); +``` + -### Actions +### Filter Recipes -[Actions](/ui-kit/android/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +| Recipe | Code | +| --- | --- | +| Only user conversations | `builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER)` | +| Only group conversations | `builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_GROUP)` | +| Limit to 10 per page | `builder.setLimit(10)` | +| With specific tags | `builder.setTags(Arrays.asList("vip"))` | +| Filter by user tags | `builder.withUserAndGroupTags(true); builder.setUserTags(Arrays.asList("premium"))` | +| Filter by group tags | `builder.withUserAndGroupTags(true); builder.setGroupTags(Arrays.asList("support"))` | -##### setOnItemClick +> Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom. Refer to [ConversationsRequestBuilder](/sdk/android/retrieve-conversations) for the full builder API. -Function invoked when a conversation item is clicked, typically used to open a detailed chat screen. +## Actions and Events - - -```java YourActivity.java -cometchatConversations.setOnItemClick((view1, position, conversation) -> { - - }); -``` +### Callback Methods - +#### `setOnItemClick` +Fires when a conversation row is tapped. Primary navigation hook — set the active conversation and render the message view. + + -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.onItemClick = OnItemClick { view, position, conversation -> } ``` - + +```java YourActivity.java lines +cometchatConversations.setOnItemClick((view1, position, conversation) -> { + + }); +``` + -*** +> **What this does:** Replaces the default item-click behavior. When a user taps a conversation, your custom lambda executes instead of the built-in navigation. -##### setOnItemLongClick +#### `setOnItemLongClick` -Function executed when a conversation item is long-pressed, allowing additional actions like delete or select. +Fires when a conversation row is long-pressed. Use for additional actions like delete or select. - -```java YourActivity.java -cometchatConversations.setOnItemLongClick((view1, position, conversation) -> { - - }); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.onItemLongClick = OnItemLongClick({ view, position, conversation -> }) ``` - + +```java YourActivity.java lines +cometchatConversations.setOnItemLongClick((view1, position, conversation) -> { + + }); +``` + -*** +> **What this does:** Replaces the default long-press behavior. When a user long-presses a conversation, your custom lambda executes. -##### setOnBackPressListener +#### `setOnBackPressListener` -`OnBackPressListener` is triggered when you press the back button in the app bar. It has a predefined behavior; when clicked, it navigates to the previous activity. However, you can override this action using the following code snippet. +Fires when the user presses the back button in the app bar. Default: navigates to the previous activity. - -```java YourActivity.java -cometchatConversations.setOnBackPressListener(() -> { - - }); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.onBackPressListener = OnBackPress { } ``` - - - -*** - -##### setOnSearchClickListener - -`setOnSearchClickListener` is triggered when you click the search bar. It has a predefined behavior; when clicked, it opens the search screen. However, you can override this action using the following code snippet. - - -```java YourActivity.java - binding.cometchatConversations.setOnSearchClickListener(() -> { - Log.i(TAG, "onViewCreated: Search Bar Clicked"); - }); -``` - - - - -```kotlin YourActivity.kt - binding.cometchatConversations.setOnSearchClickListener { - Log.i(TAG, "onViewCreated: Search Bar Clicked") - } +```java YourActivity.java lines +cometchatConversations.setOnBackPressListener(() -> { + + }); ``` - - -*** +> **What this does:** Overrides the default back-press navigation. When the user taps the back button, your custom logic runs instead. -##### setOnSelect +#### `setOnSelect` -Called when a item from the fetched list is selected, useful for multi-selection features. +Fires when a conversation is checked/unchecked in multi-select mode. Requires `setSelectionMode` to be set. - -```java YourActivity.java -cometchatConversations.setOnSelect(t -> { - - }); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.setOnSelect(object : OnSelection { override fun onSelection(t: MutableList?) { } }) ``` - - - -*** - -##### OnError - -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Conversations component. - - -```java YourActivity.java -cometchatConversations.setOnError(cometchatException -> { +```java YourActivity.java lines +cometchatConversations.setOnSelect(t -> { }); ``` - + + +> **What this does:** Registers a callback that fires when the user selects one or more conversations. The callback receives the list of selected `Conversation` objects. + +#### `setOnError` +Fires on internal errors (network failure, auth issue, SDK exception). + + -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.setOnError { } ``` - + +```java YourActivity.java lines +cometchatConversations.setOnError(cometchatException -> { + + }); +``` + -*** +> **What this does:** Registers an error listener. If the component encounters an error (e.g., network failure), your callback receives the `CometChatException`. -##### setOnLoad +#### `setOnLoad` -Invoked when the list is successfully fetched and loaded, helping track component readiness. +Fires when the list is successfully fetched and loaded. - -```java YourActivity.java -cometchatConversations.setOnLoad(list -> { - -}); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.setOnLoad(object : OnLoad { override fun onLoad(list: MutableList?) { } }) ``` - + +```java YourActivity.java lines +cometchatConversations.setOnLoad(list -> { + +}); +``` + -*** +> **What this does:** Registers a callback that fires after the conversation list is fetched and rendered. The callback receives the list of loaded `Conversation` objects. -##### setOnEmpty +#### `setOnEmpty` -Called when the list is empty, enabling custom handling such as showing a placeholder message. +Fires when the list is empty, enabling custom handling such as showing a placeholder. - -```java YourActivity.java -cometchatConversations.setOnEmpty(() -> { - - }); -``` - - - -```kotlin YourActivity.kt +```kotlin YourActivity.kt lines cometchatConversations.setOnEmpty{ } ``` - + +```java YourActivity.java lines +cometchatConversations.setOnEmpty(() -> { + + }); +``` + -*** - -### Filters +> **What this does:** Registers a callback that fires when the conversation list has no items. Use this to show a custom empty-state message or trigger other logic. -You can set `ConversationsRequestBuilder` in the Conversations Component to filter the conversation list. You can modify the builder as per your specific requirements with multiple options available to know more refer to [ConversationRequestBuilder](/sdk/android/retrieve-conversations). +#### `setOnSearchClickListener` -You can set filters using the following parameters. - -1. **Conversation Type:** Filters on type of Conversation, `User` or `Groups` -2. **Limit:** Number of conversations fetched in a single request. -3. **WithTags:** Filter on fetching conversations containing tags -4. **Tags:** Filters on specific `Tag` -5. **UserTags:** Filters on specific User `Tag` -6. **GroupTags:** Filters on specific Group `Tag` +Fires when the user taps the search icon in the toolbar. - -```java YourActivity.java -ConversationsRequest.ConversationsRequestBuilder builder = new ConversationsRequest.ConversationsRequestBuilder(); - builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER); - builder.setLimit(50); + +```kotlin YourActivity.kt lines +cometchatConversations.setOnSearchClickListener { -cometChatConversations.setConversationsRequestBuilder(builder); + } ``` - - -```kotlin -val builder = ConversationsRequest.ConversationsRequestBuilder() - builder.setConversationType(CometChatConstants.CONVERSATION_TYPE_USER) - builder.setLimit(50) + +```java YourActivity.java lines +cometchatConversations.setOnSearchClickListener(() -> { -cometChatConversations.setConversationsRequestBuilder(builder) + }); ``` - - -*** +> **What this does:** Overrides the default search icon tap behavior. When the user taps the search icon, your custom logic runs instead. -### Events +- **Verify**: After setting an action callback, trigger the corresponding user interaction (tap, long-press, back, select, search) and confirm your custom logic executes instead of the default behavior. -[Events](/ui-kit/android/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +### Global UI Events -##### 1. ConversationDeleted +`CometChatConversationEvents` emits events subscribable from anywhere in the application. Add a listener and remove it when no longer needed. -This event will be emitted when the user deletes a conversation +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccConversationDeleted` | A conversation is deleted from the list | `Conversation` | - -```ruby Add Listener -CometChatConversationEvents.addListener("YOUR_LISTENER_TAG", new CometChatConversationEvents() { - @Override - public void ccConversationDeleted(Conversation conversation) { - super.ccConversationDeleted(conversation); + +```kotlin Add Listener lines +CometChatConversationEvents.addListener("LISTENER_TAG", object : CometChatConversationEvents() { + override fun ccConversationDeleted(conversation: Conversation) { + super.ccConversationDeleted(conversation) } -}); +}) ``` Remove Listener ``` -CometChatConversationEvents.removeListener("YOUR_LISTENER_TAG"); + CometChatConversationEvents.removeListener("LISTENER_TAG"); ``` - - -```ruby Add Listener -CometChatConversationEvents.addListener("LISTENER_TAG", object : CometChatConversationEvents() { - override fun ccConversationDeleted(conversation: Conversation) { - super.ccConversationDeleted(conversation) - } -}) -``` - -Remove Listener - -``` - CometChatConversationEvents.removeListener("LISTENER_TAG"); -``` - - - - - -## Customization - -To fit your app's design requirements, you can customize the appearance of the conversation component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. - -### Style - -Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component. - -##### setStyle - -You can set the styling object to the `CometChatConversations` Component to customize the styling. - - - - - -```xml themes.xml - - - - - -``` - - - -```java -cometChatConversations.setStyle(R.style.CustomConversationsStyle); -``` - - - - -```kotlin -cometChatConversations.setStyle(R.style.CustomConversationsStyle) -``` - - - - - -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_conversations.xml). - -### Functionality - -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. - -Below is a list of customizations along with corresponding code snippets - -| Methods | Description | Code | -| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| setBackIconVisibility | Used to toggle visibility for back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | -| setToolbarVisibility | Used to toggle visibility for back button in the app bar | `.setToolbarVisibility(View.GONE);` | -| setLoadingStateVisibility | Used to hide loading state while fetching Users | `.setLoadingStateVisibility(View.GONE);` | -| setDeleteConversationOptionVisibility | Used to toggle visibility for delete option on a long press of conversation item | `.setDeleteConversationOptionVisibility(View.GONE);` | -| setErrorStateVisibility | Used to hide error state on fetching conversations | `.setErrorStateVisibility(View.GONE);` | -| setEmptyStateVisibility | Used to hide empty state on fetching conversations | `.setEmptyStateVisibility(View.GONE);` | -| setSeparatorVisibility | Used to control visibility of Separators in the list view | `.setSeparatorVisibility(View.GONE);` | -| setUsersStatusVisibility | Used to control visibility of status indicator shown if user is online | `.setUsersStatusVisibility(View.GONE);` | -| setGroupTypeVisibility | Used to control visibility of status indicator shown for the group type | `.setGroupTypeVisibility(View.GONE);` | -| setReceiptsVisibility | Used to hide receipts shown in the subtitle of the conversation item without disabling the functionality of marking messages as read and delivered. | `.setReceiptsVisibility(View.GONE);` | -| setSearchInputEndIconVisibility | Used to control the visibility for the end icon icon in the search bar of 'CometChatConversation' | `.setSearchInputEndIconVisibility(View.GONE);` | -| setSearchInputEndIconVisibility | Used to control the visibility for the end icon icon in the search bar of 'CometChatConversation' | `.setSearchInputEndIconVisibility(View.GONE);` | -| disableSoundForMessages | This method disables sound notifications for incoming messages | `.disableSoundForMessages(true);` | -| setCustomSoundForMessages | This method enables users to personalize their chat experience by setting a custom sound file for incoming message notifications. | `.setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2);` | -| setSelectionMode | This method determines the selection mode for conversations, enabling users to select either a single conversation or multiple conversations at once. | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | -| setSearchInputText | This method sets the text in the search input field. | .setSearchInputText("Sample Text"); | -| setSearchPlaceholderText | This method sets the placeholder text for the search input field. | .setSearchPlaceholderText("Enter search term"); | - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -*** - -#### setDateTimeFormatter - -By providing a custom implementation of the DateTimeFormatterCallback, you can configure how time and date values are displayed. This ensures consistent formatting for labels such as "Today", "Yesterday", "X minutes ago", and more. - -Each method in the interface corresponds to a specific case: - -`time(long timestamp)` → Custom full timestamp format - -`today(long timestamp)` → Called when a message is from today - -`yesterday(long timestamp)` → Called for yesterday’s messages - -`lastWeek(long timestamp)` → Messages from the past week - -`otherDays(long timestamp)` → Older messages - -`minute(long timestamp)` / `hour(long timestamp)` → Exact time unit - -`minutes(long diffInMinutesFromNow, long timestamp)` → e.g., "5 minutes ago" - -`hours(long diffInHourFromNow, long timestamp)` → e.g., "2 hours ago" - - - -```java -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - - -cometchatConversations.setDateTimeFormatter(new DateTimeFormatterCallback() { - - private final SimpleDateFormat fullTimeFormatter = new SimpleDateFormat("hh:mm a", Locale.getDefault()); - private final SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()); - - @Override - public String time(long timestamp) { - return fullTimeFormatter.format(new Date(timestamp)); - } - - @Override - public String today(long timestamp) { - return "Today"; - } - - @Override - public String yesterday(long timestamp) { - return "Yesterday"; - } - - @Override - public String lastWeek(long timestamp) { - return "Last Week"; - } - - @Override - public String otherDays(long timestamp) { - return dateFormatter.format(new Date(timestamp)); - } - - @Override - public String minutes(long diffInMinutesFromNow, long timestamp) { - return diffInMinutesFromNow + " mins ago"; - } - - @Override - public String hours(long diffInHourFromNow, long timestamp) { - return diffInHourFromNow + " hrs ago"; - } - }); -``` - - - - -```kotlin -import java.text.SimpleDateFormat -import java.util.* - -cometchatConversations.setDateTimeFormatterCallback(object : DateTimeFormatterCallback { - - private val fullTimeFormatter = SimpleDateFormat("hh:mm a", Locale.getDefault()) - private val dateFormatter = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()) - - override fun time(timestamp: Long): String { - return fullTimeFormatter.format(Date(timestamp)) - } - - override fun today(timestamp: Long): String { - return "Today" - } - - override fun yesterday(timestamp: Long): String { - return "Yesterday" - } - - override fun lastWeek(timestamp: Long): String { - return "Last Week" - } - - override fun otherDays(timestamp: Long): String { - return dateFormatter.format(Date(timestamp)) - } - - override fun minutes(diffInMinutesFromNow: Long, timestamp: Long): String { - return "$diffInMinutesFromNow mins ago" - } - - override fun hours(diffInHourFromNow: Long, timestamp: Long): String { - return "$diffInHourFromNow hrs ago" - } - }); -``` - - - - - -*** - -#### setOptions - -This method sets a predefined list of actions that users can perform when they long press a conversation in the list. These options typically include: - -* Deleting a conversation -* Marking a conversation as read or unread -* Pinning or unpinning a conversation -* Muting notifications for a specific conversation - -By customizing these options, developers can provide a streamlined and contextually relevant user experience. - - - -```java -cometchatConversations.setOptions((context, conversation) -> Collections.emptyList()); -``` - - - - -```kotlin -cometchatConversations.options = Function2?> { context, conversation -> emptyList() } -``` - - - - - -Demonstration - - - - - - - -```java -cometchatConversations.setOptions((context, conversation) -> { -List optionsArrayList = new ArrayList<>(); -optionsArrayList.add(new CometChatPopupMenu.MenuItem(UIKitConstants.ConversationOption.DELETE, - "Delete", - getResources().getDrawable(com.cometchat.chatuikit.R.drawable.cometchat_ic_delete), - null, - CometChatTheme.getErrorColor(context), - 0, - CometChatTheme.getErrorColor(context), - CometChatTheme.getTextAppearanceBodyRegular(context), - () -> { - Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show(); - })); - return optionsArrayList; - }); -``` - - - - -```kotlin -cometchatConversations.setOptions { context, conversation -> - val optionsArrayList: MutableList = - ArrayList() - optionsArrayList.add( - CometChatPopupMenu.MenuItem( - UIKitConstants.ConversationOption.DELETE, - "Delete", - ResourcesCompat. getDrawable(resources,com.cometchat.chatuikit.R.drawable.cometchat_ic_delete, getContext()?.theme), - null, - CometChatTheme.getErrorColor(context), - 0, - CometChatTheme.getErrorColor(context), - CometChatTheme.getTextAppearanceBodyRegular(context) - ) { - Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show() - } - ) - optionsArrayList - } -``` - - - - - -*** - -#### addOptions - -This method extends the existing set of actions available when users long press a conversation item. Unlike setOptionsDefines, which replaces the default options, addOptionsAdds allows developers to append additional actions without removing the default ones. Example use cases include: - -* Adding a "Report Spam" action -* Introducing a "Save to Notes" option -* Integrating third-party actions such as "Share to Cloud Storage" - -This method provides flexibility in modifying user interaction capabilities. - - - -```java -cometchatConversations.addOptions((context, conversation) -> Collections.emptyList()); -``` - - - - -```kotlin -cometchatConversations.addOptions { context, conversation -> emptyList() } -``` - - - - - -Demonstration - - - - - - -```java -cometchatConversations.addOptions((context, conversation) -> { - List optionsArrayList = new ArrayList<>(); - optionsArrayList.add(new CometChatPopupMenu.MenuItem("ARCHIVE", - "Archive", - getResources().getDrawable(R.drawable.archive), - null, - CometChatTheme.getTextColorPrimary(context), - 0, - CometChatTheme.getTextColorPrimary(context), - CometChatTheme.getTextAppearanceBodyRegular(context), - () -> Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show())); - optionsArrayList.add(new CometChatPopupMenu.MenuItem("PIN", - "Pin", - getResources().getDrawable(R.drawable.pin), - null, - CometChatTheme.getTextColorPrimary(context), - 0, - CometChatTheme.getTextColorPrimary(context), - CometChatTheme.getTextAppearanceBodyRegular(context), - () -> Toast.makeText(context, "Archive", Toast.LENGTH_SHORT).show())); - optionsArrayList.add(new CometChatPopupMenu.MenuItem("MARKASREAD", - "Mark as read", - getResources().getDrawable(R.drawable.mark_as_read), - null, - CometChatTheme.getTextColorPrimary(context), - 0, - CometChatTheme.getTextColorPrimary(context), - CometChatTheme.getTextAppearanceBodyRegular(context), - () -> Toast.makeText(context, "Mark as read", Toast.LENGTH_SHORT).show())); - return optionsArrayList; - }); -``` - - - - -```kotlin -cometchatConversations.addOptions { context, conversation -> - val optionsArrayList: MutableList = ArrayList() - optionsArrayList.add( - CometChatPopupMenu.MenuItem( - "ARCHIVE", - "Archive", - resources.getDrawable(R.drawable.archive), - null, - CometChatTheme.getTextColorPrimary(context), - 0, - CometChatTheme.getTextColorPrimary(context), - CometChatTheme.getTextAppearanceBodyRegular(context) - ) { - Toast - .makeText(context, "Delete", Toast.LENGTH_SHORT) - .show() - } - ) - optionsArrayList.add( - CometChatPopupMenu.MenuItem( - "PIN", - "Pin", - resources.getDrawable(R.drawable.pin), - null, - CometChatTheme.getTextColorPrimary(context), - 0, - CometChatTheme.getTextColorPrimary(context), - CometChatTheme.getTextAppearanceBodyRegular(context) - ) { - Toast - .makeText(context, "Archive", Toast.LENGTH_SHORT) - .show() - } - ) - optionsArrayList.add( - CometChatPopupMenu.MenuItem( - "MARKASREAD", - "Mark as read", - resources.getDrawable(R.drawable.mark_as_read), - null, - CometChatTheme.getTextColorPrimary(context), - 0, - CometChatTheme.getTextColorPrimary(context), - CometChatTheme.getTextAppearanceBodyRegular(context) - ) { - Toast - .makeText(context, "Mark as read", Toast.LENGTH_SHORT) - .show() - } - ) - optionsArrayList - } -``` - - - - - -*** - -#### setLoadingView - -This method allows developers to set a custom loading view that is displayed when data is being fetched or loaded within the component. Instead of using a default loading spinner, a custom animation, progress bar, or branded loading screen can be displayed. - -Use cases: - -* Showing a skeleton loader for conversations while data loads -* Displaying a custom progress indicator with branding -* Providing an animated loading experience for a more engaging UI - - - -```java -cometchatConversations.setLoadingView(R.layout.your_loading_view); -``` - - - - -```kotlin -cometchatConversations.loadingView = R.layout.your_loading_view -``` - - - - - -*** - -#### setEmptyView - -Configures a custom view to be displayed when there are no conversations or messages in the list. This improves the user experience by providing meaningful content instead of an empty screen. - -Examples: - -* Displaying a message like "No conversations yet. Start a new chat!" -* Showing an illustration or animation to make the UI visually appealing -* Providing a button to start a new conversation - - - -```java -cometchatConversations.setEmptyView(R.layout.your_empty_view); -``` - - - - -```kotlin -cometchatConversations.emptyView = R.layout.your_empty_view -``` - - - - - -*** - -#### setErrorView - -Defines a custom error state view that appears when an issue occurs while loading conversations or messages. This enhances the user experience by displaying friendly error messages instead of generic system errors. - -Common use cases: - -* Showing "Something went wrong. Please try again." with a retry button -* Displaying a connection issue message if the user is offline -* Providing troubleshooting steps for the error - - - -```java -cometchatConversations.setErrorView(R.layout.your_empty_view); -``` - - - - -```kotlin -cometchatConversations.errorView = R.layout.your_error_view -``` - - - - - -*** - -#### setLeadingView - -Allows setting a custom leading view element that appears at the beginning of each conversation item. This is typically used to modify profile pictures, avatars, or icons in the conversation list. - -Examples: - -* Displaying user avatars with online/offline status indicators -* Using initials or custom graphics instead of images - - - -```java - cometchatConversations.setLeadingView(new ConversationsViewHolderListener() { - @Override - public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { - - } - }); +```java Add Listener lines +CometChatConversationEvents.addListener("YOUR_LISTENER_TAG", new CometChatConversationEvents() { + @Override + public void ccConversationDeleted(Conversation conversation) { + super.ccConversationDeleted(conversation); + } +}); ``` +Remove Listener + +``` +CometChatConversationEvents.removeListener("YOUR_LISTENER_TAG"); +``` + +### SDK Events (Real-Time, Automatic) + +The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required. + +| SDK Listener | Internal behavior | +| --- | --- | +| `onTextMessageReceived` / `onMediaMessageReceived` / `onCustomMessageReceived` | Moves conversation to top, updates last message preview and unread count | +| `onTypingStarted` / `onTypingEnded` | Shows/hides typing indicator in the subtitle | +| `onMessagesDelivered` / `onMessagesRead` / `onMessagesDeliveredToAll` / `onMessagesReadByAll` | Updates receipt ticks (unless `setReceiptsVisibility(View.GONE)`) | +| `onUserOnline` / `onUserOffline` | Updates online/offline status dot (unless `setUserStatusVisibility(View.GONE)`) | +| `onGroupMemberJoined` / `onGroupMemberLeft` / `onGroupMemberKicked` / `onGroupMemberBanned` / `onMemberAddedToGroup` | Updates group conversation metadata | + +> Automatic: new messages, typing indicators, receipts, user presence, group membership changes. +> Manual: deleting a conversation via the SDK directly (not through the component's context menu) requires emitting `CometChatConversationEvents.ccConversationDeleted` for the UI to update. + +## Functionality + +Small functional customizations such as toggling visibility of UI elements, setting custom sounds, and configuring selection modes. + +| Methods | Description | Code | +| --- | --- | --- | +| `setBackIconVisibility` | Toggles visibility for the back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | +| `setToolbarVisibility` | Toggles visibility for the toolbar in the app bar | `.setToolbarVisibility(View.GONE);` | +| `setLoadingStateVisibility` | Hides the loading state while fetching conversations | `.setLoadingStateVisibility(View.GONE);` | +| `setDeleteConversationOptionVisibility` | Toggles visibility for the delete option on long press | `.setDeleteConversationOptionVisibility(View.GONE);` | +| `setErrorStateVisibility` | Hides the error state on fetching conversations | `.setErrorStateVisibility(View.GONE);` | +| `setEmptyStateVisibility` | Hides the empty state on fetching conversations | `.setEmptyStateVisibility(View.GONE);` | +| `setSeparatorVisibility` | Controls visibility of separators in the list view | `.setSeparatorVisibility(View.GONE);` | +| `setUserStatusVisibility` | Controls visibility of the online status indicator | `.setUserStatusVisibility(View.GONE);` | +| `setGroupTypeVisibility` | Controls visibility of the group type indicator | `.setGroupTypeVisibility(View.GONE);` | +| `setReceiptsVisibility` | Hides receipts shown in the subtitle without disabling read/delivered marking | `.setReceiptsVisibility(View.GONE);` | +| `setSearchBoxVisibility` | Controls visibility of the search box in the toolbar | `.setSearchBoxVisibility(View.GONE);` | +| `setSearchInputEndIconVisibility` | Controls visibility of the end icon in the search bar | `.setSearchInputEndIconVisibility(View.GONE);` | +| `hideReceipts` | Hides read receipts in the conversation list (adapter-level) | `.hideReceipts(true);` | +| `disableSoundForMessages` | Disables sound notifications for incoming messages | `.disableSoundForMessages(true);` | +| `setCustomSoundForMessages` | Sets a custom sound file for incoming message notifications | `.setCustomSoundForMessages(com.cometchat.chatuikit.R.raw.cometchat_beep2);` | +| `setSelectionMode` | Determines the selection mode (single or multiple) | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | +| `setSearchInputText` | Sets the text in the search input field | `.setSearchInputText("Sample Text");` | +| `setSearchPlaceholderText` | Sets the placeholder text for the search input field | `.setSearchPlaceholderText("Enter search term");` | + +- **Verify**: After calling a visibility method, confirm the corresponding UI element is shown or hidden. After calling `disableSoundForMessages(true)`, confirm no sound plays on incoming messages. + +## Custom View Slots + +Each slot replaces a section of the default UI. Slots that accept a `Conversation` parameter receive the conversation object for that row via the `ConversationsViewHolderListener` pattern (`createView` + `bindView`). + +| Slot | Method | Replaces | +| --- | --- | --- | +| Leading view | `setLeadingView(ConversationsViewHolderListener)` | Avatar / left section | +| Title view | `setTitleView(ConversationsViewHolderListener)` | Name / title text | +| Subtitle view | `setSubtitleView(ConversationsViewHolderListener)` | Last message preview | +| Trailing view | `setTrailingView(ConversationsViewHolderListener)` | Timestamp / badge / right section | +| Item view | `setItemView(ConversationsViewHolderListener)` | Entire list item row | +| Loading view | `setLoadingView(@LayoutRes int)` | Loading spinner | +| Empty view | `setEmptyView(@LayoutRes int)` | Empty state | +| Error view | `setErrorView(@LayoutRes int)` | Error state | +| Overflow menu | `setOverflowMenu(View)` | Toolbar menu | +| Options (replace) | `setOptions(Function2)` | Long-press context menu (replaces defaults) | +| Options (append) | `addOptions(Function2)` | Long-press context menu (appends to defaults) | + +### `setLeadingView` + +Replace the avatar / left section. Typing-aware avatar example. + + -```kotlin +```kotlin lines cometchatConversations.setLeadingView(object : ConversationsViewHolderListener() { override fun createView( @@ -942,18 +699,34 @@ Examples: } }) ``` - + +```java lines + cometchatConversations.setLeadingView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { + + } + }); +``` + -Demonstration +> **What this does:** Registers a `ConversationsViewHolderListener` that provides a custom view for the leading (left) area of each conversation item. `createView` inflates your layout, and `bindView` populates it with conversation data. -```xml drawable/chat_dots.xml +The following example shows a custom leading view with a chat-dots icon for typing indicators and an avatar with status indicator: + +```xml drawable/chat_dots.xml lines ``` -You can create an `leading_view.xml` as a custom layout file. Which we will inflate in `setLeadingView()` +> **What this does:** Defines a vector drawable of a chat bubble with three dots, used as a typing indicator icon in the custom leading view. -```html +Create a `leading_view.xml` custom layout: + +```html lines - ``` -In the method `setLeadingView` you need to inflate the XML and initialize the views using the conversation objects. +Inflate and bind with typing indicator tracking: - -```java -HashMap typingIndicatorHashMap = new HashMap<>(); -CometChat.addMessageListener(System.currentTimeMillis() + "", new CometChat.MessageListener() { - @Override - public void onTypingStarted(TypingIndicator typingIndicator) { - if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { - if (typingIndicatorHashMap.containsKey(typingIndicator.getSender().getUid())) { - return; - } - Log.e(TAG, "bindView: " + typingIndicator.getSender().getUid()); - typingIndicatorHashMap.put(typingIndicator.getSender().getUid(), true); - } else { - if (typingIndicatorHashMap.containsKey(typingIndicator.getReceiverId())) { - return; - } - typingIndicatorHashMap.put(typingIndicator.getReceiverId(), true); - } - } - - @Override - public void onTypingEnded(TypingIndicator typingIndicator) { - if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { - typingIndicatorHashMap.remove(typingIndicator.getSender().getUid()); - } else { - typingIndicatorHashMap.remove(typingIndicator.getReceiverId()); - } - } - }); - -cometchatConversations.setLeadingView(new ConversationsViewHolderListener() { - @Override - public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.leading_view, null); - } - - @Override - public void bindView(Context context, - View createdView, - Conversation conversation, - RecyclerView.ViewHolder holder, - List conversationList, - int position) { - - ImageView imageView = createdView.findViewById(R.id.leading_iv); - ConstraintLayout constraintLayout = createdView.findViewById(R.id.leading_view); - CometChatAvatar avatar = createdView.findViewById(R.id.conversations_avatar); - CometChatStatusIndicator statusIndicator = createdView.findViewById(R.id.status_and_type_indicator); - - - avatar.setAvatar(ConversationsUtils.getConversationTitle(conversation), ConversationsUtils.getConversationAvatar(conversation)); - - - if (conversation.getConversationType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { - if (((User) conversation.getConversationWith()).getStatus().equalsIgnoreCase(CometChatConstants.USER_STATUS_ONLINE)) { - if (!Utils.isBlocked(((User) conversation.getConversationWith()))) { - statusIndicator.setStatusIndicator(StatusIndicator.ONLINE); - } else { - statusIndicator.setStatusIndicator(StatusIndicator.OFFLINE); - } - } else { - statusIndicator.setStatusIndicator(StatusIndicator.OFFLINE); - } - if (typingIndicatorHashMap.containsKey(((User) conversation.getConversationWith()).getUid())) { - imageView.setVisibility(View.VISIBLE); - constraintLayout.setVisibility(GONE); - } else { - imageView.setVisibility(GONE); - constraintLayout.setVisibility(View.VISIBLE); - } - } else { - if (typingIndicatorHashMap.containsKey(((Group) conversation.getConversationWith()).getGuid())) { - imageView.setVisibility(View.VISIBLE); - constraintLayout.setVisibility(GONE); - } else { - imageView.setVisibility(GONE); - constraintLayout.setVisibility(View.VISIBLE); - } - } - - } - }); -``` - - - -```kotlin +```kotlin lines val typingIndicatorHashMap = HashMap() CometChat.addMessageListener(System.currentTimeMillis().toString() + "", object : MessageListener() { override fun onTypingStarted(typingIndicator: TypingIndicator) { @@ -1157,10 +845,8 @@ cometchatConversations.setLeadingView(new ConversationsViewHolderListener() { val avatar = createdView.findViewById(R.id.conversations_avatar) val statusIndicator = createdView.findViewById(R.id.status_and_type_indicator) - avatar.setAvatar(ConversationsUtils.getConversationTitle(conversation), ConversationsUtils.getConversationAvatar(conversation)) - if (conversation.conversationType == CometChatConstants.RECEIVER_TYPE_USER) { if ((conversation.conversationWith as User).status.equals(CometChatConstants.USER_STATUS_ONLINE, ignoreCase = true)) { if (!Utils.isBlocked((conversation.conversationWith as User))) { @@ -1190,133 +876,41 @@ cometchatConversations.setLeadingView(new ConversationsViewHolderListener() { } }) ``` - - - -*** - -#### setTitleView - -Overrides the default title view in the conversation list with a custom layout. This is useful for branding or modifying how conversation names and details are displayed. - -Examples: - -* Displaying conversation titles with additional metadata (e.g., last seen time) -* Custom fonts or text styles for conversation names -* Adding icons or indicators next to titles - - -```java - cometchatConversations.setTitleView(new ConversationsViewHolderListener() { +```java lines +HashMap typingIndicatorHashMap = new HashMap<>(); +CometChat.addMessageListener(System.currentTimeMillis() + "", new CometChat.MessageListener() { @Override - public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return null; + public void onTypingStarted(TypingIndicator typingIndicator) { + if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { + if (typingIndicatorHashMap.containsKey(typingIndicator.getSender().getUid())) { + return; + } + typingIndicatorHashMap.put(typingIndicator.getSender().getUid(), true); + } else { + if (typingIndicatorHashMap.containsKey(typingIndicator.getReceiverId())) { + return; + } + typingIndicatorHashMap.put(typingIndicator.getReceiverId(), true); + } } @Override - public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { - + public void onTypingEnded(TypingIndicator typingIndicator) { + if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { + typingIndicatorHashMap.remove(typingIndicator.getSender().getUid()); + } else { + typingIndicatorHashMap.remove(typingIndicator.getReceiverId()); + } } }); -``` - - - - -```kotlin - cometchatConversations.setTitleView(object : - ConversationsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatConversationsListItemsBinding? - ): View? { - return null - } - - override fun bindView( - context: Context, - createdView: View, - conversation: Conversation, - holder: RecyclerView.ViewHolder, - conversationList: List, - position: Int - ) { - } - }) -``` - - - - - -Demonstration - - - - - -You can create an `custom_title_view.xml` as a custom layout file. Which we will inflate in `setTitleView()` - -```html - - - - - - - - - - - - - - - - - - -``` -In the method `setTitleView` you need to inflate the XML and initialize the views using the conversation objects. - - - -```java -cometchatConversations.setTitleView(new ConversationsViewHolderListener() { +cometchatConversations.setLeadingView(new ConversationsViewHolderListener() { @Override public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null); + return LayoutInflater.from(context).inflate(R.layout.leading_view, null); } @Override @@ -1327,70 +921,96 @@ cometchatConversations.setTitleView(new ConversationsViewHolderListener() { List conversationList, int position) { - TextView name = createdView.findViewById(R.id.name); - TextView status = createdView.findViewById(R.id.status); + ImageView imageView = createdView.findViewById(R.id.leading_iv); + ConstraintLayout constraintLayout = createdView.findViewById(R.id.leading_view); + CometChatAvatar avatar = createdView.findViewById(R.id.conversations_avatar); + CometChatStatusIndicator statusIndicator = createdView.findViewById(R.id.status_and_type_indicator); + + avatar.setAvatar(ConversationsUtils.getConversationTitle(conversation), ConversationsUtils.getConversationAvatar(conversation)); - name.setText(ConversationsUtils.getConversationTitle(conversation)); if (conversation.getConversationType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { - status.setVisibility(View.VISIBLE); - status.setText("• " + ((User) conversation.getConversationWith()).getStatusMessage()); + if (((User) conversation.getConversationWith()).getStatus().equalsIgnoreCase(CometChatConstants.USER_STATUS_ONLINE)) { + if (!Utils.isBlocked(((User) conversation.getConversationWith()))) { + statusIndicator.setStatusIndicator(StatusIndicator.ONLINE); + } else { + statusIndicator.setStatusIndicator(StatusIndicator.OFFLINE); + } + } else { + statusIndicator.setStatusIndicator(StatusIndicator.OFFLINE); + } + if (typingIndicatorHashMap.containsKey(((User) conversation.getConversationWith()).getUid())) { + imageView.setVisibility(View.VISIBLE); + constraintLayout.setVisibility(GONE); + } else { + imageView.setVisibility(GONE); + constraintLayout.setVisibility(View.VISIBLE); + } } else { - status.setVisibility(View.GONE); + if (typingIndicatorHashMap.containsKey(((Group) conversation.getConversationWith()).getGuid())) { + imageView.setVisibility(View.VISIBLE); + constraintLayout.setVisibility(GONE); + } else { + imageView.setVisibility(GONE); + constraintLayout.setVisibility(View.VISIBLE); + } } } }); ``` - + - -```kotlin -cometchatConversations.setTitleView(object : ConversationsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatConversationsListItemsBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null) - } +### `setTrailingView` - override fun bindView( - context: Context, - createdView: View, - conversation: Conversation, - holder: RecyclerView.ViewHolder, - conversationList: List, - position: Int - ) { - val name = createdView.findViewById(R.id.name) - val status = createdView.findViewById(R.id.status) +Replace the timestamp / badge / right section. - name.text = ConversationsUtils.getConversationTitle(conversation) - if (conversation.conversationType == CometChatConstants.RECEIVER_TYPE_USER) { - status.visibility = View.VISIBLE - status.text = "• " + (conversation.conversationWith as User).statusMessage - } else { - status.visibility = View.GONE - } - } - }) -``` + + +```kotlin lines +cometchatConversations.setTrailingView(object : + ConversationsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatConversationsListItemsBinding? + ): View? { + return null + } + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + } +}) +``` - - -*** - -#### setTrailingView + +```java lines +cometchatConversations.setTrailingView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return null; + } -Customizes the trailing (end) view of a conversation item, which is typically used for action buttons or additional information. + @Override + public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { -Examples: + } +}); +``` + + -* Adding a mute/unmute button for each conversation -* Displaying the last message time in a custom format -* Showing unread message counts or notification badges +Relative time badge example: -You can create an `custom_tail_view.xml` as a custom layout file. Which we will inflate in `setTrailingView()` +Create a `custom_tail_view.xml` custom layout file: -```html +```html lines ``` -In the method `setTrailingView` you need to inflate the XML and initialize the views using the conversation objects. +> **What this does:** Defines a custom trailing view layout with a `MaterialCardView` containing two `TextView` elements for displaying the time value and unit (e.g., "5" and "Min ago"). + +Inflate and bind with color-coded time badges: + +```kotlin lines +cometchatConversations.setTrailingView(object : ConversationsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatConversationsListItemsBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null) + } + + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + val card = createdView.findViewById(R.id.card) + val tvHours = createdView.findViewById(R.id.hours) + val tvMessage = createdView.findViewById(R.id.time_title) + + var timestamp = conversation.updatedAt * 1000 + + if (timestamp.toString().length == 10) { + timestamp *= 1000 + } + + val now = Calendar.getInstance() + val lastSeen = Calendar.getInstance() + lastSeen.timeInMillis = timestamp + + val diffInMillis = now.timeInMillis - lastSeen.timeInMillis + val diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) + val diffInHours = TimeUnit.MILLISECONDS.toHours(diffInMillis) + + if (diffInMinutes == 0L) { + tvHours.text = "1" + tvMessage.text = "Min ago" + card.setCardBackgroundColor(Utils.applyColorWithAlphaValue(Color.parseColor("#6852D6"), 40)) + tvMessage.setTextColor(Color.parseColor("#6852D6")) + tvHours.setTextColor(Color.parseColor("#6852D6")) + } else if (diffInMinutes < 60) { + tvHours.text = diffInMinutes.toString() + tvMessage.text = "Min ago" + card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#6852D6"), 40)) + tvMessage.setTextColor(Color.parseColor("#6852D6")) + tvHours.setTextColor(Color.parseColor("#6852D6")) + } else if (diffInHours < 10) { + tvHours.text = diffInHours.toString() + tvMessage.text = "Hr ago" + tvMessage.setTextColor(Color.parseColor("#FFAB00")) + tvHours.setTextColor(Color.parseColor("#FFAB00")) + card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#FFAB00"), 40)) + } else if (diffInHours < 1000) { + tvHours.text = diffInHours.toString() + tvMessage.text = "Hr ago" + tvMessage.setTextColor(Color.parseColor("#F44649")) + tvHours.setTextColor(Color.parseColor("#F44649")) + card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#F44649"), 40)) + } + } + }) +``` + + -```java +```java lines cometchatConversations.setTrailingView(new ConversationsViewHolderListener() { @Override public View createView(Context context, CometchatConversationsListItemsBinding listItem) { @@ -1457,7 +1142,6 @@ cometchatConversations.setTrailingView(new ConversationsViewHolderListener() { long timestamp = conversation.getUpdatedAt() * 1000; if (String.valueOf(timestamp).length() == 10) { - // Convert seconds to milliseconds timestamp *= 1000; } @@ -1469,32 +1153,24 @@ cometchatConversations.setTrailingView(new ConversationsViewHolderListener() { long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMillis); long diffInHours = TimeUnit.MILLISECONDS.toHours(diffInMillis); - // Check if the timestamp is within the last hour if (diffInMinutes == 0) { tvHours.setText("1"); tvMessage.setText("Min ago"); card.setCardBackgroundColor(Utils.applyColorWithAlphaValue(Color.parseColor("#6852D6"), 40)); tvMessage.setTextColor(Color.parseColor("#6852D6")); tvHours.setTextColor(Color.parseColor("#6852D6")); - return; - } else if (diffInMinutes < 60) { tvHours.setText(diffInMinutes + ""); tvMessage.setText("Min ago"); card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#6852D6"), 40)); tvMessage.setTextColor(Color.parseColor("#6852D6")); tvHours.setTextColor(Color.parseColor("#6852D6")); - return; - } - - // Check if the timestamp is within the last 24 hours - if (diffInHours < 10) { + } else if (diffInHours < 10) { tvHours.setText(diffInHours + ""); tvMessage.setText("Hr ago"); tvMessage.setTextColor(Color.parseColor("#FFAB00")); tvHours.setTextColor(Color.parseColor("#FFAB00")); card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#FFAB00"), 40)); - } else if (diffInHours < 1000) { tvHours.setText(diffInHours + ""); tvMessage.setText("Hr ago"); @@ -1505,14 +1181,101 @@ cometchatConversations.setTrailingView(new ConversationsViewHolderListener() { } }); ``` + + + + + + + +### `setTitleView` + +Replace the name / title text. + + + +```kotlin lines +cometchatConversations.setTitleView(object : + ConversationsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatConversationsListItemsBinding? + ): View? { + return null + } + + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + } +}) +``` + + + +```java lines +cometchatConversations.setTitleView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return null; + } + @Override + public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { + + } +}); +``` + + +Inline user status example: + +Create a `custom_title_view.xml` layout: + +```xml custom_title_view.xml lines + + + + + + + +``` + +> **What this does:** Defines a custom title layout with the conversation name and an inline user status message. + + -```kotlin -cometchatConversations.setTrailingView(object : ConversationsViewHolderListener() { +```kotlin lines +cometchatConversations.setTitleView(object : ConversationsViewHolderListener() { override fun createView(context: Context?, listItem: CometchatConversationsListItemsBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null) + return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null) } override fun bindView( @@ -1523,97 +1286,117 @@ cometchatConversations.setTrailingView(object : ConversationsViewHolderListener( conversationList: List, position: Int ) { - val card = createdView.findViewById(R.id.card) - val tvHours = createdView.findViewById(R.id.hours) - val tvMessage = createdView.findViewById(R.id.time_title) - - var timestamp = conversation.updatedAt * 1000 + val name = createdView.findViewById(R.id.name) + val status = createdView.findViewById(R.id.status) - if (timestamp.toString().length == 10) { - // Convert seconds to milliseconds - timestamp *= 1000 + name.text = ConversationsUtils.getConversationTitle(conversation) + if (conversation.conversationType == CometChatConstants.RECEIVER_TYPE_USER) { + status.visibility = View.VISIBLE + status.text = "• " + (conversation.conversationWith as User).statusMessage + } else { + status.visibility = View.GONE } + } + }) +``` + - val now = Calendar.getInstance() - val lastSeen = Calendar.getInstance() - lastSeen.timeInMillis = timestamp + +```java lines +cometchatConversations.setTitleView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null); + } - val diffInMillis = now.timeInMillis - lastSeen.timeInMillis - val diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) - val diffInHours = TimeUnit.MILLISECONDS.toHours(diffInMillis) + @Override + public void bindView(Context context, + View createdView, + Conversation conversation, + RecyclerView.ViewHolder holder, + List conversationList, + int position) { - // Check if the timestamp is within the last hour - if (diffInMinutes == 0L) { - tvHours.text = "1" - tvMessage.text = "Min ago" - card.setCardBackgroundColor(Utils.applyColorWithAlphaValue(Color.parseColor("#6852D6"), 40)) - tvMessage.setTextColor(Color.parseColor("#6852D6")) - tvHours.setTextColor(Color.parseColor("#6852D6")) - return - } else if (diffInMinutes < 60) { - tvHours.text = diffInMinutes.toString() + "" - tvMessage.text = "Min ago" - card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#6852D6"), 40)) - tvMessage.setTextColor(Color.parseColor("#6852D6")) - tvHours.setTextColor(Color.parseColor("#6852D6")) - return - } + TextView name = createdView.findViewById(R.id.name); + TextView status = createdView.findViewById(R.id.status); - // Check if the timestamp is within the last 24 hours - if (diffInHours < 10) { - tvHours.text = diffInHours.toString() + "" - tvMessage.text = "Hr ago" - tvMessage.setTextColor(Color.parseColor("#FFAB00")) - tvHours.setTextColor(Color.parseColor("#FFAB00")) - card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#FFAB00"), 40)) - } else if (diffInHours < 1000) { - tvHours.text = diffInHours.toString() + "" - tvMessage.text = "Hr ago" - tvMessage.setTextColor(Color.parseColor("#F44649")) - tvHours.setTextColor(Color.parseColor("#F44649")) - card.setCardBackgroundColor(Utils.multiplyColorAlpha(Color.parseColor("#F44649"), 40)) + name.setText(ConversationsUtils.getConversationTitle(conversation)); + if (conversation.getConversationType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { + status.setVisibility(View.VISIBLE); + status.setText("• " + ((User) conversation.getConversationWith()).getStatusMessage()); + } else { + status.setVisibility(View.GONE); } } - }) + }); +``` + + + +> **What this does:** Registers a `ConversationsViewHolderListener` that provides a custom title view for each conversation item. The example inflates a layout with the conversation name and an inline user status message. For group conversations, the status is hidden. + +### `setSubtitleView` + +Replace the last message preview text. + + + +```kotlin lines +cometchatConversations.setSubtitleView(object : + ConversationsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatConversationsListItemsBinding? + ): View? { + return null + } + + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + } +}) ``` + + + +```java lines +cometchatConversations.setSubtitleView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return null; + } - + @Override + public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { + } +}); +``` + -Demonstration +Example with last-active timestamp: - + - -```java - cometchatConversations.setTrailingView(new ConversationsViewHolderListener() { - @Override - public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { - - } - }); -``` - - - -```kotlin - cometchatConversations.setTrailingView(object : +```kotlin lines + cometchatConversations.setSubtitleView(object : ConversationsViewHolderListener() { override fun createView( context: Context?, listItem: CometchatConversationsListItemsBinding? - ): View? { - return null + ): View { + return TextView(context) } override fun bindView( @@ -1624,87 +1407,99 @@ Demonstration conversationList: List, position: Int ) { + val tvSubtitle = createdView as TextView + tvSubtitle.text = + "Last Active at: " + SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format( + conversation.updatedAt * 1000 + ) + tvSubtitle.setTextColor(Color.BLACK) } }) ``` - - - -*** - -#### setItemView - -This function allows developers to assign a completely custom list item design to the Conversations Component, replacing the default layout. - -Use cases: - -* Implementing a unique conversation list design with custom styling -* Adding extra elements like swipe gestures, priority indicators, or group labels -* Fully customizing how messages are displayed in the list - - -```java - cometchatConversations.setItemView(new ConversationsViewHolderListener() { +```java YourActivity.java lines + cometchatConversations.setSubtitleView(new ConversationsViewHolderListener() { @Override public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return null; + return new TextView(context); } @Override public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { - + TextView tvSubtitle = (TextView) createdView; + tvSubtitle.setText("Last Active at: "+new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(conversation.getUpdatedAt() * 1000)); + tvSubtitle.setTextColor(Color.BLACK); } }); ``` - + + +> **What this does:** Registers a `ConversationsViewHolderListener` that provides a custom subtitle view for each conversation item. The example creates a `TextView` showing the last active timestamp formatted as "dd/MM/yyyy, HH:mm:ss". +### `setItemView` + +Replace the entire list item row. + + -```kotlin - cometchatConversations.setItemView(object : - ConversationsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatConversationsListItemsBinding? - ): View? { - return null - } +```kotlin lines +cometchatConversations.setItemView(object : + ConversationsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatConversationsListItemsBinding? + ): View? { + return null + } - override fun bindView( - context: Context, - createdView: View, - conversation: Conversation, - holder: RecyclerView.ViewHolder, - conversationList: List, - position: Int - ) { - } - }) + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + } +}) ``` - + +```java lines +cometchatConversations.setItemView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { + + } +}); +``` + -Demonstration +Example with compact layout: -You can create an `item_converation_list.xml` as a custom layout file. Which we will inflate in `setListItemView()` +Create an `item_converation_list.xml` custom layout file: -```html +```html lines + android:orientation="vertical"> - - - + - + + + +``` + +> **What this does:** Defines a custom list item layout with a `CometChatAvatar`, status indicator, conversation name, and date — providing a compact, single-line conversation item design. + +Inflate the XML and bind: + + + +```kotlin lines + cometchatConversations.setItemView(object : + ConversationsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatConversationsListItemsBinding? + ): View { + return LayoutInflater.from(context) + .inflate(R.layout.custom_list_item_view, null, false) + } + + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + val avatar = createdView.findViewById(R.id.custom_avatar) + val title = createdView.findViewById(R.id.tvName) + val tvDate = createdView.findViewById(R.id.tvDate) + + val name = ConversationsUtils.getConversationTitle(conversation) + title.text = name + avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle) + avatar.avatarPlaceHolderTextAppearance = + com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold + avatar.setAvatar(name, ConversationsUtils.getConversationAvatar(conversation)) + val simpleDateFormat = SimpleDateFormat("hh:mm a") + val date = simpleDateFormat.format(conversation.updatedAt * 1000) + tvDate.text = date + } + }) +``` + + + +```java YourActivity.java lines + cometchatConversations.setItemView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.custom_list_item_view, null, false); + } + + @Override + public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { + CometChatAvatar avatar = createdView.findViewById(R.id.custom_avatar); + TextView title = createdView.findViewById(R.id.tvName); + TextView tvDate = createdView.findViewById(R.id.tvDate); + + String name = ConversationsUtils.getConversationTitle(conversation); + title.setText(name); + avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle); + avatar.setAvatarPlaceHolderTextAppearance(com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold); + avatar.setAvatar(name, ConversationsUtils.getConversationAvatar(conversation)); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm a"); + String date = simpleDateFormat.format(conversation.getUpdatedAt() * 1000); + tvDate.setText(date); + } + }); +``` + + + +> **What this does:** Registers a `ConversationsViewHolderListener` that replaces the entire list item row. The example inflates a compact layout with an avatar, name, and date — replacing the default multi-line conversation item. + +### `setDateTimeFormatter` + +Custom date/time formatting for conversation timestamps. Implement the `DateTimeFormatterCallback` interface to control how each time range is displayed: + +| Method | Called when | +| --- | --- | +| `time(long timestamp)` | Custom full timestamp format | +| `today(long timestamp)` | Message is from today | +| `yesterday(long timestamp)` | Message is from yesterday | +| `lastWeek(long timestamp)` | Message is from the past week | +| `otherDays(long timestamp)` | Message is older than a week | +| `minute(long timestamp)` | Exactly 1 minute ago | +| `minutes(long diffInMinutesFromNow, long timestamp)` | Multiple minutes ago (e.g., "5 minutes ago") | +| `hour(long timestamp)` | Exactly 1 hour ago | +| `hours(long diffInHourFromNow, long timestamp)` | Multiple hours ago (e.g., "2 hours ago") | + + + +```kotlin lines +cometchatConversations.setDateTimeFormatter(object : DateTimeFormatterCallback { + + private val fullTimeFormatter = SimpleDateFormat("hh:mm a", Locale.getDefault()) + private val dateFormatter = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()) + + override fun time(timestamp: Long): String { + return fullTimeFormatter.format(Date(timestamp)) + } + + override fun today(timestamp: Long): String { + return "Today" + } + + override fun yesterday(timestamp: Long): String { + return "Yesterday" + } + + override fun lastWeek(timestamp: Long): String { + return "Last Week" + } + + override fun otherDays(timestamp: Long): String { + return dateFormatter.format(Date(timestamp)) + } + + override fun minutes(diffInMinutesFromNow: Long, timestamp: Long): String { + return "$diffInMinutesFromNow mins ago" + } + + override fun hours(diffInHourFromNow: Long, timestamp: Long): String { + return "$diffInHourFromNow hrs ago" + } + }) +``` + + + +```java lines +cometchatConversations.setDateTimeFormatter(new DateTimeFormatterCallback() { + + private final SimpleDateFormat fullTimeFormatter = new SimpleDateFormat("hh:mm a", Locale.getDefault()); + private final SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM yyyy", Locale.getDefault()); + + @Override + public String time(long timestamp) { + return fullTimeFormatter.format(new Date(timestamp)); + } + + @Override + public String today(long timestamp) { + return "Today"; + } + + @Override + public String yesterday(long timestamp) { + return "Yesterday"; + } + + @Override + public String lastWeek(long timestamp) { + return "Last Week"; + } + + @Override + public String otherDays(long timestamp) { + return dateFormatter.format(new Date(timestamp)); + } + + @Override + public String minutes(long diffInMinutesFromNow, long timestamp) { + return diffInMinutesFromNow + " mins ago"; + } + + @Override + public String hours(long diffInHourFromNow, long timestamp) { + return diffInHourFromNow + " hrs ago"; + } + }); +``` + + + +### `setOptions` - -``` +Replace the long-press context menu entirely. -In the method `setItemView` you need to inflate the XML and initialize the views using the conversation objects. +Generic signature: + +```kotlin lines +cometchatConversations.setOptions { context, conversation -> emptyList() } +``` + + -```java YourActivity.java - cometchatConversations.setItemView(new ConversationsViewHolderListener() { - @Override - public View createView(Context context, CometchatConversationsListItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.custom_list_item_view, null, false); - } +```java lines +cometchatConversations.setOptions((context, conversation) -> Collections.emptyList()); +``` + + - @Override - public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { - CometChatAvatar avatar = createdView.findViewById(R.id.custom_avatar); - TextView title = createdView.findViewById(R.id.tvName); - TextView tvDate = createdView.findViewById(R.id.tvDate); +Example with a custom delete option: - String name = ConversationsUtils.getConversationTitle(conversation); - title.setText(name); - avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle); - avatar.setAvatarPlaceHolderTextAppearance(com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold); - avatar.setAvatar(name, ConversationsUtils.getConversationAvatar(conversation)); - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm a"); - String date = simpleDateFormat.format(conversation.getUpdatedAt() * 1000); - tvDate.setText(date); - } - }); + + + + + + +```kotlin lines +cometchatConversations.setOptions { context, conversation -> + val optionsArrayList: MutableList = + ArrayList() + optionsArrayList.add( + CometChatPopupMenu.MenuItem( + UIKitConstants.ConversationOption.DELETE, + "Delete", + ResourcesCompat. getDrawable(resources,com.cometchat.chatuikit.R.drawable.cometchat_ic_delete, getContext()?.theme), + null, + CometChatTheme.getErrorColor(context), + 0, + CometChatTheme.getErrorColor(context), + CometChatTheme.getTextAppearanceBodyRegular(context) + ) { + Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show() + } + ) + optionsArrayList + } ``` + + +```java lines +cometchatConversations.setOptions((context, conversation) -> { +List optionsArrayList = new ArrayList<>(); +optionsArrayList.add(new CometChatPopupMenu.MenuItem(UIKitConstants.ConversationOption.DELETE, + "Delete", + getResources().getDrawable(com.cometchat.chatuikit.R.drawable.cometchat_ic_delete), + null, + CometChatTheme.getErrorColor(context), + 0, + CometChatTheme.getErrorColor(context), + CometChatTheme.getTextAppearanceBodyRegular(context), + () -> { + Toast.makeText(context, "Delete", Toast.LENGTH_SHORT).show(); + })); + return optionsArrayList; + }); +``` + - -```kotlin - cometchatConversations.setItemView(object : - ConversationsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatConversationsListItemsBinding? - ): View { - return LayoutInflater.from(context) - .inflate(R.layout.custom_list_item_view, null, false) - } +### `addOptions` - override fun bindView( - context: Context, - createdView: View, - conversation: Conversation, - holder: RecyclerView.ViewHolder, - conversationList: List, - position: Int - ) { - val avatar = createdView.findViewById(R.id.custom_avatar) - val title = createdView.findViewById(R.id.tvName) - val tvDate = createdView.findViewById(R.id.tvDate) +Append to the long-press context menu without removing defaults. - val name = ConversationsUtils.getConversationTitle(conversation) - title.text = name - avatar.setStyle(com.cometchat.chatuikit.R.style.CometChatAvatarStyle) - avatar.avatarPlaceHolderTextAppearance = - com.cometchat.chatuikit.R.style.CometChatTextAppearanceHeading4_Bold - avatar.setAvatar(name, ConversationsUtils.getConversationAvatar(conversation)) - val simpleDateFormat = SimpleDateFormat("hh:mm a") - val date = simpleDateFormat.format(conversation.updatedAt * 1000) - tvDate.text = date - } - }) -``` +Generic signature: + + +```kotlin lines +cometchatConversations.addOptions { context, conversation -> emptyList() } +``` + +```java lines +cometchatConversations.addOptions((context, conversation) -> Collections.emptyList()); +``` + -*** +Example with archive, pin, and mark-as-read options: -#### setTextFormatters + + + -This method enables developers to define and apply text formatters that dynamically modify or transform message content before rendering it in the UI. Text formatters can be used for purposes such as: + + +```kotlin lines +cometchatConversations.addOptions { context, conversation -> + val optionsArrayList: MutableList = ArrayList() + optionsArrayList.add( + CometChatPopupMenu.MenuItem( + "ARCHIVE", "Archive", + resources.getDrawable(R.drawable.archive), null, + CometChatTheme.getTextColorPrimary(context), 0, + CometChatTheme.getTextColorPrimary(context), + CometChatTheme.getTextAppearanceBodyRegular(context) + ) { Toast.makeText(context, "Archive", Toast.LENGTH_SHORT).show() } + ) + optionsArrayList.add( + CometChatPopupMenu.MenuItem( + "PIN", "Pin", + resources.getDrawable(R.drawable.pin), null, + CometChatTheme.getTextColorPrimary(context), 0, + CometChatTheme.getTextColorPrimary(context), + CometChatTheme.getTextAppearanceBodyRegular(context) + ) { Toast.makeText(context, "Pin", Toast.LENGTH_SHORT).show() } + ) + optionsArrayList.add( + CometChatPopupMenu.MenuItem( + "MARKASREAD", "Mark as read", + resources.getDrawable(R.drawable.mark_as_read), null, + CometChatTheme.getTextColorPrimary(context), 0, + CometChatTheme.getTextColorPrimary(context), + CometChatTheme.getTextAppearanceBodyRegular(context) + ) { Toast.makeText(context, "Mark as read", Toast.LENGTH_SHORT).show() } + ) + optionsArrayList + } +``` + -* Automatically converting URLs into clickable links -* Applying Markdown or rich text styling -* Replacing certain words or patterns with emojis or predefined text -* Censoring specific words for moderation + +```java lines +cometchatConversations.addOptions((context, conversation) -> { + List optionsArrayList = new ArrayList<>(); + optionsArrayList.add(new CometChatPopupMenu.MenuItem("ARCHIVE", + "Archive", + getResources().getDrawable(R.drawable.archive), + null, + CometChatTheme.getTextColorPrimary(context), + 0, + CometChatTheme.getTextColorPrimary(context), + CometChatTheme.getTextAppearanceBodyRegular(context), + () -> Toast.makeText(context, "Archive", Toast.LENGTH_SHORT).show())); + optionsArrayList.add(new CometChatPopupMenu.MenuItem("PIN", + "Pin", + getResources().getDrawable(R.drawable.pin), + null, + CometChatTheme.getTextColorPrimary(context), + 0, + CometChatTheme.getTextColorPrimary(context), + CometChatTheme.getTextAppearanceBodyRegular(context), + () -> Toast.makeText(context, "Pin", Toast.LENGTH_SHORT).show())); + optionsArrayList.add(new CometChatPopupMenu.MenuItem("MARKASREAD", + "Mark as read", + getResources().getDrawable(R.drawable.mark_as_read), + null, + CometChatTheme.getTextColorPrimary(context), + 0, + CometChatTheme.getTextColorPrimary(context), + CometChatTheme.getTextAppearanceBodyRegular(context), + () -> Toast.makeText(context, "Mark as read", Toast.LENGTH_SHORT).show())); + return optionsArrayList; + }); +``` + + -By utilizing this method, developers can enhance readability, usability, and compliance with content guidelines. [MentionsFormatter Guide](/ui-kit/android/mentions-formatter-guide) +### `setTextFormatters` -**Example** +Custom text formatters for the conversation subtitle. See the [MentionsFormatter Guide](/ui-kit/android/mentions-formatter-guide) for details. -```xml themes.xml +```xml themes.xml lines - @Override - public void bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position) { - TextView tvSubtitle = (TextView) createdView; - tvSubtitle.setText("Last Active at: "+new SimpleDateFormat("dd/mm/yyyy, HH:MM:SS").format(conversation.getUpdatedAt() * 1000)); - tvSubtitle.setTextColor(Color.BLACK); - } - }); -``` + - + +``` + -```kotlin - cometchatConversations.setSubtitleView(object : - ConversationsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatConversationsListItemsBinding? - ): View { - return TextView(context) - } - - override fun bindView( - context: Context, - createdView: View, - conversation: Conversation, - holder: RecyclerView.ViewHolder, - conversationList: List, - position: Int - ) { - val tvSubtitle = createdView as TextView - tvSubtitle.text = - "Last Active at: " + SimpleDateFormat("dd/mm/yyyy, HH:MM:SS").format( - conversation.updatedAt * 1000 - ) - tvSubtitle.setTextColor(Color.BLACK) - } - }) +```kotlin lines +cometChatConversations.setStyle(R.style.CustomConversationsStyle) ``` - + +```java lines +cometChatConversations.setStyle(R.style.CustomConversationsStyle); +``` + + +To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_conversations.xml). + +### Programmatic Style Properties + +In addition to XML theme styles, the component exposes programmatic setters for fine-grained control: + +| Method | Type | Description | +| --- | --- | --- | +| `setBackgroundColor` | `@ColorInt int` | Background color of the component | +| `setBackIconTint` | `@ColorInt int` | Tint color for the back icon | +| `setBackIcon` | `Drawable` | Custom back icon drawable | +| `setTitleTextColor` | `@ColorInt int` | Title text color in the toolbar | +| `setTitleTextAppearance` | `@StyleRes int` | Title text appearance in the toolbar | +| `setItemTitleTextColor` | `@ColorInt int` | Text color for conversation item titles | +| `setItemTitleTextAppearance` | `@StyleRes int` | Text appearance for conversation item titles | +| `setItemSubtitleTextColor` | `@ColorInt int` | Text color for conversation item subtitles | +| `setItemSubtitleTextAppearance` | `@StyleRes int` | Text appearance for conversation item subtitles | +| `setItemMessageTypeIconTint` | `@ColorInt int` | Tint for message type icons in subtitles | +| `setSeparatorColor` | `@ColorInt int` | Color of list item separators | +| `setSeparatorHeight` | `@Dimension int` | Height of list item separators | +| `setStrokeColor` | `@ColorInt int` | Stroke color of the component border | +| `setStrokeWidth` | `@Dimension int` | Stroke width of the component border | +| `setCornerRadius` | `@Dimension int` | Corner radius of the component | +| `setEmptyStateTitleTextColor` | `@ColorInt int` | Title text color for the empty state | +| `setEmptyStateSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the empty state | +| `setEmptyStateTextTitleAppearance` | `@StyleRes int` | Title text appearance for the empty state | +| `setEmptyStateTextSubtitleAppearance` | `@StyleRes int` | Subtitle text appearance for the empty state | +| `setErrorStateTitleTextColor` | `@ColorInt int` | Title text color for the error state | +| `setErrorStateSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the error state | +| `setErrorStateTextTitleAppearance` | `@StyleRes int` | Title text appearance for the error state | +| `setErrorStateTextSubtitleAppearance` | `@StyleRes int` | Subtitle text appearance for the error state | +| `setDeleteOptionIcon` | `Drawable` | Icon for the delete option in the context menu | +| `setDeleteOptionIconTint` | `int` | Tint for the delete option icon | +| `setDeleteOptionTextColor` | `int` | Text color for the delete option | +| `setDeleteOptionTextAppearance` | `int` | Text appearance for the delete option | +| `setAvatarStyle` | `@StyleRes int` | Style for conversation avatars | +| `setStatusIndicatorStyle` | `@StyleRes int` | Style for online/offline status indicators | +| `setBadgeStyle` | `@StyleRes int` | Style for unread badge counts | +| `setReceiptStyle` | `@StyleRes int` | Style for read/delivered receipt icons | +| `setTypingIndicatorStyle` | `@StyleRes int` | Style for typing indicator text | +| `setMentionsStyle` | `@StyleRes int` | Style for @mention text in subtitles | +| `setItemBackgroundColor` | `@ColorInt int` | Background color for list items | +| `setItemSelectedBackgroundColor` | `@ColorInt int` | Background color for selected list items | + +### Checkbox Style Properties (Selection Mode) + +When using `SINGLE` or `MULTIPLE` selection mode, checkboxes appear on each item: + +| Method | Type | Description | +| --- | --- | --- | +| `setCheckBoxStrokeWidth` | `@Dimension int` | Stroke width of the checkbox border | +| `setCheckBoxCornerRadius` | `@Dimension int` | Corner radius of the checkbox | +| `setCheckBoxStrokeColor` | `@ColorInt int` | Stroke color of the checkbox border | +| `setCheckBoxBackgroundColor` | `@ColorInt int` | Background color of unchecked checkbox | +| `setCheckBoxCheckedBackgroundColor` | `@ColorInt int` | Background color of checked checkbox | +| `setCheckBoxSelectIcon` | `Drawable` | Icon shown when checkbox is checked | +| `setCheckBoxSelectIconTint` | `@ColorInt int` | Tint for the checkbox select icon | +| `setDiscardSelectionIcon` | `Drawable` | Icon for the discard selection button | +| `setDiscardSelectionIconTint` | `@ColorInt int` | Tint for the discard selection icon | +| `setSubmitSelectionIcon` | `Drawable` | Icon for the submit selection button | +| `setSubmitSelectionIconTint` | `@ColorInt int` | Tint for the submit selection icon | + +## Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Activity/Fragment | `setOn` callbacks | `setOnItemClick((v, pos, c) -> { ... })` | +| Filter which conversations appear | Activity/Fragment | `setConversationsRequestBuilder` | `setConversationsRequestBuilder(builder)` | +| Toggle visibility of UI elements | Activity/Fragment | `setVisibility(int)` | `setReceiptsVisibility(View.GONE)` | +| Replace a section of the list item | Activity/Fragment | `setView` | `setLeadingView(listener)` | +| Change colors, fonts, spacing | `themes.xml` | `CometChatConversationsStyle` | `@style/...` | +| Avatar style (corner radius, background) | `themes.xml` | `cometchatConversationsAvatarStyle` | `8dp` | +| Badge count style (background, text color) | `themes.xml` | `cometchatConversationsBadgeStyle` | `#F76808` | +| Apply a custom style | Activity/Fragment | `setStyle(int styleRes)` | `cometChatConversations.setStyle(R.style.CustomConversationsStyle);` | +| Back button visibility | Activity/Fragment | `setBackIconVisibility(int)` | `.setBackIconVisibility(View.VISIBLE);` | +| Toolbar visibility | Activity/Fragment | `setToolbarVisibility(int)` | `.setToolbarVisibility(View.GONE);` | +| Loading state visibility | Activity/Fragment | `setLoadingStateVisibility(int)` | `.setLoadingStateVisibility(View.GONE);` | +| Delete option visibility on long press | Activity/Fragment | `setDeleteConversationOptionVisibility(int)` | `.setDeleteConversationOptionVisibility(View.GONE);` | +| Error state visibility | Activity/Fragment | `setErrorStateVisibility(int)` | `.setErrorStateVisibility(View.GONE);` | +| Empty state visibility | Activity/Fragment | `setEmptyStateVisibility(int)` | `.setEmptyStateVisibility(View.GONE);` | +| Separator visibility | Activity/Fragment | `setSeparatorVisibility(int)` | `.setSeparatorVisibility(View.GONE);` | +| User online status visibility | Activity/Fragment | `setUserStatusVisibility(int)` | `.setUserStatusVisibility(View.GONE);` | +| Group type indicator visibility | Activity/Fragment | `setGroupTypeVisibility(int)` | `.setGroupTypeVisibility(View.GONE);` | +| Read/delivered receipts visibility | Activity/Fragment | `setReceiptsVisibility(int)` | `.setReceiptsVisibility(View.GONE);` | +| Incoming message sound | Activity/Fragment | `disableSoundForMessages(boolean)` | `.disableSoundForMessages(true);` | +| Custom message sound | Activity/Fragment | `setCustomSoundForMessages(int)` | `.setCustomSoundForMessages(R.raw.cometchat_beep2);` | +| Selection mode (single/multiple) | Activity/Fragment | `setSelectionMode(SelectionMode)` | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | +| Date/time formatting | Activity/Fragment | `setDateTimeFormatter(DateTimeFormatterCallback)` | See `setDateTimeFormatter` code above | +| Date format | Activity/Fragment | `setDateFormat(SimpleDateFormat)` | `.setDateFormat(new SimpleDateFormat("dd MMM, hh:mm a", Locale.getDefault()));` | +| Long-press options (replace) | Activity/Fragment | `setOptions(Function2)` | See `setOptions` code above | +| Long-press options (append) | Activity/Fragment | `addOptions(Function2)` | See `addOptions` code above | +| Loading view | Activity/Fragment | `setLoadingView(int)` | `.setLoadingView(R.layout.your_loading_view);` | +| Empty view | Activity/Fragment | `setEmptyView(int)` | `.setEmptyView(R.layout.your_empty_view);` | +| Error view | Activity/Fragment | `setErrorView(int)` | `.setErrorView(R.layout.your_error_view);` | +| Leading view (avatar area) | Activity/Fragment | `setLeadingView(ConversationsViewHolderListener)` | See `setLeadingView` code above | +| Title view | Activity/Fragment | `setTitleView(ConversationsViewHolderListener)` | See `setTitleView` code above | +| Trailing view | Activity/Fragment | `setTrailingView(ConversationsViewHolderListener)` | See `setTrailingView` code above | +| Entire list item | Activity/Fragment | `setItemView(ConversationsViewHolderListener)` | See `setItemView` code above | +| Subtitle view | Activity/Fragment | `setSubtitleView(ConversationsViewHolderListener)` | See `setSubtitleView` code above | +| Text formatters (mentions) | Activity/Fragment | `setTextFormatters(List)` | See `setTextFormatters` code above | +| Overflow menu | Activity/Fragment | `setOverflowMenu(View)` | `cometChatConversations.setOverflowMenu(view);` | +| Filter conversations | Activity/Fragment | `setConversationsRequestBuilder(ConversationsRequestBuilder)` | See Filters code above | +| Search box visibility | Activity/Fragment | `setSearchBoxVisibility(int)` | `.setSearchBoxVisibility(View.GONE);` | +| Search input text | Activity/Fragment | `setSearchInputText(String)` | `.setSearchInputText("search term");` | +| Search placeholder text | Activity/Fragment | `setSearchPlaceholderText(String)` | `.setSearchPlaceholderText("Search...");` | +| Search input colors | Activity/Fragment | `setSearchInputTextColor`, `setSearchInputBackgroundColor` | `.setSearchInputTextColor(Color.BLACK);` | +| Search input icons | Activity/Fragment | `setSearchInputStartIcon`, `setSearchInputEndIcon` | `.setSearchInputStartIcon(drawable);` | +| Hide receipts (adapter) | Activity/Fragment | `hideReceipts(boolean)` | `.hideReceipts(true);` | +| Programmatic selection | Activity/Fragment | `selectConversation(Conversation, SelectionMode)` | `.selectConversation(conv, SelectionMode.SINGLE);` | +| Clear selection | Activity/Fragment | `clearSelection()` | `.clearSelection();` | +| Selected conversations strip | Activity/Fragment | `setSelectedConversationsListVisibility(int)` | `.setSelectedConversationsListVisibility(View.VISIBLE);` | +| Selected conversation avatar style | Activity/Fragment | `setSelectedConversationAvatarStyle(int)` | `.setSelectedConversationAvatarStyle(R.style.CustomAvatarStyle);` | +| Internal adapter access | Activity/Fragment | `getConversationsAdapter()` / `setAdapter()` | Advanced use only | +| Internal ViewModel access | Activity/Fragment | `getViewModel()` | Advanced use only | +| Mention-all label | Activity/Fragment | `setMentionAllLabelId(String, String)` | `.setMentionAllLabelId("all", "Everyone");` | + +## Accessibility + +The component renders a scrollable `RecyclerView` of interactive conversation items. Each conversation row responds to tap and long-press gestures. The unread badge count is rendered as a `TextView` with the count as text content, accessible to TalkBack. Avatar images include the conversation name as content description. + +For custom views provided via `setLeadingView`, `setTitleView`, `setTrailingView`, or `setItemView`, ensure you set `android:contentDescription` on visual-only elements (status indicators, icons) so TalkBack can announce them. The default views handle this automatically. + +Group type indicators and online/offline status dots are visual-only by default. If screen reader descriptions are needed for these, provide them via a custom view with appropriate `contentDescription` attributes. + +## Next Steps + + + + Browse and search available users + + + Browse and search available groups + + + Display messages in a conversation + + + Rich input for sending messages + + diff --git a/ui-kit/android/core-features.mdx b/ui-kit/android/core-features.mdx index ecc7e1470..cec440708 100644 --- a/ui-kit/android/core-features.mdx +++ b/ui-kit/android/core-features.mdx @@ -1,12 +1,21 @@ --- title: "Core" +description: "Overview of CometChat's core chat features including instant messaging, media sharing, read receipts, typing indicators, user presence, reactions, mentions, threaded conversations, search, and moderation." --- -## Overview + -The UI Kit comprises a variety of components, each designed to work seamlessly with one another to deliver a comprehensive and intuitive chat experience. +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Required setup | `CometChatUIKit.init()` then `CometChatUIKit.login()` — must complete before rendering any component | +| Core features | Instant Messaging, Media Sharing, Read Receipts, Mark as Unread, Typing Indicator, User Presence, Reactions, Mentions, Quoted Reply, Search, Threaded Conversations, Moderation, Report Message, Group Chat | +| Key components | `CometChatConversations` → [Conversations](/ui-kit/android/conversations), `CometChatMessageList` → [Message List](/ui-kit/android/message-list), `CometChatMessageComposer` → [Message Composer](/ui-kit/android/message-composer), `CometChatMessageHeader` → [Message Header](/ui-kit/android/message-header), `CometChatUsers` → [Users](/ui-kit/android/users), `CometChatGroups` → [Groups](/ui-kit/android/groups), `CometChatGroupMembers` → [Group Members](/ui-kit/android/group-members) | +| Theming | Override theme attributes in `themes.xml`. See [Theming](/ui-kit/android/theme-introduction) | -Here's how different UI Kit components work together to achieve CometChat's Core features: + + +The UI Kit components work together to deliver a complete chat experience. The sections below map each core feature to the components that power it. ## Instant Messaging @@ -53,7 +62,7 @@ CometChat's Read Receipts feature provides visibility into the message status, l | [MessageList](/ui-kit/android/message-list) | [MessageList](/ui-kit/android/message-list) is a Component that renders different types of Message bubbles, Read Recept status is an integral part of all message bubbles, no matter the type, and provides real-time updates about the status of the message. | | [MessageInformation](/ui-kit/android/component-styling#message-information) | [MessageInformation](/ui-kit/android/component-styling#message-information) component provides transparency into the status of each sent message, giving the sender insights into whether their message has been delivered and read. | -## Mark As Unread +## Mark as Unread Mark as Unread feature allows users to manually mark messages as unread, helping them keep track of important conversations they want to revisit later. When enabled, the message list can automatically start from the first unread message, making it easier to pick up where you left off. @@ -66,9 +75,9 @@ Mark as Unread feature allows users to manually mark messages as unread, helping | [Message List](/ui-kit/android/message-list) | [Message List](/ui-kit/android/message-list) provides the "Mark as unread" option in message actions and supports starting from the first unread message when enabled. | | [Conversations](/ui-kit/android/conversations) | [Conversations](/ui-kit/android/conversations) component listens to conversation updates and reflects the updated unread count in real-time. | -## Typing Indicator +## Typing Indicators -The Typing Indicator feature in CometChat shows when a user is typing a response in real-time, fostering a more interactive and engaging chat environment. This feature enhances the real-time communication experience, making conversations feel more natural and fluid. +Typing Indicators in CometChat show when a user is typing a response in real-time, fostering a more interactive and engaging chat environment. This feature enhances the real-time communication experience, making conversations feel more natural and fluid. @@ -91,7 +100,7 @@ CometChat's User Presence feature allows users to see whether their contacts are | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Conversations](/ui-kit/android/conversations) | [Conversations](/ui-kit/android/conversations) is a Component that renders Conversations item List, Conversations item also shows user presence information. | | [Message Header](/ui-kit/android/message-header) | [Message Header](/ui-kit/android/message-header) that renders details of User or Groups in ToolBar. The MessageHeader also handles user Presence information. | -| [Users](/ui-kit/android/users) | [Users](/ui-kit/android/users) renders list of users available in your app.It also responsible to render users Presence information. | +| [Users](/ui-kit/android/users) | [Users](/ui-kit/android/users) renders a list of users available in your app. It is also responsible for rendering user presence information. | | [Group Members](/ui-kit/android/group-members) | [Group Members](/ui-kit/android/group-members) renders list of users available in the group. The Group Members component also handles user Presence information. | ## Reactions @@ -117,12 +126,26 @@ Mentions is a robust feature provided by CometChat that enhances the interactivi | Components | Functionality | | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Conversations](/ui-kit/android/conversations) | [Conversations](/ui-kit/android/conversations) component provides an enhanced user experience by integrating the Mentions feature. This means that from the conversation list itself, users can see where they or someone else have been specifically mentioned. | -| [MessageComposer](/ui-kit/android/message-composer) | [MessageComposer](/ui-kit/android/message-composer)is a component that allows users to craft and send various types of messages, including the usage of the Mentions feature for direct addressing within the conversation. | +| [MessageComposer](/ui-kit/android/message-composer) | [MessageComposer](/ui-kit/android/message-composer) is a component that allows users to craft and send various types of messages, including the usage of the Mentions feature for direct addressing within the conversation. | | [MessageList](/ui-kit/android/message-list) | [MessageList](/ui-kit/android/message-list) is a component that displays a list of sent and received messages. It also supports the rendering of Mentions, enhancing the readability and interactivity of conversations. | -## Quoted Reply +## Threaded Conversations -Quoted Reply is a robust feature provided by CometChat that enables users to quickly reply to specific messages by selecting the "Reply" option from a message's action menu. This enhances context, keeps conversations organized, and improves overall chat experience in both 1-1 and group chats. +The Threaded Conversations feature enables users to respond directly to a specific message in a chat. This keeps conversations organized and enhances the user experience by maintaining context, especially in group chats. + + + + + +| Components | Functionality | +| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Threaded Header](/ui-kit/android/threaded-messages-header) | [Threaded Header](/ui-kit/android/threaded-messages-header) that displays all replies made to a particular message in a conversation. | +| [MessageComposer](/ui-kit/android/message-composer) | [MessageComposer](/ui-kit/android/message-composer) is a component that allows users to craft and send various types of messages, including the usage of the Mentions feature for direct addressing within the conversation. | +| [MessageList](/ui-kit/android/message-list) | [MessageList](/ui-kit/android/message-list) is a component that displays a list of sent and received messages. It also supports the rendering of Mentions, enhancing the readability and interactivity of conversations. | + +## Quoted Replies + +Quoted Replies are a robust feature provided by CometChat that enables users to quickly reply to specific messages by selecting the "Reply" option from a message's action menu. This enhances context, keeps conversations organized, and improves overall chat experience in both 1-1 and group chats. @@ -133,20 +156,15 @@ Quoted Reply is a robust feature provided by CometChat that enables users to qui | [Message List](/ui-kit/android/message-list) | [Message List](/ui-kit/android/message-list) supports replying to messages via the "Reply" option. Users can select "Reply" on a message to open the composer with the quoted reply pre-filled, maintaining context. | | [Message Composer](/ui-kit/android/message-composer) | [Message Composer](/ui-kit/android/message-composer) works seamlessly with Quoted Message by showing the quoted reply above the input field, letting users compose their response in proper context. | -## Conversation and Advanced Search +## Group Chats -Conversation and Advanced Search is a powerful feature provided by CometChat that enables users to quickly find conversations, messages, and media across chats in real time. It supports filters, scopes, and custom actions, allowing users to locate content efficiently while keeping the chat experience smooth and intuitive. +CometChat facilitates Group Chats, allowing users to have conversations with multiple participants simultaneously. This feature is crucial for team collaborations, group discussions, social communities, and more. - + -| Components | Functionality | -| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Search](/ui-kit/android/search) | [Search](/ui-kit/android/search) allows users to search across conversations and messages in real time. Users can click on a result to open the conversation or jump directly to a specific message. | -| [Message Header](/ui-kit/android/message-header) | [Message Header](/ui-kit/android/message-header) shows the search button in the chat header, allowing users to search within a conversation. | -| [Message List](/ui-kit/android/message-list) | [Message List](/ui-kit/android/message-list) shows the selected message when clicked from search results and highlights it in the message list. | -| [Conversations](/ui-kit/android/conversations) | [Conversations](/ui-kit/android/conversations) displays the search input. | +For a comprehensive understanding and guide on implementing and using the Groups feature in CometChat, you should refer to our detailed guide on [Groups](/ui-kit/android/groups). ## Moderation @@ -182,26 +200,36 @@ Learn more about how flagged messages are handled, reviewed, and moderated in th | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Message List](/ui-kit/android/message-list) | [Message List](/ui-kit/android/message-list) provides the "Report Message" option in the message actions menu, allowing users to initiate the reporting process for inappropriate messages. | -## Threaded Conversations +## Conversation and Advanced Search -The Threaded Conversations feature enables users to respond directly to a specific message in a chat. This keeps conversations organized and enhances the user experience by maintaining context, especially in group chats. +Conversation and Advanced Search is a powerful feature provided by CometChat that enables users to quickly find conversations, messages, and media across chats in real time. It supports filters, scopes, and custom actions, allowing users to locate content efficiently while keeping the chat experience smooth and intuitive. - + -| Components | Functionality | -| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Threaded Header](/ui-kit/android/threaded-messages-header) | [Threaded Header](/ui-kit/android/threaded-messages-header) that displays all replies made to a particular message in a conversation. | -| [MessageComposer](/ui-kit/android/message-composer) | [MessageComposer](/ui-kit/android/message-composer)is a component that allows users to craft and send various types of messages, including the usage of the Mentions feature for direct addressing within the conversation. | -| [MessageList](/ui-kit/android/message-list) | [MessageList](/ui-kit/android/message-list) is a component that displays a list of sent and received messages. It also supports the rendering of Mentions, enhancing the readability and interactivity of conversations. | - -## Group Chat - -CometChat facilitates Group Chats, allowing users to have conversations with multiple participants simultaneously. This feature is crucial for team collaborations, group discussions, social communities, and more. +| Components | Functionality | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Search](/ui-kit/android/search) | [Search](/ui-kit/android/search) allows users to search across conversations and messages in real time. Users can click on a result to open the conversation or jump directly to a specific message. | +| [Message Header](/ui-kit/android/message-header) | [Message Header](/ui-kit/android/message-header) shows the search button in the chat header, allowing users to search within a conversation. | +| [Message List](/ui-kit/android/message-list) | [Message List](/ui-kit/android/message-list) shows the selected message when clicked from search results and highlights it in the message list. | +| [Conversations](/ui-kit/android/conversations) | [Conversations](/ui-kit/android/conversations) displays the search input. | - - - +--- -For a comprehensive understanding and guide on implementing and using the Groups feature in CometChat, you should refer to our detailed guide on [Groups](/ui-kit/android/groups). +## Next Steps + + + + Browse all available UI Kit components + + + Customize the look and feel of your chat UI + + + Add audio and video calling + + + Explore AI-powered chat capabilities + + diff --git a/ui-kit/android/custom-text-formatter-guide.mdx b/ui-kit/android/custom-text-formatter-guide.mdx new file mode 100644 index 000000000..fbda68dbe --- /dev/null +++ b/ui-kit/android/custom-text-formatter-guide.mdx @@ -0,0 +1,220 @@ +--- +title: "Custom Text Formatter" +sidebarTitle: "Custom Text Formatter" +description: "Extend CometChatTextFormatter to build custom inline text patterns with tracking characters and suggestion lists." +--- + + + +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Key class | `CometChatTextFormatter` (abstract base class for custom formatters) | +| Required setup | `CometChatUIKit.init()` then `CometChatUIKit.login("UID")` | +| Purpose | Extend to create custom inline text patterns with tracking characters, suggestion lists, and span formatting | +| Features | Tracking character activation, suggestion list, span formatting per context (composer, bubbles, conversations), pre-send hooks | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-android/tree/v5/sample-app-kotlin) | +| Related | [Mentions Formatter](/ui-kit/android/mentions-formatter-guide) \| [ShortCut Formatter](/ui-kit/android/shortcut-formatter-guide) \| [All Guides](/ui-kit/android/guide-overview) | + + + +`CometChatTextFormatter` is an abstract class for formatting text in the message composer and message bubbles. Extend it to build custom formatters — hashtags, shortcuts, or any pattern triggered by a tracking character. + +| Capability | Description | +| --- | --- | +| Tracking character | Activates the formatter when the user types a specific character (e.g., `#`, `!`) | +| Suggestion list | Populates a dropdown of `SuggestionItem` objects as the user types | +| Span formatting | Applies `SpannableStringBuilder` spans per context: composer, left/right bubbles, conversations | +| Pre-send hook | `handlePreMessageSend` lets you modify the message before it's sent | +| Component integration | Plugs into any component via `setTextFormatters()` | + +--- + +## Steps + +### 1. Create a class extending CometChatTextFormatter + +Pass your tracking character to the superclass constructor. + + + +```kotlin lines +class HashTagFormatter : CometChatTextFormatter('#') { + private val suggestions: MutableList = ArrayList() +} +``` + + +```java lines +public class HashTagFormatter extends CometChatTextFormatter { + private List suggestions = new ArrayList<>(); + + public HashTagFormatter() { + super('#'); + } +} +``` + + + +### 2. Override the search method + +Called when the user types after the tracking character. Match input against your data and update the suggestion list. + + + +```kotlin lines +override fun search(context: Context, queryString: String?) { + suggestions.clear() + val query = "#${queryString ?: ""}" + // Match against your hashtag data source + val matchingTags = getMatchingTags(query) + for (tag in matchingTags) { + val item = SuggestionItem("", tag, null, null, tag, null, null) + item.isHideLeadingIcon = true + suggestions.add(item) + } + setSuggestionItemList(suggestions) +} +``` + + +```java lines +@Override +public void search(@NonNull Context context, @Nullable String queryString) { + suggestions.clear(); + String query = "#" + (queryString != null ? queryString : ""); + // Match against your hashtag data source + List matchingTags = getMatchingTags(query); + for (String tag : matchingTags) { + SuggestionItem item = new SuggestionItem("", tag, null, null, tag, null, null); + item.setHideLeadingIcon(true); + suggestions.add(item); + } + setSuggestionItemList(suggestions); +} +``` + + + +### 3. Override onScrollToBottom + +Required by the base class. Implement pagination logic or leave empty. + + + +```kotlin +override fun onScrollToBottom() { + // Load more suggestions if needed +} +``` + + +```java +@Override +public void onScrollToBottom() { + // Load more suggestions if needed +} +``` + + + +### 4. Override span formatting methods (optional) + +Customize how matched text renders in different contexts using `SpannableStringBuilder`. + + + +```kotlin lines +override fun prepareLeftMessageBubbleSpan( + context: Context, baseMessage: BaseMessage, spannable: SpannableStringBuilder +): SpannableStringBuilder? { + // Apply custom spans for incoming message bubbles + return applyHashTagSpans(spannable, Color.parseColor("#5dff05")) +} + +override fun prepareRightMessageBubbleSpan( + context: Context, baseMessage: BaseMessage, spannable: SpannableStringBuilder +): SpannableStringBuilder? { + // Apply custom spans for outgoing message bubbles + return applyHashTagSpans(spannable, Color.parseColor("#30b3ff")) +} +``` + + +```java lines +@Override +public SpannableStringBuilder prepareLeftMessageBubbleSpan( + @NonNull Context context, @NonNull BaseMessage baseMessage, SpannableStringBuilder spannable) { + return applyHashTagSpans(spannable, Color.parseColor("#5dff05")); +} + +@Override +public SpannableStringBuilder prepareRightMessageBubbleSpan( + @NonNull Context context, @NonNull BaseMessage baseMessage, SpannableStringBuilder spannable) { + return applyHashTagSpans(spannable, Color.parseColor("#30b3ff")); +} +``` + + + +### 5. Integrate with a component + + + +```kotlin lines +val textFormatters = CometChatUIKit.getDataSource().getTextFormatters(this, messageComposer.additionParameter) +textFormatters.add(HashTagFormatter()) +messageComposer.setTextFormatters(textFormatters) +``` + + +```java lines +List textFormatters = CometChatUIKit.getDataSource().getTextFormatters(this, messageComposer.getAdditionParameter()); +textFormatters.add(new HashTagFormatter()); +messageComposer.setTextFormatters(textFormatters); +``` + + + +Pass the same list to `CometChatMessageList` and `CometChatConversations` via their `setTextFormatters()` methods to apply formatting across all contexts. + +--- + +## Methods Reference + +| Method | Description | +| --- | --- | +| `search(Context, String)` | Abstract — called when user types after the tracking character. Update the suggestion list here. | +| `onScrollToBottom()` | Abstract — called when the suggestion list scrolls to the bottom. Implement pagination or leave empty. | +| `onItemClick(Context, SuggestionItem, User, Group)` | Called when a suggestion item is selected. Override to customize insertion behavior. | +| `handlePreMessageSend(Context, BaseMessage)` | Called before a message is sent. Override to modify the message (e.g., add metadata). | +| `prepareLeftMessageBubbleSpan(Context, BaseMessage, SpannableStringBuilder)` | Override to format text in incoming message bubbles. | +| `prepareRightMessageBubbleSpan(Context, BaseMessage, SpannableStringBuilder)` | Override to format text in outgoing message bubbles. | +| `prepareComposerSpan(Context, BaseMessage, SpannableStringBuilder)` | Override to format text in the message composer. | +| `prepareConversationSpan(Context, BaseMessage, SpannableStringBuilder)` | Override to format text in the conversations list preview. | +| `setSuggestionItemList(List)` | Updates the suggestion dropdown with new items. | +| `setDisableSuggestions(boolean)` | Disables the suggestion dropdown entirely. (`protected` — accessible from subclasses only.) | +| `setInfoText(String)` | Sets informational text displayed above the suggestion list. | +| `setInfoVisibility(boolean)` | Toggles visibility of the info text. | +| `setShowLoadingIndicator(boolean)` | Shows/hides a loading spinner in the suggestion dropdown. | +| `getTrackingCharacter()` | Returns the tracking character passed to the constructor. | + +--- + +## Next Steps + + + + Built-in @mention formatting with styled tokens + + + Shortcut text expansion via the message-shortcuts extension + + + Browse all feature and formatter guides + + + Full working sample application on GitHub + + diff --git a/ui-kit/android/customization-adapters.mdx b/ui-kit/android/customization-adapters.mdx new file mode 100644 index 000000000..14a7adde5 --- /dev/null +++ b/ui-kit/android/customization-adapters.mdx @@ -0,0 +1,131 @@ +--- +title: "Adapters" +description: "Access or replace the RecyclerView Adapter to control how list items are rendered and manage list data directly." +--- + +List-based components like `CometChatConversations` use a `RecyclerView.Adapter` to bind data to list items. You can access the default adapter to manipulate data, or replace it entirely with a custom implementation. + +## Accessing the Adapter + + + +```kotlin +val conversations = CometChatConversations(context) +val adapter: ConversationsAdapter = conversations.getConversationsAdapter() +``` + + +```java +CometChatConversations conversations = new CometChatConversations(context); +ConversationsAdapter adapter = conversations.getConversationsAdapter(); +``` + + + +## Replacing the Adapter + +Use `setAdapter` to replace the default adapter with a custom implementation: + + + +```kotlin +val customAdapter = ConversationsAdapter(context) +// Configure your custom adapter... +conversations.setAdapter(customAdapter) +``` + + +```java +ConversationsAdapter customAdapter = new ConversationsAdapter(context); +// Configure your custom adapter... +conversations.setAdapter(customAdapter); +``` + + + +## Data Manipulation API + +The adapter provides methods to programmatically manage the list data: + +| Method | Description | +|---|---| +| `setList(List)` | Replace the entire list | +| `addList(List)` | Append conversations to the end | +| `add(Conversation)` | Add a single conversation to the end | +| `add(int position, Conversation)` | Insert a conversation at a specific position | +| `remove(int position)` | Remove a conversation by position | +| `remove(Conversation)` | Remove a specific conversation | +| `clear()` | Remove all conversations | +| `updateConversation(Conversation)` | Update an existing conversation in place | +| `getConversationsList()` | Get the current list of conversations | + + + +```kotlin +val adapter = conversations.getConversationsAdapter() + +// Get the current list +val currentList = adapter.getConversationsList() + +// Add a conversation at the top +adapter.add(0, newConversation) + +// Remove a conversation +adapter.remove(conversation) + +// Replace the entire list +adapter.setList(filteredConversations) +``` + + +```java +ConversationsAdapter adapter = conversations.getConversationsAdapter(); + +// Get the current list +List currentList = adapter.getConversationsList(); + +// Add a conversation at the top +adapter.add(0, newConversation); + +// Remove a conversation +adapter.remove(conversation); + +// Replace the entire list +adapter.setList(filteredConversations); +``` + + + + +## View Slots on the Adapter + +The adapter exposes the same view slot setters as the View layer. When you set a view slot on the View (e.g., `conversations.setSubtitleView(...)`), it delegates to the adapter internally. You can also set view slots directly on the adapter: + +| Adapter Method | Equivalent View Method | +|---|---| +| `adapter.setLeadingView(...)` | `conversations.setLeadingView(...)` | +| `adapter.setTitleView(...)` | `conversations.setTitleView(...)` | +| `adapter.setSubtitleView(...)` | `conversations.setSubtitleView(...)` | +| `adapter.setTrailingView(...)` | `conversations.setTrailingView(...)` | +| `adapter.setItemView(...)` | `conversations.setItemView(...)` | + +Setting view slots directly on the adapter is useful when you've replaced the adapter with `setAdapter` and need to configure it before attaching. + +## Adapter Style Propagation + +The adapter has its own style setter methods. These are typically called internally by the View layer, but you can use them directly when working with a custom adapter: + +| Method | Applies To | +|---|---| +| `setConversationsAvatarStyle(@StyleRes int)` | Avatar style for list items | +| `setConversationsBadgeStyle(@StyleRes int)` | Unread badge style | +| `setConversationsReceiptStyle(@StyleRes int)` | Message receipt icon style | +| `setConversationsDateStyle(@StyleRes int)` | Date/time label style | +| `setConversationsTypingIndicatorStyle(@StyleRes int)` | Typing indicator style | +| `setConversationsStatusIndicatorStyle(@StyleRes int)` | Online/offline status indicator style | + +## Related + +- [View Slots](/ui-kit/android/customization-view-slots) — Learn the ViewHolderListener pattern used by adapter view slots. +- [ViewModel & Data](/ui-kit/android/customization-viewmodel-data) — Manage data at the ViewModel level instead of the adapter. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-datasource.mdx b/ui-kit/android/customization-datasource.mdx new file mode 100644 index 000000000..b2049b6f3 --- /dev/null +++ b/ui-kit/android/customization-datasource.mdx @@ -0,0 +1,155 @@ +--- +title: "DataSource & ChatConfigurator" +description: "Extend or override message templates, bubble content views, and other message-level behaviors at a global level using the DataSource decorator framework." +--- + +The DataSource framework is the most powerful customization mechanism in the UI Kit. It lets you globally modify how messages are rendered, what options appear on message bubbles, what attachment actions are available in the composer, and how text is formatted — all without touching individual components. + +## DataSource Interface + +The `DataSource` interface defines how the UI Kit provides: + +- Message templates (how each message type is rendered) +- Bubble content views (the actual views inside message bubbles) +- Message options (actions on message bubbles like reply, copy, delete) +- Attachment options (composer actions like camera, gallery, file) +- AI options (AI-powered composer actions) +- Text formatters (text processing for mentions, links, etc.) + +## DataSourceDecorator Pattern + +`DataSourceDecorator` is an abstract class that wraps a `DataSource` and delegates all method calls to it. You extend it and override only the methods you want to customize. This is the decorator pattern — you layer behavior on top of the existing implementation. + +```mermaid +graph LR + CC["ChatConfigurator"] --> D["Your DataSourceDecorator"] + D --> M["MessagesDataSource (default)"] +``` + +## ChatConfigurator + +`ChatConfigurator` manages the active `DataSource` instance: + +| Method | Description | +|---|---| +| `ChatConfigurator.enable(Function1)` | Register a decorator that wraps the current active DataSource | +| `ChatConfigurator.init()` | Reset to the default `MessagesDataSource` | + +You can chain multiple decorators by calling `enable` multiple times. Each call wraps the previous DataSource. + +## Example: Adding a Custom Message Option + +Create a `DataSourceDecorator` that adds a "Translate" option to all text messages: + + + + +```kotlin +class TranslateDataSource(dataSource: DataSource) : DataSourceDecorator(dataSource) { + + override fun getTextMessageOptions( + context: Context, + baseMessage: BaseMessage, + group: Group?, + additionParameter: AdditionParameter + ): List { + val options = super.getTextMessageOptions(context, baseMessage, group, additionParameter).toMutableList() + options.add(CometChatMessageOption( + id = "translate", + title = "Translate", + icon = R.drawable.ic_translate, + onClick = { translateMessage(baseMessage) } + )) + return options + } +} + +// Register the decorator +ChatConfigurator.enable { dataSource -> TranslateDataSource(dataSource) } + +// Reset to defaults when needed +ChatConfigurator.init() +``` + + +```java +public class TranslateDataSource extends DataSourceDecorator { + public TranslateDataSource(DataSource dataSource) { + super(dataSource); + } + + @Override + public List getTextMessageOptions( + Context context, BaseMessage baseMessage, Group group, @NonNull AdditionParameter additionParameter) { + List options = + new ArrayList<>(super.getTextMessageOptions(context, baseMessage, group, additionParameter)); + options.add(new CometChatMessageOption( + "translate", "Translate", R.drawable.ic_translate, + () -> translateMessage(baseMessage) + )); + return options; + } +} + +// Register the decorator +ChatConfigurator.enable(dataSource -> new TranslateDataSource(dataSource)); + +// Reset to defaults when needed +ChatConfigurator.init(); +``` + + + +## Message Template Methods + +Message templates define how each message type is rendered. Override these to add custom message types or modify existing ones: + +| Method | Description | +|---|---| +| `getTextTemplate(AdditionParameter)` | Template for text messages | +| `getImageTemplate(AdditionParameter)` | Template for image messages | +| `getVideoTemplate(AdditionParameter)` | Template for video messages | +| `getAudioTemplate(AdditionParameter)` | Template for audio messages | +| `getFileTemplate(AdditionParameter)` | Template for file messages | +| `getFormTemplate(AdditionParameter)` | Template for form messages | +| `getSchedulerTemplate(AdditionParameter)` | Template for scheduler messages | +| `getCardTemplate(AdditionParameter)` | Template for card messages | +| `getAIAssistantTemplate(AdditionParameter)` | Template for AI assistant messages | +| `getMessageTemplates(AdditionParameter)` | All message templates combined | +| `getMessageTemplate(String category, String type, AdditionParameter)` | Template for a specific category/type | + +## Bubble Content View Methods + +Each message type has a pair of methods following the `createView` / `bindView` pattern: + +| Create Method | Bind Method | Message Type | +|---|---|---| +| `getTextBubbleContentView(...)` | `bindTextBubbleContentView(...)` | Text | +| `getImageBubbleContentView(...)` | `bindImageBubbleContentView(...)` | Image | +| `getVideoBubbleContentView(...)` | `bindVideoBubbleContentView(...)` | Video | +| `getAudioBubbleContentView(...)` | `bindAudioBubbleContentView(...)` | Audio | +| `getFileBubbleContentView(...)` | `bindFileBubbleContentView(...)` | File | +| `getFormBubbleContentView(...)` | `bindFormBubbleContentView(...)` | Form | +| `getSchedulerBubbleContentView(...)` | `bindSchedulerBubbleContentView(...)` | Scheduler | +| `getCardBubbleContentView(...)` | `bindCardBubbleContentView(...)` | Card | +| `getAIAssistantBubbleContentView(...)` | `bindAIAssistantBubbleContentView(...)` | AI Assistant | + +The `get*` method creates the View (called once per ViewHolder), and the `bind*` method populates it with data (called on each bind). Override these to completely replace how a message type is rendered inside its bubble. + +## Other DataSource Methods + +| Method | Description | +|---|---| +| `getAttachmentOptions(Context, User, Group, HashMap, AdditionParameter)` | Composer attachment actions | +| `getAIOptions(Context, User, Group, HashMap, AIOptionsStyle, AdditionParameter)` | Composer AI actions | +| `getCommonOptions(Context, BaseMessage, Group, AdditionParameter)` | Options common to all message types | +| `getMessageOptions(Context, BaseMessage, Group, AdditionParameter)` | All options for a message | +| `getTextFormatters(Context, AdditionParameter)` | Text formatters for message processing | +| `getLastConversationMessage(Context, Conversation, AdditionParameter)` | Last message preview in conversations list | +| `getAuxiliaryHeaderMenu(Context, User, Group, AdditionParameter)` | Auxiliary header menu view | + +## Related + +- [Menu & Options](/ui-kit/android/customization-menu-options) — Component-level option customization. +- [Text Formatters](/ui-kit/android/customization-text-formatters) — Custom text processing via DataSource. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-events.mdx b/ui-kit/android/customization-events.mdx new file mode 100644 index 000000000..0f7dc4714 --- /dev/null +++ b/ui-kit/android/customization-events.mdx @@ -0,0 +1,205 @@ +--- +title: "Events & Callbacks" +description: "Handle user interaction events, selection mode, and global UI Kit events with component-level and static event listeners." +--- + +The UI Kit provides two levels of event handling: component-level callbacks set directly on a View instance, and global events registered via static listener methods on event classes. + +## Component-Level Callbacks + +### Click Callbacks + +| Setter | Triggered When | +|---|---| +| `setOnItemClick(OnItemClick)` | User taps a list item | +| `setOnItemLongClick(OnItemLongClick)` | User long-presses a list item | +| `setOnBackPressListener(OnBackPress)` | User taps the back button | +| `setOnSearchClickListener(OnSearchClick)` | User taps the search icon | + + + +```kotlin +conversations.setOnItemClick { conversation, position -> + // Navigate to chat screen + openChat(conversation) +} + +conversations.setOnItemLongClick { conversation, position -> + // Show custom context menu + showCustomMenu(conversation) +} + +conversations.setOnBackPressListener { + // Handle back navigation + finish() +} + +conversations.setOnSearchClickListener { + // Open search screen + openSearch() +} +``` + + +```java +conversations.setOnItemClick((conversation, position) -> { + // Navigate to chat screen + openChat(conversation); +}); + +conversations.setOnItemLongClick((conversation, position) -> { + // Show custom context menu + showCustomMenu(conversation); +}); + +conversations.setOnBackPressListener(() -> { + // Handle back navigation + finish(); +}); + +conversations.setOnSearchClickListener(() -> { + // Open search screen + openSearch(); +}); +``` + + + +### Error Callback + +Use `setOnError` to handle component-level errors: + + + +```kotlin +conversations.setOnError { exception -> + Log.e("Conversations", "Error: ${exception.message}") +} +``` + + +```java +conversations.setOnError(exception -> { + Log.e("Conversations", "Error: " + exception.getMessage()); +}); +``` + + + +## Selection Mode + +Enable single or multi-select on list components: + +| Method | Description | +|---|---| +| `setSelectionMode(UIKitConstants.SelectionMode)` | Set the selection mode: `NONE`, `SINGLE`, or `MULTIPLE` | +| `setOnSelect(OnSelection)` | Callback when selection changes | +| `getSelectedConversations()` | Get the list of currently selected conversations | +| `clearSelection()` | Clear all selections | +| `selectConversation(Conversation, SelectionMode)` | Programmatically select a conversation | + + + + +```kotlin +// Enable multi-select mode +conversations.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE) + +// Listen for selection changes +conversations.setOnSelect { selectedList -> + updateToolbar(selectedList.size) +} + +// Get selected items +val selected = conversations.getSelectedConversations() + +// Clear selection +conversations.clearSelection() +``` + + +```java +// Enable multi-select mode +conversations.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE); + +// Listen for selection changes +conversations.setOnSelect(selectedList -> { + updateToolbar(selectedList.size()); +}); + +// Get selected items +List selected = conversations.getSelectedConversations(); + +// Clear selection +conversations.clearSelection(); +``` + + + +## Global Events + +Global events are fired by the UI Kit when actions happen anywhere in the app. Register listeners using the static listener registration methods on each event class (`addListener`, `addGroupListener`, or `addUserListener` depending on the class). + +| Event Class | Fires When | +|---|---| +| `CometChatConversationEvents` | Conversation is deleted or updated | +| `CometChatMessageEvents` | Messages are sent, edited, deleted, or reacted to | +| `CometChatGroupEvents` | Groups are created, updated, members added/removed | +| `CometChatUserEvents` | Users are blocked/unblocked | +| `CometChatUIEvents` | UI-level events like opening chat, showing dialogs | +| `CometChatCallEvents` | Calls are initiated, accepted, rejected, or ended | + +Each listener is registered with a unique `String` tag so it can be removed later. + +### Component-Level vs Global Events + +- Component-level callbacks (e.g., `setOnItemClick`) are set on a specific View instance and only fire for that component. +- Global events (e.g., `CometChatMessageEvents.addListener`) are static and fire regardless of which component triggered the action. Use them for cross-component coordination. + + + +```kotlin +// Register a global message event listener +CometChatMessageEvents.addListener("unique-listener-id", + object : CometChatMessageEvents() { + override fun ccMessageSent(baseMessage: BaseMessage, status: Int) { + // Handle sent message across the app + } + + override fun onMessageDeleted(message: BaseMessage) { + // Handle deleted message + } + } +) + +// Remove the listener when done +CometChatMessageEvents.removeListener("unique-listener-id") +``` + + +```java +// Register a global message event listener +CometChatMessageEvents.addListener("unique-listener-id", + new CometChatMessageEvents() { + @Override + public void ccMessageSent(BaseMessage baseMessage, int status) { + // Handle sent message across the app + } + + @Override + public void onMessageDeleted(BaseMessage message) { + // Handle deleted message + } + } +); + +// Remove the listener when done +CometChatMessageEvents.removeListener("unique-listener-id"); +``` + + + +## Related + +- [Events Reference](/ui-kit/android/events) — Full list of all event classes and their methods. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-menu-options.mdx b/ui-kit/android/customization-menu-options.mdx new file mode 100644 index 000000000..c82df83c6 --- /dev/null +++ b/ui-kit/android/customization-menu-options.mdx @@ -0,0 +1,179 @@ +--- +title: "Menu & Options" +description: "Add, replace, or extend context menu actions and composer attachment options on components." +--- + +Components provide context menus (e.g., long-press on a conversation) and the message composer provides attachment and AI action options. You can customize all of these at the component level or globally via the DataSource framework. + +## Component-Level Options + +### setOptions vs addOptions + +| Method | Behavior | +|---|---| +| `setOptions(Function2>)` | Replaces all default options with your custom list | +| `addOptions(Function2>)` | Appends your custom options to the existing defaults | + +Use `addOptions` when you want to keep the default actions (like "Delete") and add your own. Use `setOptions` when you want full control over the menu. + +### Example: Adding a Custom Option + + + +```kotlin +conversations.addOptions { context, conversation -> + listOf( + CometChatPopupMenu.MenuItem( + id = "pin", + name = "Pin Conversation", + startIcon = ContextCompat.getDrawable(context, R.drawable.ic_pin), + endIcon = null, + onClick = { + pinConversation(conversation) + } + ) + ) +} +``` + + +```java +conversations.addOptions((context, conversation) -> { + List items = new ArrayList<>(); + items.add(new CometChatPopupMenu.MenuItem( + "pin", + "Pin Conversation", + ContextCompat.getDrawable(context, R.drawable.ic_pin), + null, + () -> pinConversation(conversation) + )); + return items; +}); +``` + + + +### Example: Replacing All Options + + + +```kotlin +conversations.setOptions { context, conversation -> + listOf( + CometChatPopupMenu.MenuItem( + id = "archive", + name = "Archive", + startIcon = ContextCompat.getDrawable(context, R.drawable.ic_archive), + endIcon = null, + onClick = { archiveConversation(conversation) } + ), + CometChatPopupMenu.MenuItem( + id = "mute", + name = "Mute", + startIcon = ContextCompat.getDrawable(context, R.drawable.ic_mute), + endIcon = null, + onClick = { muteConversation(conversation) } + ) + ) +} +``` + + +```java +conversations.setOptions((context, conversation) -> { + List items = new ArrayList<>(); + items.add(new CometChatPopupMenu.MenuItem("archive", "Archive", + ContextCompat.getDrawable(context, R.drawable.ic_archive), null, + () -> archiveConversation(conversation))); + items.add(new CometChatPopupMenu.MenuItem("mute", "Mute", + ContextCompat.getDrawable(context, R.drawable.ic_mute), null, + () -> muteConversation(conversation))); + return items; +}); +``` + + + + +## DataSource Message Options + +For message-level options (the actions that appear on message bubbles), use the `DataSource` framework. Override these methods in a `DataSourceDecorator`: + +### Message Option Methods + +| Method | Description | +|---|---| +| `getTextMessageOptions(Context, BaseMessage, Group)` | Options for text messages | +| `getImageMessageOptions(Context, BaseMessage, Group)` | Options for image messages | +| `getVideoMessageOptions(Context, BaseMessage, Group)` | Options for video messages | +| `getAudioMessageOptions(Context, BaseMessage, Group)` | Options for audio messages | +| `getFileMessageOptions(Context, BaseMessage, Group)` | Options for file messages | +| `getCommonOptions(Context, BaseMessage, Group)` | Options common to all message types | +| `getMessageOptions(Context, BaseMessage, Group)` | All options for a message (combines type-specific and common) | + +### Composer Action Methods + +| Method | Description | +|---|---| +| `getAttachmentOptions(Context, User, Group)` | Attachment options in the composer (camera, gallery, file, etc.) | +| `getAIOptions(Context, User, Group)` | AI action options in the composer | + +## Extending Options via DataSourceDecorator + +Use a `DataSourceDecorator` to add custom options globally without replacing the defaults: + + + +```kotlin +class CustomOptionsDataSource(dataSource: DataSource) : DataSourceDecorator(dataSource) { + + override fun getTextMessageOptions( + context: Context, + baseMessage: BaseMessage, + group: Group? + ): List { + val options = super.getTextMessageOptions(context, baseMessage, group).toMutableList() + options.add(CometChatMessageOption( + id = "translate", + title = "Translate", + icon = R.drawable.ic_translate, + onClick = { translateMessage(baseMessage) } + )) + return options + } +} + +// Register globally +ChatConfigurator.enable { dataSource -> CustomOptionsDataSource(dataSource) } +``` + + +```java +public class CustomOptionsDataSource extends DataSourceDecorator { + public CustomOptionsDataSource(DataSource dataSource) { + super(dataSource); + } + + @Override + public List getTextMessageOptions( + Context context, BaseMessage baseMessage, Group group) { + List options = + new ArrayList<>(super.getTextMessageOptions(context, baseMessage, group)); + options.add(new CometChatMessageOption( + "translate", "Translate", R.drawable.ic_translate, + () -> translateMessage(baseMessage) + )); + return options; + } +} + +// Register globally +ChatConfigurator.enable(dataSource -> new CustomOptionsDataSource(dataSource)); +``` + + + +## Related + +- [DataSource & ChatConfigurator](/ui-kit/android/customization-datasource) — Full DataSource decorator framework reference. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-overview.mdx b/ui-kit/android/customization-overview.mdx new file mode 100644 index 000000000..20947f6ae --- /dev/null +++ b/ui-kit/android/customization-overview.mdx @@ -0,0 +1,106 @@ +--- +title: "Customization Overview" +description: "Understand the View + ViewModel + Adapter architecture and discover all customization entry points in the CometChat Android UI Kit." +--- + +Every component in the Android UI Kit follows a three-layer architecture. Understanding these layers is the key to unlocking deep customization without rebuilding components from scratch. + +## Architecture + +Each component is composed of three collaborating classes: + +| Layer | Role | Example Class | +|---|---|---| +| View | Renders the UI, handles user interaction, and exposes setter methods for customization. | `CometChatConversations` | +| ViewModel | Manages data fetching, state, and business logic via `LiveData`. | `ConversationsViewModel` | +| Adapter | Binds data to `RecyclerView` items and controls how each list row is rendered. | `ConversationsAdapter` | + +```mermaid +graph LR + V["CometChatConversations\n(View Layer)"] -->|getViewModel()| VM["ConversationsViewModel\n(ViewModel Layer)"] + V -->|getConversationsAdapter()| A["ConversationsAdapter\n(Adapter Layer)"] + V -->|getRecyclerView()| RV["RecyclerView"] + V -->|getBinding()| B["ViewBinding"] + VM -->|LiveData| V + A -->|ViewHolder| RV +``` + +## Accessing Internal Layers + +The View layer provides accessor methods to reach the other layers: + +| Method | Returns | Purpose | +|---|---|---| +| `getViewModel()` | `ConversationsViewModel` | Access the ViewModel to observe `LiveData`, call mutation methods, or configure request builders. | +| `getConversationsAdapter()` | `ConversationsAdapter` | Access the Adapter to manipulate list data or set view slots directly on the adapter. | +| `getRecyclerView()` | `RecyclerView` | Access the underlying `RecyclerView` for scroll listeners, layout manager changes, or item decorations. | +| `getBinding()` | `CometchatConversationsListViewBinding` | Access the ViewBinding for direct manipulation of the component's internal views. | + + + + +```kotlin +val conversations = CometChatConversations(context) + +// Access the ViewModel +val viewModel = conversations.getViewModel() + +// Access the Adapter +val adapter = conversations.getConversationsAdapter() + +// Access the RecyclerView +val recyclerView = conversations.getRecyclerView() +``` + + +```java +CometChatConversations conversations = new CometChatConversations(context); + +// Access the ViewModel +ConversationsViewModel viewModel = conversations.getViewModel(); + +// Access the Adapter +ConversationsAdapter adapter = conversations.getConversationsAdapter(); + +// Access the RecyclerView +RecyclerView recyclerView = conversations.getRecyclerView(); +``` + + + +## Customization Categories + +The UI Kit provides eight categories of customization entry points. Each category has a dedicated guide: + + + + Replace specific regions of a component's UI (leading view, title, subtitle, trailing view) using the ViewHolderListener pattern. + + + Customize visual appearance using XML theme attributes or programmatic setter methods on the View layer. + + + Configure data fetching with RequestBuilders, observe LiveData, and call mutation methods on the ViewModel. + + + Access or replace the RecyclerView Adapter to control how list items are rendered and manage list data. + + + Handle click events, selection mode, and global UI Kit events with component-level and static event listeners. + + + Replace or restyle the default empty, error, and loading state views with custom layouts. + + + Create custom text processors for hashtags, mentions, links, or any pattern using the CometChatTextFormatter API. + + + Add, replace, or extend context menu actions and composer attachment options on components. + + + +For global-level customization that spans across all message types and components, see the [DataSource & ChatConfigurator](/ui-kit/android/customization-datasource) guide. + +## What's Next + +If you're new to customization, start with [View Slots](/ui-kit/android/customization-view-slots) for quick UI changes, or [Styles](/ui-kit/android/customization-styles) to match your brand. For advanced use cases like custom message types or global behavior changes, head to [DataSource & ChatConfigurator](/ui-kit/android/customization-datasource). diff --git a/ui-kit/android/customization-state-views.mdx b/ui-kit/android/customization-state-views.mdx new file mode 100644 index 000000000..c3ad4c744 --- /dev/null +++ b/ui-kit/android/customization-state-views.mdx @@ -0,0 +1,145 @@ +--- +title: "State Views" +description: "Replace or restyle the default empty, error, and loading state views with custom layouts." +--- + +Components display state views when the list is empty, an error occurs, or data is loading. You can replace these with custom layouts or restyle the default ones. + +## Replacing State Views + +Each state view setter accepts an Android layout resource ID (`@LayoutRes int`). The component inflates the layout when the corresponding state is triggered. + +| Setter | State | +|---|---| +| `setEmptyView(@LayoutRes int)` | No data to display | +| `setErrorView(@LayoutRes int)` | An error occurred during data fetching | +| `setLoadingView(@LayoutRes int)` | Data is being fetched | + +## Example: Custom Empty State + +Create a custom layout: + +```xml + + + + + + + + + +``` + +Set it on the component: + + + +```kotlin +conversations.setEmptyView(R.layout.custom_empty_state) +``` + + +```java +conversations.setEmptyView(R.layout.custom_empty_state); +``` + + + +## State Visibility Controls + +Hide or show specific state views entirely: + +| Method | Description | +|---|---| +| `setEmptyStateVisibility(int)` | Show or hide the empty state (`View.VISIBLE` or `View.GONE`) | +| `setErrorStateVisibility(int)` | Show or hide the error state | +| `setLoadingStateVisibility(int)` | Show or hide the loading state | + + + +```kotlin +// Hide the error state entirely +conversations.setErrorStateVisibility(View.GONE) + +// Hide the loading state (useful if you have your own loading indicator) +conversations.setLoadingStateVisibility(View.GONE) +``` + + +```java +// Hide the error state entirely +conversations.setErrorStateVisibility(View.GONE); + +// Hide the loading state +conversations.setLoadingStateVisibility(View.GONE); +``` + + + +## Restyling Default State Views + +If you want to keep the default state layout but change its appearance, use the text customization setters: + +### Empty State + +| Method | Description | +|---|---| +| `setEmptyStateTitleTextColor(@ColorInt int)` | Title text color | +| `setEmptyStateSubtitleTextColor(@ColorInt int)` | Subtitle text color | +| `setEmptyStateTextTitleAppearance(@StyleRes int)` | Title text appearance (font, size, style) | +| `setEmptyStateTextSubtitleAppearance(@StyleRes int)` | Subtitle text appearance | + +### Error State + +| Method | Description | +|---|---| +| `setErrorStateTitleTextColor(@ColorInt int)` | Title text color | +| `setErrorStateSubtitleTextColor(@ColorInt int)` | Subtitle text color | +| `setErrorStateTextTitleAppearance(@StyleRes int)` | Title text appearance | +| `setErrorStateTextSubtitleAppearance(@StyleRes int)` | Subtitle text appearance | + + + +```kotlin +// Restyle the default empty state +conversations.setEmptyStateTitleTextColor(Color.parseColor("#1A1A1A")) +conversations.setEmptyStateSubtitleTextColor(Color.parseColor("#808080")) +conversations.setEmptyStateTextTitleAppearance(R.style.TextAppearance_Heading) +``` + + +```java +// Restyle the default empty state +conversations.setEmptyStateTitleTextColor(Color.parseColor("#1A1A1A")); +conversations.setEmptyStateSubtitleTextColor(Color.parseColor("#808080")); +conversations.setEmptyStateTextTitleAppearance(R.style.TextAppearance_Heading); +``` + + + +## Related + +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-styles.mdx b/ui-kit/android/customization-styles.mdx new file mode 100644 index 000000000..fa2b64bab --- /dev/null +++ b/ui-kit/android/customization-styles.mdx @@ -0,0 +1,160 @@ +--- +title: "Styles" +description: "Customize component appearance using XML theme attributes or programmatic setter methods to match your app's brand." +--- + +The UI Kit supports two approaches to styling: XML theme attributes for declarative, app-wide theming, and programmatic setters for runtime customization. + + +Programmatic setters take precedence over XML theme attributes when both are applied to the same property. + + +## XML Theme Hierarchy + +The theming system follows a three-level hierarchy: + +1. Your `AppTheme` extends `CometChatTheme.DayNight` (theme-level colors and fonts) +2. Component styles extend parent styles (e.g., `cometchatConversationsStyle`) +3. Sub-component styles are nested within component styles (e.g., avatar style within conversations) + +```xml + + + + + + + + +``` + +## Font Customization + +Override fonts at the theme level using these attributes: + +| Attribute | Usage | +|---|---| +| `cometchatFontBold` | Headings, titles, and emphasized text | +| `cometchatFontMedium` | Subtitles and secondary headings | +| `cometchatFontRegular` | Body text, descriptions, and input fields | + + +## Programmatic Styling with CometChatTheme + +The `CometChatTheme` class provides static setter/getter methods for runtime color and typography token overrides: + +### Color Tokens + +| Method | Description | +|---|---| +| `setPrimaryColor(int)` | Primary brand color used for buttons, links, and highlights | +| `setErrorColor(int)` | Error state color | +| `setSuccessColor(int)` | Success state color | +| `setWarningColor(int)` | Warning state color | +| `setInfoColor(int)` | Informational state color | +| `setBackgroundColor1(int)` – `setBackgroundColor4(int)` | Background color levels | +| `setTextColorPrimary(int)` | Primary text color | +| `setTextColorSecondary(int)` | Secondary text color | +| `setTextColorTertiary(int)` | Tertiary text color | +| `setTextColorDisabled(int)` | Disabled text color | +| `setTextColorWhite(int)` | White text color | +| `setTextColorHighlight(int)` | Highlighted text color | + +### Icon Tints + +| Method | Description | +|---|---| +| `setIconTintPrimary(int)` | Primary icon tint | +| `setIconTintSecondary(int)` | Secondary icon tint | +| `setIconTintTertiary(int)` | Tertiary icon tint | +| `setIconTintWhite(int)` | White icon tint | +| `setIconTintHighlight(int)` | Highlighted icon tint | + +### Button Colors + +| Method | Description | +|---|---| +| `setPrimaryButtonBackgroundColor(int)` | Primary button background | +| `setPrimaryButtonTextColor(int)` | Primary button text | +| `setSecondaryButtonBackgroundColor(int)` | Secondary button background | +| `setSecondaryButtonTextColor(int)` | Secondary button text | + + + +```kotlin +// Override theme colors at runtime +CometChatTheme.setPrimaryColor(Color.parseColor("#6851D6")) +CometChatTheme.setErrorColor(Color.parseColor("#FF3B30")) +CometChatTheme.setTextColorPrimary(Color.parseColor("#1A1A1A")) +CometChatTheme.setTextColorSecondary(Color.parseColor("#808080")) +``` + + +```java +// Override theme colors at runtime +CometChatTheme.setPrimaryColor(Color.parseColor("#6851D6")); +CometChatTheme.setErrorColor(Color.parseColor("#FF3B30")); +CometChatTheme.setTextColorPrimary(Color.parseColor("#1A1A1A")); +CometChatTheme.setTextColorSecondary(Color.parseColor("#808080")); +``` + + + +## Component Style Setters + +Each component exposes setter methods for its own style and sub-component styles. Using `CometChatConversations` as an example: + +| Method | Applies To | +|---|---| +| `setStyle(@StyleRes int)` | The component's own style | +| `setAvatarStyle(@StyleRes int)` | Avatar sub-component | +| `setBadgeStyle(@StyleRes int)` | Unread badge sub-component | +| `setReceiptStyle(@StyleRes int)` | Message receipt icons | +| `setTypingIndicatorStyle(@StyleRes int)` | Typing indicator | +| `setMentionsStyle(@StyleRes int)` | Mentions formatting | +| `setStatusIndicatorStyle(@StyleRes int)` | Online/offline status indicator | +| `setDateStyle(@StyleRes int)` | Date/time label | + + + +```kotlin +val conversations = CometChatConversations(context) +conversations.setStyle(R.style.CustomConversationsStyle) +conversations.setAvatarStyle(R.style.CustomAvatarStyle) +conversations.setBadgeStyle(R.style.CustomBadgeStyle) +``` + + +```java +CometChatConversations conversations = new CometChatConversations(context); +conversations.setStyle(R.style.CustomConversationsStyle); +conversations.setAvatarStyle(R.style.CustomAvatarStyle); +conversations.setBadgeStyle(R.style.CustomBadgeStyle); +``` + + + +## Related + +- [Theming Introduction](/ui-kit/android/theme-introduction) — Full theming reference for the UI Kit. +- [Component Styling](/ui-kit/android/component-styling) — Detailed per-component style attribute reference. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-text-formatters.mdx b/ui-kit/android/customization-text-formatters.mdx new file mode 100644 index 000000000..b812a7287 --- /dev/null +++ b/ui-kit/android/customization-text-formatters.mdx @@ -0,0 +1,229 @@ +--- +title: "Text Formatters" +description: "Create custom text processors for hashtags, mentions, links, or any pattern using the CometChatTextFormatter API." +--- + +Text formatters let you process message text with tracking characters, suggestion lists, and spannable transformations. Use them to add hashtag detection, custom mentions, link previews, or any text pattern processing. + +## CometChatTextFormatter + +The `CometChatTextFormatter` abstract class is the base for all formatters. Its constructor takes a `char trackingCharacter` that triggers the formatter when typed in the composer (e.g., `@` for mentions, `#` for hashtags). + +### Key Override Methods + +| Method | Purpose | +|---|---| +| `search(Context, String)` | Called when the user types after the tracking character. Use this to fetch and display suggestions. | +| `onScrollToBottom()` | Called when the user scrolls to the bottom of the suggestion list. Use for pagination. | +| `prepareLeftMessageBubbleSpan(Context, BaseMessage, SpannableStringBuilder)` | Apply spans to text in received (left) message bubbles. | +| `prepareRightMessageBubbleSpan(Context, BaseMessage, SpannableStringBuilder)` | Apply spans to text in sent (right) message bubbles. | +| `prepareComposerSpan(Context, BaseMessage, SpannableStringBuilder)` | Apply spans to text in the message composer. | +| `prepareConversationSpan(Context, BaseMessage, SpannableStringBuilder)` | Apply spans to the last message preview in the conversations list. | + +### Pre-Send Hook + +Override `handlePreMessageSend(Context, BaseMessage)` to modify a message before it's sent. This is useful for attaching metadata, transforming text, or adding custom data to the message object. + +## Suggestion System + +The formatter provides a built-in suggestion dropdown: + +| Method | Description | +|---|---| +| `setSuggestionItemList(List)` | Set the list of suggestions to display | +| `setShowLoadingIndicator(boolean)` | Show/hide a loading spinner in the suggestion dropdown | +| `setDisableSuggestions(boolean)` | Disable the suggestion dropdown entirely | +| `onItemClick(Context, SuggestionItem, User, Group)` | Called when the user selects a suggestion item | + + +## Example: Custom Hashtag Formatter + + + +```kotlin +class HashtagFormatter : CometChatTextFormatter('#') { + + override fun search(context: Context, queryString: String?) { + // Fetch hashtag suggestions based on query + val suggestions = fetchHashtags(queryString) + setSuggestionItemList(suggestions) + } + + override fun onScrollToBottom() { + // Load more suggestions + } + + override fun prepareLeftMessageBubbleSpan( + context: Context, + baseMessage: BaseMessage, + spannable: SpannableStringBuilder + ): SpannableStringBuilder? { + // Apply blue color to #hashtags in received messages + applyHashtagSpans(spannable, context) + return spannable + } + + override fun prepareRightMessageBubbleSpan( + context: Context, + baseMessage: BaseMessage, + spannable: SpannableStringBuilder + ): SpannableStringBuilder? { + // Apply blue color to #hashtags in sent messages + applyHashtagSpans(spannable, context) + return spannable + } + + override fun prepareComposerSpan( + context: Context, + baseMessage: BaseMessage, + spannable: SpannableStringBuilder + ): SpannableStringBuilder? { + applyHashtagSpans(spannable, context) + return spannable + } + + override fun prepareConversationSpan( + context: Context, + baseMessage: BaseMessage, + spannable: SpannableStringBuilder + ): SpannableStringBuilder? { + applyHashtagSpans(spannable, context) + return spannable + } +} +``` + + +```java +public class HashtagFormatter extends CometChatTextFormatter { + + public HashtagFormatter() { + super('#'); + } + + @Override + public void search(@Nonnull Context context, @Nullable String queryString) { + // Fetch hashtag suggestions based on query + List suggestions = fetchHashtags(queryString); + setSuggestionItemList(suggestions); + } + + @Override + public void onScrollToBottom() { + // Load more suggestions + } + + @Nullable + @Override + public SpannableStringBuilder prepareLeftMessageBubbleSpan( + @Nonnull Context context, + @Nonnull BaseMessage baseMessage, + SpannableStringBuilder spannable) { + applyHashtagSpans(spannable, context); + return spannable; + } + + @Nullable + @Override + public SpannableStringBuilder prepareRightMessageBubbleSpan( + @Nonnull Context context, + @Nonnull BaseMessage baseMessage, + SpannableStringBuilder spannable) { + applyHashtagSpans(spannable, context); + return spannable; + } + + @Nullable + @Override + public SpannableStringBuilder prepareComposerSpan( + @Nonnull Context context, + @Nonnull BaseMessage baseMessage, + SpannableStringBuilder spannable) { + applyHashtagSpans(spannable, context); + return spannable; + } + + @Nullable + @Override + public SpannableStringBuilder prepareConversationSpan( + @Nonnull Context context, + @Nonnull BaseMessage baseMessage, + SpannableStringBuilder spannable) { + applyHashtagSpans(spannable, context); + return spannable; + } +} +``` + + + +## Registering Formatters + +Register formatters on a component using `setTextFormatters`: + + + +```kotlin +val hashtagFormatter = HashtagFormatter() +conversations.setTextFormatters(listOf(hashtagFormatter)) +``` + + +```java +HashtagFormatter hashtagFormatter = new HashtagFormatter(); +conversations.setTextFormatters(Arrays.asList(hashtagFormatter)); +``` + + + +## Built-in Formatter: CometChatMentionsFormatter + +The UI Kit includes `CometChatMentionsFormatter` as a built-in formatter that handles `@mention` detection, user suggestion lists, and spannable highlighting. It serves as a reference implementation for building custom formatters. + +See the [Mentions Formatter Guide](/ui-kit/android/mentions-formatter-guide) for details. + +## Global Configuration via DataSource + +Formatters can also be configured globally using the `DataSource` framework. Override `getTextFormatters` in a `DataSourceDecorator` to add formatters that apply across all components: + + + +```kotlin +class CustomDataSource(dataSource: DataSource) : DataSourceDecorator(dataSource) { + override fun getTextFormatters(context: Context, additionParameter: AdditionParameter): List { + val formatters = super.getTextFormatters(context, additionParameter).toMutableList() + formatters.add(HashtagFormatter()) + return formatters + } +} + +// Register globally +ChatConfigurator.enable { dataSource -> CustomDataSource(dataSource) } +``` + + +```java +public class CustomDataSource extends DataSourceDecorator { + public CustomDataSource(DataSource dataSource) { + super(dataSource); + } + + @Override + public List getTextFormatters(Context context, AdditionParameter additionParameter) { + List formatters = new ArrayList<>(super.getTextFormatters(context, additionParameter)); + formatters.add(new HashtagFormatter()); + return formatters; + } +} + +// Register globally +ChatConfigurator.enable(dataSource -> new CustomDataSource(dataSource)); +``` + + + +## Related + +- [DataSource & ChatConfigurator](/ui-kit/android/customization-datasource) — Learn the full DataSource decorator framework. +- [Mentions Formatter Guide](/ui-kit/android/mentions-formatter-guide) — Built-in mentions formatter reference. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-view-slots.mdx b/ui-kit/android/customization-view-slots.mdx new file mode 100644 index 000000000..cec78b5e1 --- /dev/null +++ b/ui-kit/android/customization-view-slots.mdx @@ -0,0 +1,202 @@ +--- +title: "View Slots" +description: "Replace specific regions of a component's UI using the ViewHolderListener pattern without rebuilding the entire component." +--- + +View Slots let you swap out specific parts of a component's list item — the avatar area, title, subtitle, trailing section, or the entire row — while keeping the rest of the component's behavior intact. + +## The ViewHolderListener Pattern + +Every list-based component defines a `ViewHolderListener` abstract class (e.g., `ConversationsViewHolderListener`) with two callbacks: + +| Callback | Purpose | +|---|---| +| `createView(Context context, CometchatConversationsListItemsBinding listItem)` | Return a `View` that will be placed in the slot. Called once when the ViewHolder is created. | +| `bindView(Context context, View createdView, Conversation conversation, RecyclerView.ViewHolder holder, List conversationList, int position)` | Bind data to your custom view. Called every time the item is bound (scroll, update). `createdView` is the view returned by `createView`, and the full conversation list and holder are provided for context. | + +## Available View Slots + +| Setter | Region | Description | +|---|---|---| +| `setLeadingView` | Left section | Replaces the avatar / leading area of each list item. | +| `setTitleView` | Title text | Replaces the name / title text area. | +| `setSubtitleView` | Subtitle text | Replaces the last message preview area. | +| `setTrailingView` | Right section | Replaces the timestamp / badge / trailing area. | +| `setItemView` | Entire row | Replaces the entire list item layout. | + +## Slot-Level vs Full Item Replacement + +Use slot-level setters (`setLeadingView`, `setTitleView`, `setSubtitleView`, `setTrailingView`) when you want to customize one region while keeping the default layout for everything else. Use `setItemView` when you need complete control over the entire row layout. + + +When you use `setItemView`, all other slot setters are ignored since the entire row is replaced. + + +## Example: Custom Leading View + +Replace the default avatar with a custom view that shows the first letter of the conversation name in a colored circle: + + + + +```kotlin +conversations.setLeadingView(object : ConversationsViewHolderListener() { + override fun createView( + context: Context, + listItem: CometchatConversationsListItemsBinding + ): View { + val textView = TextView(context).apply { + layoutParams = ViewGroup.LayoutParams(48.dp, 48.dp) + gravity = Gravity.CENTER + textSize = 18f + setTextColor(Color.WHITE) + } + return textView + } + + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + val textView = createdView as TextView + val name = conversation.conversationWith?.name ?: "" + textView.text = name.firstOrNull()?.uppercase() ?: "?" + textView.background = GradientDrawable().apply { + shape = GradientDrawable.OVAL + setColor(Color.parseColor("#6851D6")) + } + } +}) +``` + + +```java +conversations.setLeadingView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + TextView textView = new TextView(context); + textView.setLayoutParams(new ViewGroup.LayoutParams(48, 48)); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(18f); + textView.setTextColor(Color.WHITE); + return textView; + } + + @Override + public void bindView(Context context, View createdView, Conversation conversation, + RecyclerView.ViewHolder holder, List conversationList, int position) { + TextView textView = (TextView) createdView; + String name = conversation.getConversationWith() != null + ? conversation.getConversationWith().getName() : ""; + String initial = name.isEmpty() ? "?" : String.valueOf(name.charAt(0)).toUpperCase(); + textView.setText(initial); + GradientDrawable bg = new GradientDrawable(); + bg.setShape(GradientDrawable.OVAL); + bg.setColor(Color.parseColor("#6851D6")); + textView.setBackground(bg); + } +}); +``` + + + +## Example: Custom Subtitle View + +Show a "typing..." indicator or a custom last message format in the subtitle area: + + + +```kotlin +conversations.setSubtitleView(object : ConversationsViewHolderListener() { + override fun createView( + context: Context, + listItem: CometchatConversationsListItemsBinding + ): View { + return TextView(context).apply { + maxLines = 1 + ellipsize = TextUtils.TruncateAt.END + } + } + + override fun bindView( + context: Context, + createdView: View, + conversation: Conversation, + holder: RecyclerView.ViewHolder, + conversationList: List, + position: Int + ) { + val textView = createdView as TextView + val lastMessage = conversation.lastMessage + textView.text = when (lastMessage) { + is TextMessage -> lastMessage.text + is MediaMessage -> "📎 ${lastMessage.attachment?.fileExtension ?: "Media"}" + else -> "New conversation" + } + } +}) +``` + + +```java +conversations.setSubtitleView(new ConversationsViewHolderListener() { + @Override + public View createView(Context context, CometchatConversationsListItemsBinding listItem) { + TextView textView = new TextView(context); + textView.setMaxLines(1); + textView.setEllipsize(TextUtils.TruncateAt.END); + return textView; + } + + @Override + public void bindView(Context context, View createdView, Conversation conversation, + RecyclerView.ViewHolder holder, List conversationList, int position) { + TextView textView = (TextView) createdView; + BaseMessage lastMessage = conversation.getLastMessage(); + String subtitle; + if (lastMessage instanceof TextMessage) { + subtitle = ((TextMessage) lastMessage).getText(); + } else if (lastMessage instanceof MediaMessage) { + subtitle = "Media"; + } else { + subtitle = "New conversation"; + } + textView.setText(subtitle); + } +}); +``` + + + +## Toolbar Overflow Menu + +Use `setOverflowMenu(View)` to inject a custom view into the component's toolbar area. This is separate from the list item view slots — it customizes the toolbar, not individual rows. + + + +```kotlin +val menuButton = ImageButton(context).apply { + setImageResource(R.drawable.ic_filter) + setOnClickListener { /* show filter dialog */ } +} +conversations.setOverflowMenu(menuButton) +``` + + +```java +ImageButton menuButton = new ImageButton(context); +menuButton.setImageResource(R.drawable.ic_filter); +menuButton.setOnClickListener(v -> { /* show filter dialog */ }); +conversations.setOverflowMenu(menuButton); +``` + + + +## Related + +- [Adapter Customization](/ui-kit/android/customization-adapters) — View slot setters are also available directly on the Adapter. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/customization-viewmodel-data.mdx b/ui-kit/android/customization-viewmodel-data.mdx new file mode 100644 index 000000000..7f8e682e9 --- /dev/null +++ b/ui-kit/android/customization-viewmodel-data.mdx @@ -0,0 +1,205 @@ +--- +title: "ViewModel & Data" +description: "Access and configure the ViewModel layer to customize data fetching, filtering, and state management." +--- + +Each component's ViewModel manages data fetching, state transitions, and business logic via `LiveData`. You can access it to configure request parameters, observe state changes, or manipulate the data list directly. + +## Accessing the ViewModel + + + +```kotlin +val conversations = CometChatConversations(context) +val viewModel: ConversationsViewModel = conversations.getViewModel() +``` + + +```java +CometChatConversations conversations = new CometChatConversations(context); +ConversationsViewModel viewModel = conversations.getViewModel(); +``` + + + +## Configuring Data Fetching with RequestBuilders + +Use `setConversationsRequestBuilder` to control what data the component fetches. The builder accepts SDK parameters like limits, tags, and filters. + + + +```kotlin +// Filter conversations by tags and limit to 20 results +val builder = ConversationsRequest.ConversationsRequestBuilder() + .setLimit(20) + .setTags(listOf("important", "pinned")) + .withTags(true) + +conversations.setConversationsRequestBuilder(builder) +``` + + +```java +// Filter conversations by tags and limit to 20 results +ConversationsRequest.ConversationsRequestBuilder builder = + new ConversationsRequest.ConversationsRequestBuilder() + .setLimit(20) + .setTags(Arrays.asList("important", "pinned")) + .withTags(true); + +conversations.setConversationsRequestBuilder(builder); +``` + + + + +Pass the builder object, not the result of `.build()`. The component calls `.build()` internally. + + +## LiveData Observables + +The ViewModel exposes `LiveData` observables you can observe for custom logic: + +| Observable | Type | Description | +|---|---|---| +| `getMutableConversationList()` | `MutableLiveData>` | The current list of conversations | +| `getStates()` | `MutableLiveData` | Component state (LOADING, LOADED, EMPTY, ERROR) | +| `insertAtTop()` | `MutableLiveData` | Emits the index when a new conversation is inserted at the top | +| `moveToTop()` | `MutableLiveData` | Emits the index when a conversation moves to the top | +| `updateConversation()` | `MutableLiveData` | Emits the index when a conversation is updated | +| `remove()` | `MutableLiveData` | Emits the index when a conversation is removed | +| `progressState()` | `MutableLiveData` | Tracks delete operation progress | +| `playSound()` | `MutableLiveData` | Triggers when a new message sound should play | +| `getCometChatException()` | `MutableLiveData` | Emits errors from the SDK | + + + + +```kotlin +val viewModel = conversations.getViewModel() + +// Observe state changes +viewModel.getStates().observe(lifecycleOwner) { state -> + when (state) { + UIKitConstants.States.LOADING -> { /* show custom loading */ } + UIKitConstants.States.LOADED -> { /* data ready */ } + UIKitConstants.States.EMPTY -> { /* no conversations */ } + UIKitConstants.States.ERROR -> { /* handle error */ } + } +} + +// Observe the conversation list +viewModel.getMutableConversationList().observe(lifecycleOwner) { list -> + // React to list changes +} +``` + + +```java +ConversationsViewModel viewModel = conversations.getViewModel(); + +// Observe state changes +viewModel.getStates().observe(lifecycleOwner, state -> { + if (state == UIKitConstants.States.LOADING) { + // show custom loading + } else if (state == UIKitConstants.States.LOADED) { + // data ready + } +}); + +// Observe the conversation list +viewModel.getMutableConversationList().observe(lifecycleOwner, list -> { + // React to list changes +}); +``` + + + +## Mutation Methods + +The ViewModel provides methods to programmatically manipulate the data list: + +| Method | Description | +|---|---| +| `addList(List)` | Append a list of conversations | +| `remove(Conversation)` | Remove a specific conversation | +| `remove(int index)` | Remove a conversation by index | +| `update(Conversation, boolean)` | Update a conversation in the list | +| `refreshList()` | Clear and re-fetch from the server | +| `clear()` | Clear all conversations from the list | +| `fetchConversation()` | Fetch the next page of conversations | +| `deleteConversation(Conversation)` | Delete a conversation via the SDK | + + + +```kotlin +val viewModel = conversations.getViewModel() + +// Refresh the entire list +viewModel.refreshList() + +// Remove a specific conversation +viewModel.remove(conversation) + +// Clear all data +viewModel.clear() +``` + + +```java +ConversationsViewModel viewModel = conversations.getViewModel(); + +// Refresh the entire list +viewModel.refreshList(); + +// Remove a specific conversation +viewModel.remove(conversation); + +// Clear all data +viewModel.clear(); +``` + + + +## Lifecycle Callbacks + +Intercept data loading lifecycle events with these callbacks on the View: + +| Callback | Triggered When | +|---|---| +| `setOnLoad(OnLoad)` | Data has been successfully loaded | +| `setOnEmpty(OnEmpty)` | The data list is empty after loading | + + + +```kotlin +conversations.setOnLoad { list -> + // Called when conversations are loaded + Log.d("Conversations", "Loaded ${list.size} conversations") +} + +conversations.setOnEmpty { + // Called when no conversations exist + Log.d("Conversations", "No conversations found") +} +``` + + +```java +conversations.setOnLoad(list -> { + // Called when conversations are loaded + Log.d("Conversations", "Loaded " + list.size() + " conversations"); +}); + +conversations.setOnEmpty(() -> { + // Called when no conversations exist + Log.d("Conversations", "No conversations found"); +}); +``` + + + +## Related + +- [Adapter Customization](/ui-kit/android/customization-adapters) — Manipulate list data at the adapter level. +- [Customization Overview](/ui-kit/android/customization-overview) — See all customization categories. diff --git a/ui-kit/android/events.mdx b/ui-kit/android/events.mdx index 61c3696eb..215a47c72 100644 --- a/ui-kit/android/events.mdx +++ b/ui-kit/android/events.mdx @@ -1,23 +1,70 @@ --- title: "Events" +description: "Listen to UI Kit events for user actions, group changes, messages, and call lifecycle updates." --- -## Overview + -Events allow for a decoupled, flexible architecture where different parts of the application can interact without having to directly reference each other. This makes it easier to create complex, interactive experiences, as well as to extend and customize the functionality provided by the CometChat UI Kit. +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Conversation events | `ccConversationDeleted` | +| User events | `ccUserBlocked`, `ccUserUnblocked` | +| Group events | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnBanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` | +| Message events | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccLiveReaction` | +| Call events | `ccOutgoingCall`, `ccCallAccepted`, `ccCallRejected`, `ccCallEnded` | +| Purpose | Decoupled communication between UI Kit components — subscribe to events to react to changes without direct component references | -Both Components and Composite Components have the ability to emit events. These events are dispatched in response to certain changes or user interactions within the component. By emitting events, these components allow other parts of the application to react to changes or interactions, thus enabling dynamic and interactive behavior within the application. + + +Events enable a decoupled, flexible architecture in the CometChat UI Kit. Components and Composite Components emit events in response to user interactions or state changes, allowing other parts of your application to react without direct references between components. + +## When to use this + +- You need to update your UI when a user is blocked or unblocked. +- You need to respond to group actions such as member joins, kicks, bans, or ownership transfers. +- You need to track conversation deletions or updates in real time. +- You need to react to messages being sent, edited, deleted, or read. +- You need to handle call lifecycle events (outgoing, accepted, rejected, ended). +- You need to respond to UI-level events such as panel visibility changes or active chat changes. + +## Prerequisites + +- The `cometchat-chat-uikit-android` dependency added to your project. +- `CometChatUIKit.init()` called and completed successfully. +- A logged-in CometChat user (call `CometChatUIKit.login()` before registering listeners). + +## API reference ### User Events -`UserEvents` emit events when the logged-in user executes actions on another user. This class provides methods to add and remove listeners for user events, as well as methods to handle specific user actions such as blocking and unblocking users. +`CometChatUserEvents` emits events when the logged-in user executes actions on another user. This class provides methods to add and remove listeners for user events, as well as methods to handle specific user actions such as blocking and unblocking users. + +**Events:** -1. `ccUserBlocked`: Triggered when the logged-in user blocks another user. -2. `ccUserUnblocked`: Triggered when the logged-in user unblocks another user. +| Event | Description | +| ----- | ----------- | +| `ccUserBlocked` | Triggered when the logged-in user blocks another user. | +| `ccUserUnblocked` | Triggered when the logged-in user unblocks another user. | + +**Listener registration:** + +```kotlin lines +CometChatUserEvents.addUserListener(LISTENERS_TAG, object : CometChatUserEvents() { + override fun ccUserBlocked(user: User) { + // Perform action when user is blocked + } + + override fun ccUserUnblocked(user: User) { + // Perform action when user is unblocked + } +}) +``` + -```java +```java lines CometChatUserEvents.addUserListener(LISTENERS_TAG, new CometChatUserEvents() { @Override public void ccUserBlocked(User user) { @@ -30,46 +77,82 @@ CometChatUserEvents.addUserListener(LISTENERS_TAG, new CometChatUserEvents() { } }); ``` - + + +> **What this does:** Registers a listener on `CometChatUserEvents` using a unique `LISTENERS_TAG`. The `ccUserBlocked` callback fires when the logged-in user blocks another user, and `ccUserUnblocked` fires when the logged-in user unblocks another user. + +--- +### Group Events + +`CometChatGroupEvents` emits events when the logged-in user performs actions related to groups. This class provides methods to listen to various group-related events and handle them. + +**Events:** + +| Event | Description | +| ----- | ----------- | +| `ccGroupCreated` | Triggered when the logged-in user creates a group. | +| `ccGroupDeleted` | Triggered when the logged-in user deletes a group. | +| `ccGroupLeft` | Triggered when the logged-in user leaves a group. Provides the action message, the user who left, and the group. | +| `ccGroupMemberScopeChanged` | Triggered when the logged-in user changes the scope of another group member. Provides the action message, updated user, new scope, previous scope, and group. | +| `ccGroupMemberBanned` | Triggered when the logged-in user bans a group member from the group. Provides the action message, banned user, who banned them, and the group. | +| `ccGroupMemberKicked` | Triggered when the logged-in user kicks another group member from the group. Provides the action message, kicked user, who kicked them, and the group. | +| `ccGroupMemberUnBanned` | Triggered when the logged-in user unbans a user banned from the group. Provides the action message, unbanned user, who unbanned them, and the group. | +| `ccGroupMemberJoined` | Triggered when the logged-in user joins a group. Provides the joined user and the group. | +| `ccGroupMemberAdded` | Triggered when the logged-in user adds new members to the group. Provides action messages, added users, the group, and who added them. | +| `ccOwnershipChanged` | Triggered when the logged-in user transfers the ownership of their group to some other member. Provides the group and the new owner (as `GroupMember`). | + +**Listener registration:** + + -```kotlin -CometChatUserEvents.addUserListener(LISTENERS_TAG, object : CometChatUserEvents() { - override fun ccUserBlocked(user: User) { - // Perform action when user is blocked +```kotlin lines +CometChatGroupEvents.addGroupListener(LISTENERS_TAG, object : CometChatGroupEvents() { + override fun ccGroupCreated(group: Group) { + // Perform action when group is created } - override fun ccUserUnblocked(user: User) { - // Perform action when user is unblocked + override fun ccGroupDeleted(group: Group) { + // Perform action when group is deleted } -}) -``` - + override fun ccGroupLeft(actionMessage: Action, leftUser: User, leftGroup: Group) { + // Perform action when user leaves group + } - + override fun ccGroupMemberScopeChanged(actionMessage: Action, updatedUser: User, scopeChangedTo: String, scopeChangedFrom: String, group: Group) { + // Perform action when group member scope is changed + } -### Group Events + override fun ccGroupMemberBanned(actionMessage: Action, bannedUser: User, bannedBy: User, bannedFrom: Group) { + // Perform action when user is banned from group + } -`GroupEvents` Emits events when the logged-in user performs actions related to groups. This class provides methods to listen to various group-related events and handle them accordingly. + override fun ccGroupMemberKicked(actionMessage: Action, kickedUser: User, kickedBy: User, kickedFrom: Group) { + // Perform action when user is kicked from group + } -Following are all the group events + override fun ccGroupMemberUnBanned(actionMessage: Action, unbannedUser: User, unBannedBy: User, unBannedFrom: Group) { + // Perform action when user is unbanned from group + } -1. `ccGroupCreated`: Triggered when the logged-in user creates a group. -2. `ccGroupDeleted`: Triggered when the logged-in user deletes a group. -3. `ccGroupLeft`: Triggered when the logged-in user leaves a group. -4. `ccGroupMemberScopeChanged`: Triggered when the logged-in user changes the scope of another group member. -5. `ccGroupMemberBanned`: Triggered when the logged-in user bans a group member from the group. -6. `ccGroupMemberKicked`: Triggered when the logged-in user kicks another group member from the group. -7. `ccGroupMemberUnbanned`: Triggered when the logged-in user unbans a user banned from the group. -8. `ccGroupMemberJoined`: Triggered when the logged-in user joins a group. -9. `ccGroupMemberAdded`: Triggered when the logged-in user adds new members to the group. -10. `ccOwnershipChanged`: Triggered when the logged-in user transfers the ownership of their group to some other member. + override fun ccGroupMemberJoined(joinedUser: User, joinedGroup: Group) { + // Perform action when user joins group + } -To listen to group events + override fun ccGroupMemberAdded(actionMessages: List, usersAdded: List, userAddedIn: Group, addedBy: User) { + // Perform action when members are added to group + } -```typescript + override fun ccOwnershipChanged(group: Group, newOwner: GroupMember) { + // Perform action when group ownership is changed + } +}) +``` + + +```java lines CometChatGroupEvents.addGroupListener(LISTENERS_TAG, new CometChatGroupEvents() { @Override public void ccGroupCreated(Group group) { @@ -82,59 +165,82 @@ CometChatGroupEvents.addGroupListener(LISTENERS_TAG, new CometChatGroupEvents() } @Override - public void ccGroupLeft(Group group) { + public void ccGroupLeft(Action actionMessage, User leftUser, Group leftGroup) { // Perform action when user leaves group } @Override - public void ccGroupMemberScopeChanged(Group group, User user, String scope) { + public void ccGroupMemberScopeChanged(Action actionMessage, User updatedUser, String scopeChangedTo, String scopeChangedFrom, Group group) { // Perform action when group member scope is changed } @Override - public void ccGroupMemberBanned(Group group, User user, User bannedBy) { + public void ccGroupMemberBanned(Action actionMessage, User bannedUser, User bannedBy, Group bannedFrom) { // Perform action when user is banned from group } @Override - public void ccGroupMemberKicked(Group group, User kickedUser, User kickedBy) { + public void ccGroupMemberKicked(Action actionMessage, User kickedUser, User kickedBy, Group kickedFrom) { // Perform action when user is kicked from group } @Override - public void ccGroupMemberUnbanned(Group group, User user, User unbannedBy) { + public void ccGroupMemberUnBanned(Action actionMessage, User unbannedUser, User unBannedBy, Group unBannedFrom) { // Perform action when user is unbanned from group } @Override - public void ccGroupMemberJoined(Group group, User joinedUser) { + public void ccGroupMemberJoined(User joinedUser, Group joinedGroup) { // Perform action when user joins group } @Override - public void ccGroupMemberAdded(Group group, List addedMembers, User addedBy) { + public void ccGroupMemberAdded(List actionMessages, List usersAdded, Group userAddedIn, User addedBy) { // Perform action when members are added to group } @Override - public void ccOwnershipChanged(Group group, User newOwner, User oldOwner) { + public void ccOwnershipChanged(Group group, GroupMember newOwner) { // Perform action when group ownership is changed } }); ``` + + + +> **What this does:** Registers a listener on `CometChatGroupEvents` using a unique `LISTENERS_TAG`. Each callback fires when the logged-in user performs the corresponding group action — creating, deleting, leaving a group, or managing members (scope change, ban, kick, unban, join, add, ownership transfer). + +--- ### Conversation Events -The `ConversationEvents` component emits events when the logged-in user performs actions related to conversations. This allows for the UI to be updated accordingly. Below are the events emitted by the Conversation Component: +`CometChatConversationEvents` emits events when the logged-in user performs actions related to conversations. This allows the UI to be updated when conversations change. + +**Events:** -* `ccConversationDeleted`: Triggered when the logged-in user deletes a conversation. -* `ccUpdateConversation`: Triggered when there is an update in the conversation. +| Event | Description | +| ----- | ----------- | +| `ccConversationDeleted` | Triggered when the logged-in user deletes a conversation. | +| `ccUpdateConversation` | Triggered when there is an update in the conversation. | -To listen to conversation events and handle them in your application, you can use the following code snippets: +**Listener registration:** + +```kotlin lines +CometChatConversationEvents.addListener("LISTENERS_TAG", object : CometChatConversationEvents() { + override fun ccConversationDeleted(conversation: Conversation) { + // Perform action when conversation is deleted + } + + override fun ccUpdateConversation(conversation: Conversation) { + // Perform action when conversation is updated + } +}) +``` + -```java +```java lines CometChatConversationEvents.addListener("LISTENERS_TAG", new CometChatConversationEvents() { @Override public void ccConversationDeleted(Conversation conversation) { @@ -142,122 +248,144 @@ CometChatConversationEvents.addListener("LISTENERS_TAG", new CometChatConversati } @Override - public void ccUpdateConversation(Conversation conversation) { - // Perform action when conversation is updated - } + public void ccUpdateConversation(Conversation conversation) { + // Perform action when conversation is updated + } }); ``` - + - -```kotlin -CometChatConversationEvents.addListener("LISTENERS_TAG", object : CometChatConversationEvents() { - override fun ccConversationDeleted(conversation: Conversation) { - // Perform action when conversation is deleted - } -}) -``` - - +> **What this does:** Registers a listener on `CometChatConversationEvents` using a unique listener tag. The `ccConversationDeleted` callback fires when the logged-in user deletes a conversation, and `ccUpdateConversation` fires when a conversation is updated. - +--- ### Message Events -`MessageEvents` emits events when various actions are performed on messages within the application. These events facilitate updating the UI accordingly. Below are the events emitted by the MessageEvents component: +`CometChatMessageEvents` emits events when various actions are performed on messages within the application. These events facilitate updating the UI when messages change. -* `ccMessageSent`: Triggered whenever a loggedIn user sends any message. It can have two states: `inProgress` and `sent`. -* `ccMessageEdited`: Triggered whenever a loggedIn user edits any message from the list of messages. It can have two states: `inProgress` and `sent`. -* `ccMessageDeleted`: Triggered whenever a loggedIn user deletes any message from the list of messages. -* `ccMessageRead`: Triggered whenever a loggedIn user reads any message. -* `ccLiveReaction`: Triggered whenever a loggedIn user clicks on live reaction. -* `onFormMessageReceived`: Triggered when a form message is received. -* `onCardMessageReceived`: Triggered when a card message is received. -* `onCustomInteractiveMessageReceived`: Triggered when a custom interactive message is received. -* `onInteractionGoalCompleted`: Triggered when an interaction goal is completed. -* `onSchedulerMessageReceived`: Triggered when a scheduler message is received. +**Events:** -To listen to message events and handle them in your application, you can use the following code snippets: +| Event | Description | +| ----- | ----------- | +| `ccMessageSent` | Triggered whenever a logged-in user sends any message. It can have two states: `inProgress` and `sent`. | +| `ccMessageEdited` | Triggered whenever a logged-in user edits any message from the list of messages. It can have two states: `inProgress` and `sent`. | +| `ccMessageDeleted` | Triggered whenever a logged-in user deletes any message from the list of messages. | +| `ccMessageRead` | Triggered whenever a logged-in user reads any message. | +| `ccLiveReaction` | Triggered whenever a logged-in user clicks on live reaction. | +| `onFormMessageReceived` | Triggered when a form message is received. | +| `onCardMessageReceived` | Triggered when a card message is received. | +| `onCustomInteractiveMessageReceived` | Triggered when a custom interactive message is received. | +| `onInteractionGoalCompleted` | Triggered when an interaction goal is completed. | +| `onSchedulerMessageReceived` | Triggered when a scheduler message is received. | + +**Listener registration:** - -```java -CometChatMessageEvents.addListener("UNIQUE_ID", new CometChatMessageEvents() { - @Override - public void ccMessageSent(BaseMessage baseMessage, int status) { + +```kotlin lines +CometChatMessageEvents.addListener("UNIQUE_ID", object : CometChatMessageEvents() { + override fun ccMessageSent(baseMessage: BaseMessage?, status: Int) { // Perform action when message is sent } - @Override - public void ccMessageEdited(BaseMessage baseMessage, int status) { + override fun ccMessageEdited(baseMessage: BaseMessage?, status: Int) { // Perform action when message is edited } - @Override - public void ccMessageDeleted(BaseMessage baseMessage) { + override fun ccMessageDeleted(baseMessage: BaseMessage?) { // Perform action when message is deleted } - @Override - public void ccMessageRead(BaseMessage baseMessage) { + override fun ccMessageRead(baseMessage: BaseMessage?) { // Perform action when message is read } - @Override - public void ccLiveReaction(int icon) { + override fun ccLiveReaction(icon: Int) { // Perform action on live reaction } // Other overridden methods for handling specific message types and actions -}); +}) ``` - - - -```kotlin -CometChatMessageEvents.addListener("UNIQUE_ID", object : CometChatMessageEvents() { - override fun ccMessageSent(baseMessage: BaseMessage?, status: Int) { + +```java lines +CometChatMessageEvents.addListener("UNIQUE_ID", new CometChatMessageEvents() { + @Override + public void ccMessageSent(BaseMessage baseMessage, int status) { // Perform action when message is sent } - override fun ccMessageEdited(baseMessage: BaseMessage?, status: Int) { + @Override + public void ccMessageEdited(BaseMessage baseMessage, int status) { // Perform action when message is edited } - override fun ccMessageDeleted(baseMessage: BaseMessage?) { + @Override + public void ccMessageDeleted(BaseMessage baseMessage) { // Perform action when message is deleted } - override fun ccMessageRead(baseMessage: BaseMessage?) { + @Override + public void ccMessageRead(BaseMessage baseMessage) { // Perform action when message is read } - override fun ccLiveReaction(icon: Int) { + @Override + public void ccLiveReaction(int icon) { // Perform action on live reaction } // Other overridden methods for handling specific message types and actions -}) +}); ``` - - +> **What this does:** Registers a listener on `CometChatMessageEvents` using a unique ID string. The callbacks fire for message lifecycle events — sending, editing, deleting, reading messages, and reacting with live reactions. Additional overrides handle interactive message types (`onFormMessageReceived`, `onCardMessageReceived`, `onCustomInteractiveMessageReceived`, `onInteractionGoalCompleted`, `onSchedulerMessageReceived`). + +--- + ### Call Events -`Call Events` emits events related to calls within the application. This class provides methods to listen to call-related events and handle them accordingly. +`CometChatCallEvents` emits events related to calls within the application. This class provides methods to listen to call-related events and handle them. + +**Events:** -* `ccOutgoingCall`: Triggered when the logged-in user initiates an outgoing call. -* `ccCallAccepted`: Triggered when a call is accepted. -* `ccCallRejected`: Triggered when a call is rejected. -* `ccCallEnded`: Triggered when a call is ended. +| Event | Description | +| ----- | ----------- | +| `ccOutgoingCall` | Triggered when the logged-in user initiates an outgoing call. | +| `ccCallAccepted` | Triggered when a call is accepted. | +| `ccCallRejected` | Triggered when a call is rejected. | +| `ccCallEnded` | Triggered when a call is ended. | -To listen to call events and handle them in your application, you can use the following code snippet: +**Listener registration:** -```typescript + + +```kotlin lines +CometChatCallEvents.addListener("ListenerID", object : CometChatCallEvents() { + override fun ccOutgoingCall(call: Call) { + // Perform action when outgoing call is initiated + } + + override fun ccCallAccepted(call: Call) { + // Perform action when call is accepted + } + + override fun ccCallRejected(call: Call) { + // Perform action when call is rejected + } + + override fun ccCallEnded(call: Call) { + // Perform action when call is ended + } +}) +``` + + +```java lines CometChatCallEvents.addListener("ListenerID", new CometChatCallEvents() { @Override public void ccOutgoingCall(Call call) { @@ -280,21 +408,52 @@ CometChatCallEvents.addListener("ListenerID", new CometChatCallEvents() { } }); ``` + + + +> **What this does:** Registers a listener on `CometChatCallEvents` using a unique `"ListenerID"`. The callbacks fire for each stage of the call lifecycle — initiating an outgoing call, accepting, rejecting, and ending a call. + +--- ### UI Events -`UIEvents` emits events related to UI components within the CometChat UI. This class provides methods to listen to UI-related events and handle them accordingly. +`CometChatUIEvents` emits events related to UI components within the CometChat UI Kit. This class provides methods to listen to UI-related events and handle them. + +**Events:** + +| Event | Description | +| ----- | ----------- | +| `showPanel` | Triggered to show an additional UI panel with custom elements. | +| `hidePanel` | Triggered to hide a previously shown UI panel. | +| `ccActiveChatChanged` | Triggered when the active chat changes, providing information about the current message, user, and group. | +| `ccOpenChat` | Triggered to open a chat with a specific user or group. | + +**Listener registration:** -Following are the UI events + + +```kotlin lines +CometChatUIEvents.addListener("UNIQUE_ID", object : CometChatUIEvents() { + override fun showPanel(id: HashMap, alignment: UIKitConstants.CustomUIPosition, view: Function1) { + // Perform action to show UI panel with custom elements + } -* `showPanel`: Triggered to show an additional UI panel with custom elements. -* `hidePanel`: Triggered to hide a previously shown UI panel. -* `ccActiveChatChanged`: Triggered when the active chat changes, providing information about the current message, user, and group. -* `ccOpenChat`: Triggered to open a chat with a specific user or group. + override fun hidePanel(id: HashMap, alignment: UIKitConstants.CustomUIPosition) { + // Perform action to hide UI panel + } -To listen to UI events and handle them in your application, you can use the following code snippet: + override fun ccActiveChatChanged(id: HashMap, message: BaseMessage, user: User, group: Group) { + // Perform action when active chat changes + } -```typescript + override fun ccOpenChat(user: User, group: Group) { + // Perform action to open a chat with a specific user or group + } +}) +``` + + +```java lines CometChatUIEvents.addListener("UNIQUE_ID", new CometChatUIEvents() { @Override public void showPanel(HashMap id, UIKitConstants.CustomUIPosition alignment, Function1 view) { @@ -317,3 +476,29 @@ CometChatUIEvents.addListener("UNIQUE_ID", new CometChatUIEvents() { } }); ``` + + + +> **What this does:** Registers a listener on `CometChatUIEvents` using a unique ID string. The callbacks fire for UI-level actions — showing or hiding custom panels, reacting to active chat changes, and opening a chat with a specific user or group. + +--- + +## Removing event listeners + +Each event listener class provides methods to add and remove listeners. If you register a listener, remove it when the component or activity is destroyed to prevent memory leaks. Use the same tag or ID string you passed during registration. + +--- + +## Next steps + + + + UI Kit wrapper methods for initialization, authentication, and sending messages + + + Display and manage the conversation list, which reacts to conversation events + + + Display messages in a chat, which reacts to message events + + diff --git a/ui-kit/android/extensions.mdx b/ui-kit/android/extensions.mdx index 6333a9633..049a4a47c 100644 --- a/ui-kit/android/extensions.mdx +++ b/ui-kit/android/extensions.mdx @@ -1,16 +1,28 @@ --- title: "Extensions" +description: "Enable built-in CometChat extensions like reactions, stickers, polls, and link previews from the dashboard." --- -## Overview + + +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Required setup | `CometChatUIKit.init()` then `CometChatUIKit.login()` + Extensions enabled in [CometChat Dashboard](/fundamentals/extensions-overview) | +| Built-in extensions | Stickers, Polls, Collaborative Whiteboard, Collaborative Document, Message Translation, Link Preview, Thumbnail Generation, Profanity Filter | +| Key components | `CometChatMessageComposer` → [Message Composer](/ui-kit/android/message-composer) (Stickers, Polls, Whiteboard, Document), `CometChatMessageList` → [Message List](/ui-kit/android/message-list) (Translation, Link Preview, Thumbnails) | +| Activation | Enable each extension from the CometChat Dashboard — UI Kit auto-integrates them, no additional code required | +| Related | [Core Features](/ui-kit/android/core-features), [AI Features](/ui-kit/android/ai-features), [Extensions Overview](/fundamentals/extensions-overview) | + + CometChat’s UI Kit comes with built-in support for a wide variety of extensions that provide additional functionality. These extensions enhance the chatting experience, making it more interactive, secure, and efficient. -Activating any of the extensions in CometChat is a simple process done through your application's dashboard. Refer to our guide For detailed information on [Extensions](/fundamentals/extensions-overview) +Activating any of the extensions in CometChat is a simple process done through your application's dashboard. Refer to our guide for detailed information on [Extensions](/fundamentals/extensions-overview). -Once you have successfully enabled the desired extension in your dashboard, it will be reflected in your CometChat application upon initialization and successful login. Please note, that the extension features will only be available if they are supported by CometChat UI Kit. +Once you have successfully enabled the desired extension in your dashboard, it will be reflected in your CometChat application upon initialization and successful login. Please note that extension features will only be available if they are supported by the CometChat UI Kit. -CometChat’s UI Kit offers built-in support for 12 powerful extensions. This seamless integration makes it easy for you to enhance your chat application with engaging features without any extra coding effort. Just enable the desired extensions from the CometChat Dashboard, and they will be automatically reflected in the relevant components of your application, providing a richer and more engaging experience for your users. +CometChat’s UI Kit offers built-in support for 8 extensions. This seamless integration makes it easy for you to enhance your chat application with engaging features without any extra coding effort. Just enable the desired extensions from the CometChat Dashboard, and they will be automatically reflected in the relevant components of your application, providing a richer and more engaging experience for your users. ## Built-in Extensions @@ -76,12 +88,6 @@ Once you have successfully activated the [Link Preview Extension](/fundamentals/ -### Profanity Filter - -The Profanity Filter extension helps in maintaining the chat decorum by censoring obscene and inappropriate words in the messages. For a comprehensive understanding and guide on implementing and using the Profanity Filter Extension, refer to our specific guide on the [Legacy Extensions](/moderation/legacy-extensions). - -Once you have successfully activated the Profanity Filter Extension from your CometChat Dashboard, the feature will automatically be incorporated into the Message Bubble of [MessageList Component](/ui-kit/android/message-list) component of UI Kits. - ### Thumbnail Generation The Thumbnail Generation extension automatically creates a smaller preview image whenever a larger image is shared, helping to reduce the upload/download time and bandwidth usage. For a comprehensive understanding and guide on implementing and using the Thumbnail Generation Extension, refer to our specific guide on the [Thumbnail Generation Extension](/fundamentals/thumbnail-generation). @@ -91,3 +97,9 @@ Once you have successfully activated the [Thumbnail Generation Extension](/funda + +### Profanity Filter + +The Profanity Filter extension helps in maintaining the chat decorum by censoring obscene and inappropriate words in the messages. For a comprehensive understanding and guide on implementing and using the Profanity Filter Extension, refer to our specific guide on the [Legacy Extensions](/moderation/legacy-extensions). + +Once you have successfully activated the Profanity Filter Extension from your CometChat Dashboard, the feature will automatically be incorporated into the Message Bubble of [MessageList Component](/ui-kit/android/message-list) component of UI Kits. diff --git a/ui-kit/android/getting-started.mdx b/ui-kit/android/getting-started.mdx index 20f734f15..6cdc3d117 100644 --- a/ui-kit/android/getting-started.mdx +++ b/ui-kit/android/getting-started.mdx @@ -1,106 +1,75 @@ --- title: "Getting Started With CometChat Android UI Kit" sidebarTitle: "Integration" +description: "Install, configure, and launch the CometChat Android UI Kit in your app with step-by-step integration instructions." --- -The **CometChat UI Kit for Android** streamlines the integration of in-app chat functionality by providing a **comprehensive set of prebuilt UI components**. It offers seamless **theming options**, including **light and dark modes**, customizable fonts, colors, and extensive styling capabilities. + -With built-in support for **one-to-one and group conversations**, developers can efficiently enable chat features within their applications. Follow this guide to **quickly integrate chat functionality** using the CometChat Android UI Kit. +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` v5.x | +| Init | `CometChatUIKit.init(context, UIKitSettings, callback)` — must resolve before `login()` | +| Login | `CometChatUIKit.login("UID", callback)` — must resolve before rendering components | +| Order | `init()` → `login()` → render. Breaking this order = blank screen | +| Auth Key | Dev/testing only. Use Auth Token in production | +| Theme | Set `CometChatTheme.DayNight` as parent theme in `themes.xml` | +| Calling | Optional. Add `com.cometchat:calls-sdk-android` to enable voice/video | +| Min SDK | Android 7.0 (API 24) | + + + +This guide walks you through adding CometChat to an Android app. By the end you'll have a working chat UI. --------- - -*** - -## **Prerequisites** - -Before installing the **CometChat UI Kit for Android**, you must first **create a CometChat application** via the **[CometChat Dashboard](https://app.cometchat.com/)**. The dashboard provides all the essential chat service components, including: - -* **User Management** -* **Group Chat & Messaging** -* **Voice & Video Calling** -* **Real-time Notifications** - - - -To initialize the **UI Kit**, you will need the following credentials from your **CometChat application**: - -1. **App ID** -2. **Auth Key** -3. **Region** - -Ensure you have these details ready before proceeding with the installation and configuration. - - - -*** - -## **Register & Set Up CometChat** - -Follow these steps to **register on CometChat** and **set up your development environment**. - -### **Step 1: Register on CometChat** - -To use **CometChat UI Kit**, you first need to register on the **CometChat Dashboard**. - -🔗 **[Click here to Sign Up](https://app.cometchat.com/login)** - -### **Step 2: Get Your Application Keys** - -After registering, create a **new app** and retrieve your **authentication details**: -1. Navigate to **Application**, then select the **Credentials** section. - -2. Note down the following keys: - - * **App ID** - * **Auth Key** - * **Region** - - - -Each CometChat application can be integrated with a **single client app**. Users within the same application can communicate across multiple platforms, including **web and mobile**. - - +--- -### **Step 3: Set Up Your Development Environment** +## Prerequisites -Ensure your system meets the following **prerequisites** before proceeding with integration. +You need three things from the [CometChat Dashboard](https://app.cometchat.com/): -**System Requirements:** +| Credential | Where to find it | +| --- | --- | +| App ID | Dashboard → Your App → Credentials | +| Auth Key | Dashboard → Your App → Credentials | +| Region | Dashboard → Your App → Credentials (e.g. `us`, `eu`, `in`) | -* **Android Studio** installed on your machine. -* An **Android emulator or physical device** running Android 6.0 or higher. -* **Java 8 or higher** installed. -* **Gradle plugin 4.0.1 or later** installed. +You also need: +- Android Studio installed +- An Android emulator or physical device running Android 7.0 (API 24) or higher +- Java 8 or higher +- Gradle plugin 4.0.1 or later -*** + +Auth Key is for development only. In production, generate Auth Tokens server-side via the [REST API](https://api-explorer.cometchat.com/) and use [`loginWithAuthToken()`](/ui-kit/android/methods#login-using-auth-token). Never ship Auth Keys in client code. + -## **Getting Started** +--- -### **Step 1: Create an Android Project** +## Step 1 — Create an Android Project -1. Open **Android Studio** and start a **new project**. -2. Choose **Empty Activity** as the project template. -3. Enter a project name and choose **Java** or **Kotlin** as the language. -4. Set **minimum API level** to **21 or higher**. +1. Open Android Studio and start a new project. +2. Choose Empty Activity as the project template. +3. Enter a project name and choose Java or Kotlin as the language. +4. Set minimum API level to 24 or higher. -*** +--- -### **Step 2: Install Dependencies** +## Step 2 — Install Dependencies -To integrate CometChat into your Android project, add the required dependencies to your **Gradle configuration**. +Add the CometChat repository and dependencies to your Gradle configuration. -#### **i. Add the CometChat Repository** +### Add the CometChat Repository -To integrate CometChat into your Android project, you need to add the CometChat repository to your project-level `settings.gradle` or `settings.gradle.kts` file. Follow the steps below based on your project configuration. +Add the CometChat Maven repository to your project-level `settings.gradle` or `settings.gradle.kts` file. -```gradle settings.gradle.kts +```gradle settings.gradle.kts lines dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { @@ -115,7 +84,7 @@ dependencyResolutionManagement { -```gradle settings.gradle +```gradle settings.gradle lines dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { @@ -132,21 +101,21 @@ dependencyResolutionManagement { -#### **ii. Add the CometChat Dependency** +### Add the CometChat Dependency Inside `libs.versions.toml`, add the CometChat Chat UI Kit version under the `[versions]` section: -```toml libs.versions.toml +```toml libs.versions.toml lines [versions] -cometchat-ui-kit = "5.2.7" +cometchat-ui-kit = "5.2.9" cometchat-calls-sdk = "4.3.3" ``` Under the `[libraries]` section, define the library and reference the version: -```toml libs.versions.toml +```toml libs.versions.toml lines [libraries] cometchat-ui-kit = { module = "com.cometchat:chat-uikit-android", version.ref = "cometchat-ui-kit" } cometchat-calls-sdk = { module = "com.cometchat:calls-sdk-android", version.ref = "cometchat-calls-sdk" } @@ -154,7 +123,7 @@ cometchat-calls-sdk = { module = "com.cometchat:calls-sdk-android", version.ref Now, in your app-level `build.gradle.kts` file, add the dependency using libs from Version Catalogs: -```gradle build.gradle.kts +```gradle build.gradle.kts lines dependencies { implementation(libs.cometchat.ui.kit) @@ -166,12 +135,12 @@ dependencies { -Open the **app level** `build.gradle` file and add the following dependency to fetch the chat UI kit into your project. +Open the app level `build.gradle` file and add the following dependency: -```gradle build.gradle +```gradle build.gradle lines dependencies { // CometChat UIKit - implementation 'com.cometchat:chat-uikit-android:5.2.7' + implementation 'com.cometchat:chat-uikit-android:5.2.9' // (Optional) Include this if your app uses voice/video calling features implementation 'com.cometchat:calls-sdk-android:4.3.3' @@ -182,59 +151,27 @@ dependencies { -#### **iii. Add AndroidX Support** - -The Jetifier tool helps migrate legacy support libraries to AndroidX. +### Add AndroidX Support -Open the gradle.properties file and verify if the specified line is present. If not, add it accordingly. +The Jetifier tool helps migrate legacy support libraries to AndroidX. Open `gradle.properties` and verify this line is present: -```gradle gradle.properties +```gradle gradle.properties lines android.enableJetifier=true ``` -*** - -### **Step 3: Initialize & Login to CometChat UI Kit** - -To authenticate a user, you need a **`UID`**. You can either: - -1. **Create new users** on the **[CometChat Dashboard](https://app.cometchat.com)**, **[CometChat SDK Method](/ui-kit/android/methods#create-user)** or **[via the API](https://api-explorer.cometchat.com/reference/creates-user)**. - -2. **Use pre-generated test users**: - - * `cometchat-uid-1` - * `cometchat-uid-2` - * `cometchat-uid-3` - * `cometchat-uid-4` - * `cometchat-uid-5` - -The **Login** method returns a **User object** containing all relevant details of the logged-in user. - -*** - - -**Auth Key Usage** - -The **Auth Key** is an **optional property** of the `UIKitSettings` class. It is primarily recommended for **proof-of-concept (POC) development** or **early-stage application development**. - -For secure authentication, use the [`Auth Token`](/ui-kit/android/methods#login-using-auth-token) method instead. - - - -*** +--- - +## Step 3 — Initialize and Login -**Security Best Practices** +To authenticate a user, you need a UID. You can either create users on the [CometChat Dashboard](https://app.cometchat.com), via the [SDK method](/ui-kit/android/methods#create-user), or through the [REST API](https://api-explorer.cometchat.com/reference/creates-user). -* The **Auth Key** method is recommended for **proof-of-concept (POC) development** and early-stage testing. -* For **production environments**, it is strongly advised to use an **[Auth Token](/ui-kit/android/methods#login-using-auth-token)** instead of an **Auth Key** to enhance security and prevent unauthorized access. +For development, use one of the pre-created test UIDs: - +`cometchat-uid-1` · `cometchat-uid-2` · `cometchat-uid-3` · `cometchat-uid-4` · `cometchat-uid-5` -```kotlin MainActivity.kt +```kotlin MainActivity.kt highlight={15-17, 46-55} lines import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity @@ -280,15 +217,15 @@ class MainActivity : ComponentActivity() { CometChatUIKit.login("cometchat-uid-1", object : CometChat.CallbackListener() { override fun onSuccess(user: User) { - // ✅ Option 1: Launch One-to-One or Group Chat Screen + // Option 1: Launch One-to-One or Group Chat Screen // val intent = Intent(this@MainActivity, MessageActivity::class.java) // intent.putExtra("uid", "cometchat-uid-1") // startActivity(intent) - // ✅ Option 2: Launch Conversation List + Message View (Split-Screen Style) + // Option 2: Launch Conversation List + Message View (Split-Screen Style) // startActivity(Intent(this@MainActivity, ConversationActivity::class.java)) - // ✅ Option 3: Launch Tab-Based Chat Experience (Chats, Calls, Users, Groups) + // Option 3: Launch Tab-Based Chat Experience (Chats, Calls, Users, Groups) // startActivity(Intent(this@MainActivity, TabbedActivity::class.java)) } @@ -304,7 +241,7 @@ class MainActivity : ComponentActivity() { -```java MainActivity.java +```java MainActivity.java highlight={15-17, 51-60} lines import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -355,15 +292,15 @@ public class MainActivity extends ComponentActivity { public void onSuccess(User user) { Log.d(TAG, "Login successful for user: " + user.getUid()); - // ✅ Option 1: Launch One-to-One or Group Chat Screen + // Option 1: Launch One-to-One or Group Chat Screen // Intent intent = new Intent(MainActivity.this, MessageActivity.class); // intent.putExtra("uid", "cometchat-uid-1"); // startActivity(intent); - // ✅ Option 2: Launch Conversation List + Message View + // Option 2: Launch Conversation List + Message View // startActivity(new Intent(MainActivity.this, ConversationActivity.class)); - // ✅ Option 3: Launch Tab-Based Chat Experience (Chats, Calls, Users, Groups) + // Option 3: Launch Tab-Based Chat Experience (Chats, Calls, Users, Groups) // startActivity(new Intent(MainActivity.this, TabbedActivity.class)); } @@ -380,159 +317,121 @@ public class MainActivity extends ComponentActivity { - - -Ensure you replace the following placeholders with your actual CometChat credentials: + +`init()` must resolve before you call `login()`. If you call `login()` before init completes, it will fail silently. + -* APP\_ID → Your CometChat App ID -* AUTH\_KEY → Your CometChat Auth Key -* REGION → Your App Region + +For production, use [`loginWithAuthToken()`](/ui-kit/android/methods#login-using-auth-token) instead of Auth Key. Generate tokens server-side via the REST API. + -These values are required for proper authentication and seamless integration. - - - -*** +--- -### **Step 4: Set Up Global Theme** +## Step 4 — Set Up Global Theme -To customize component styling across your application in one place, you need to set up the **CometChat Theme**. +To customize component styling across your application, set up the CometChat Theme. Use the `CometChatTheme.DayNight` style, which is built on `Theme.MaterialComponents.DayNight.NoActionBar`. -**Apply the Theme** - -Set `CometChatTheme.DayNight` as the parent theme for your application in the `themes.xml` file. - -```xml themes.xml +```xml themes.xml lines + + +```kotlin lines +cometchatGroupMembers.setLeadingView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View? { + return null + } - + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + } +}) ``` + - -```java -cometchatGroupMembers.setStyle(R.style.CustomGroupMembersStyle); -``` +```java lines +cometchatGroupMembers.setLeadingView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return null; + } - + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - -```kotlin -cometchatGroupMembers.setStyle(R.style.CustomGroupMembersStyle) + } +}); ``` - - -*** - -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_group_members.xml). - -### Functionality +> **What this does:** Registers a `GroupMembersViewHolderListeners` that provides a custom view for the leading (left) area of each group member item. `createView` inflates your layout, and `bindView` populates it with group member data. -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can toggle the visibility of UI elements. +Scope badge avatar example: -Below is a list of customizations along with corresponding code snippets + + + -| Methods | Description | Code | -| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -| setGroup | Sets the group whose members need to be fetched. This is a required property for the component to function properly. | `.setGroup(group);` | -| setBackIconVisibility | Used to toggle visibility for back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | -| setToolbarVisibility | Used to toggle visibility for back button in the app bar | `.setToolbarVisibility(View.GONE);` | -| setErrorStateVisibility | Used to hide error state on fetching Users | `.setErrorStateVisibility(View.GONE);` | -| setEmptyStateVisibility | Used to hide empty state on fetching Users | `.setEmptyStateVisibility(View.GONE);` | -| setLoadingStateVisibility | Used to hide loading state while fetching Users | `.setLoadingStateVisibility(View.GONE);` | -| setSeparatorVisibility | Used to control visibility of Separators in the list view | `.setSeparatorVisibility(View.GONE);` | -| setUsersStatusVisibility | Used to control visibility of status indicator shown if user is online | `.setUsersStatusVisibility(View.GONE);` | -| setSelectionMode | This method determines the selection mode for members, enabling users to select either a single or multiple members at once. | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | -| setSearchkeyword | Used for fetching members matching the passed keywords | `.setSearchkeyword("anything");` | -| setSearchBoxVisibility | Used to hide search box shown in the tool bar | `.setSearchBoxVisibility(View.GONE);` | +Create a custom layout file named `custom_title_view.xml`: -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your own views, layouts, and UI elements and then incorporate those into the component. - -The `Group Memebers` component does not provide additional functionalities beyond this level of customization. - -*** - -#### setOptions - -Defines a set of available actions that users can perform when they interact with a group member item. +```xml custom_title_view.xml lines + + -Use Cases: + -* Provide actions like "View Profile", "Send Message", "Remove from Group". -* Restrict certain actions to admins (e.g., "Promote to Admin", "Ban User"). + - - -```java -cometchatUsers.setOptions((context, user) -> Collections.emptyList()); + ``` - +> **What this does:** Defines a custom leading view layout with a `CometChatAvatar` and a role badge view that can display different backgrounds based on the member's scope (admin, moderator, participant). + -```kotlin -cometchatUsers.options = Function2?> { context, user -> emptyList() } -``` +```kotlin YourActivity.kt lines +cometchatGroupMembers.setLeadingView(object : GroupMembersViewHolderListeners() { + override fun createView(context: Context?, listItem: CometchatGroupMemberListItemBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.header_leading_view, null, false) + } + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + val avatar = createdView.findViewById(R.id.avatar) + avatar.setAvatar(groupMember.name, groupMember.avatar) + val role = createdView.findViewById(R.id.batch_view) + if (UIKitConstants.GroupMemberScope.ADMIN == groupMember.scope) { + role.visibility = View.VISIBLE + role.background = ResourcesCompat.getDrawable(resources, R.drawable.marketing_head, null) + } else if (UIKitConstants.GroupMemberScope.MODERATOR == groupMember.scope) { + role.visibility = View.VISIBLE + role.background = ResourcesCompat.getDrawable(resources, R.drawable.sr_manager, null) + } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS == groupMember.scope) { + role.visibility = View.VISIBLE + role.background = ResourcesCompat.getDrawable(resources, R.drawable.content_manager, null) + } else { + role.background = ResourcesCompat.getDrawable(resources, R.drawable.team_member, null) + } + val layoutParams = LinearLayout.LayoutParams( + Utils.convertDpToPx(context, 40), + Utils.convertDpToPx(context, 40) + ) + createdView.layoutParams = layoutParams + } +}) +``` - - -*** - -#### addOptions - -Adds custom actions to the existing options available when interacting with a group member. - -Use Cases: - -* Extend functionality by adding "Block User", "Report User", or "View Activity". -* Customize actions based on member roles. - - -```java -cometchatUsers.addOptions((context, user) -> Collections.emptyList()); -``` - - +```java YourActivity.java lines +cometchatGroupMembers.setLeadingView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.header_leading_view, null, false); + } - -```kotlin -cometchatUsers.addOptions { context, user -> emptyList() } + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + CometChatAvatar avatar = createdView.findViewById(R.id.avatar); + avatar.setAvatar(groupMember.getName(), groupMember.getAvatar()); + View role = createdView.findViewById(R.id.batch_view); + if (UIKitConstants.GroupMemberScope.ADMIN.equals(groupMember.getScope())) { + role.setVisibility(View.VISIBLE); + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.marketing_head, null)); + } else if (UIKitConstants.GroupMemberScope.MODERATOR.equals(groupMember.getScope())) { + role.setVisibility(View.VISIBLE); + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.sr_manager, null)); + } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS.equals(groupMember.getScope())) { + role.setVisibility(View.VISIBLE); + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.content_manager, null)); + } else { + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.team_member, null)); + } + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(Utils.convertDpToPx(context, 40), + Utils.convertDpToPx(context, 40)); + createdView.setLayoutParams(layoutParams); + } +}); ``` - - -*** +> **What this does:** Inflates a custom leading view layout and populates it with the group member's avatar and a role-based badge. If the member is an admin, the badge shows the `marketing_head` drawable; if a moderator, `sr_manager`; if a participant, `content_manager`; otherwise, `team_member`. The view is sized to 40dp × 40dp. -#### setLoadingView +### `setTitleView` -Displays a custom loading view while group members are being fetched. +Replace the name / title text. -Use Cases: + + +```kotlin lines +cometchatGroupMembers.setTitleView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View? { + return null + } -* Show a loading spinner with "Fetching group members...". -* Implement a skeleton loader for a smoother UI experience. + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + } +}) +``` + - -```java -cometchatUsers.setLoadingView(R.layout.your_loading_view); -``` +```java lines +cometchatGroupMembers.setTitleView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return null; + } - + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - -```kotlin -cometchatUsers.loadingView = R.layout.your_loading_view + } +}); ``` - - -*** +Inline role badge example: -#### setEmptyView + + + -Configures a view to be displayed when no group members are found. +Create a custom layout file named `custom_title_view.xml`: -Use Cases: +```xml custom_title_view.xml lines + + -* Display a message like "No members in this group yet.". -* Show a button to Invite Members. + - - -```java -cometchatUsers.setEmptyView(R.layout.your_empty_view); + + ``` - +> **What this does:** Defines a custom title view layout with a `TextView` for the member name and a `View` for the role badge, arranged horizontally. + -```kotlin -cometchatUsers.emptyView = R.layout.your_empty_view -``` +```kotlin YourActivity.kt lines +cometchatGroupMembers.setTitleView(object : GroupMembersViewHolderListeners() { + override fun createView(context: Context?, listItem: CometchatGroupMemberListItemBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null, false) + } + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + val layout = createdView.findViewById(R.id.user_layout) + val layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + layout.layoutParams = layoutParams + val name = createdView.findViewById(R.id.title) + name.text = groupMember.name + val role = createdView.findViewById(R.id.role) + if (UIKitConstants.GroupMemberScope.ADMIN == groupMember.scope) { + role.visibility = View.VISIBLE + role.background = ResourcesCompat.getDrawable(resources, R.drawable.marketing_head, null) + } else if (UIKitConstants.GroupMemberScope.MODERATOR == groupMember.scope) { + role.visibility = View.VISIBLE + role.background = ResourcesCompat.getDrawable(resources, R.drawable.sr_manager, null) + } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS == groupMember.scope) { + role.visibility = View.VISIBLE + role.background = ResourcesCompat.getDrawable(resources, R.drawable.content_manager, null) + } else { + role.background = ResourcesCompat.getDrawable(resources, R.drawable.team_member, null) + } + } +}) +``` - - -*** - -#### setErrorView - -Defines a custom error state view when there is an issue loading group members. - -Use Cases: - -* Display a retry button with "Failed to load members. Tap to retry.". -* Show an illustration for a better user experience. - - -```java -cometchatUsers.setErrorView(R.layout.your_empty_view); -``` - - +```java YourActivity.java lines +cometchatGroupMembers.setTitleView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null, false); + } - -```kotlin -cometchatUsers.errorView = R.layout.your_error_view + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + LinearLayout layout = createdView.findViewById(R.id.user_layout); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + layout.setLayoutParams(layoutParams); + TextView name = createdView.findViewById(R.id.title); + name.setText(groupMember.getName()); + View role = createdView.findViewById(R.id.role); + if (UIKitConstants.GroupMemberScope.ADMIN.equals(groupMember.getScope())) { + role.setVisibility(View.VISIBLE); + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.marketing_head, null)); + } else if (UIKitConstants.GroupMemberScope.MODERATOR.equals(groupMember.getScope())) { + role.setVisibility(View.VISIBLE); + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.sr_manager, null)); + } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS.equals(groupMember.getScope())) { + role.setVisibility(View.VISIBLE); + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.content_manager, null)); + } else { + role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.team_member, null)); + } + } +}); ``` - - -*** - -#### setLeadingView +> **What this does:** Inflates a custom title view layout and populates it with the group member's name and a role-based badge. The badge background changes based on the member's scope: `marketing_head` for admin, `sr_manager` for moderator, `content_manager` for participant, and `team_member` for others. -Sets a custom leading view for each group member item, usually used for profile images or avatars. +### `setSubtitleView` -Use Cases: - -* Show a circular avatar with an online/offline indicator. -* Add a role-based badge (Admin, Moderator, Member). +Replace the subtitle text below the member's name. - -```java -cometchatUsers.setLeadingView(new UsersViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List userList, int position) { - - } - }); -``` - - - -```kotlin -cometchatUsers.setLeadingView(object: UsersViewHolderListener { - override fun createView(context: Context, cometChatListItem: CometChatListItem): View? { +```kotlin lines +cometchatGroupMembers.setSubtitleView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View? { return null } - override fun bindView(context: Context, view: View, user: User, viewHolder: RecyclerView.ViewHolder, list: List, i: Int) { + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { } }) ``` - - - - - - - -You can indeed create a custom layout file named `custom_title_view.xml` for more complex or unique list items. + +```java lines +cometchatGroupMembers.setSubtitleView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return null; + } -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: + } +}); +``` + + -```xml custom_title_view.xml - - +Example with join date: - + + + - + + +```kotlin YourActivity.kt lines +cometchatGroupMembers.setSubtitleView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View { + return TextView(context) + } - + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + (createdView as TextView).text = + "Joined at: " + SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(groupMember.joinedAt * 1000) + } +}) ``` + - -```java YourActivity.java -cometchatGroupMembers.setTitleView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.header_leading_view, null, false); - - - } - - @Override - public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - CometChatAvatar avatar = createdView.findViewById(R.id.avatar); - avatar.setAvatar(groupMember.getName(), groupMember.getAvatar()); - View role = createdView.findViewById(R.id.batch_view); - if (UIKitConstants.GroupMemberScope.ADMIN.equals(groupMember.getScope())) { - role.setVisibility(View.VISIBLE); - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.marketing_head, null)); - } else if (UIKitConstants.GroupMemberScope.MODERATOR.equals(groupMember.getScope())) { - role.setVisibility(View.VISIBLE); - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.sr_manager, null)); - } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS.equals(groupMember.getScope())) { - role.setVisibility(View.VISIBLE); - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.content_manager, null)); - } else { - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.team_member, null)); - } - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(Utils.convertDpToPx(context, 40), - Utils.convertDpToPx(context, 40)); - createdView.setLayoutParams(layoutParams); - } - }); -``` - - +```java YourActivity.java lines +cometchatGroupMembers.setSubtitleView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return new TextView(context); + } - -```kotlin YourActivity.kt -cometchatGroupMembers.setLeadingView(object : GroupMembersViewHolderListeners() { - override fun createView(context: Context?, listItem: CometchatGroupMemberListItemBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.header_leading_view, null, false) - } - - override fun bindView( - context: Context, - createdView: View, - groupMember: GroupMember, - group: Group, - holder: RecyclerView.ViewHolder, - groupMemberList: List, - position: Int - ) { - val avatar = createdView.findViewById(R.id.avatar) - avatar.setAvatar(groupMember.name, groupMember.avatar) - val role = createdView.findViewById(R.id.batch_view) - if (UIKitConstants.GroupMemberScope.ADMIN == groupMember.scope) { - role.visibility = View.VISIBLE - role.background = ResourcesCompat.getDrawable(resources, R.drawable.marketing_head, null) - } else if (UIKitConstants.GroupMemberScope.MODERATOR == groupMember.scope) { - role.visibility = View.VISIBLE - role.background = ResourcesCompat.getDrawable(resources, R.drawable.sr_manager, null) - } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS == groupMember.scope) { - role.visibility = View.VISIBLE - role.background = ResourcesCompat.getDrawable(resources, R.drawable.content_manager, null) - } else { - role.background = ResourcesCompat.getDrawable(resources, R.drawable.team_member, null) - } - val layoutParams = LinearLayout.LayoutParams( - Utils.convertDpToPx(context, 40), - Utils.convertDpToPx(context, 40) - ) - createdView.layoutParams = layoutParams - } - }) + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + ((TextView) createdView).setText("Joined at: " + new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(groupMember.getJoinedAt() * 1000)); + } +}); ``` - - -*** - -#### setTitleView +> **What this does:** Creates a `TextView` as the subtitle view and populates it with the group member's join date formatted as "dd/MM/yyyy, HH:mm:ss". The `joinedAt` timestamp is multiplied by 1000 to convert from seconds to milliseconds. -Customizes the title view, typically displaying the member's name. +### `setTrailingView` -Use Cases: - -* Customize fonts, colors, or styles for usernames. -* Add role-specific indicators like "(Group Admin)". +Replace the right section of each group member item. - -```java -cometchatUsers.setTitleView(new UsersViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, User user, RecyclerView.ViewHolder holder, List userList, int position) { - - } - }); -``` - - - -```kotlin -cometchatUsers.setTitleView(object: UsersViewHolderListener { - override fun createView(context: Context, cometChatListItem: CometChatListItem): View? { +```kotlin lines +cometchatGroupMembers.setTrailingView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View? { return null } - override fun bindView(context: Context, view: View, user: User, viewHolder: RecyclerView.ViewHolder, list: List, i: Int) { + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { } }) ``` - + +```java lines +cometchatGroupMembers.setTrailingView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + + } +}); +``` + +Scope badge example: + - + -You can indeed create a custom layout file named `custom_title_view.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: +Create a custom layout file named `custom_tail_view.xml`: -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: - -```xml custom_title_view.xml +```xml custom_tail_view.xml lines + android:layout_height="wrap_content"> - + android:layout_marginStart="16dp" + app:cardBackgroundColor="?attr/cometchatPrimaryColor" + app:cardCornerRadius="@dimen/cometchat_radius_max" + app:cardElevation="@dimen/cometchat_0dp"> - - -``` + - - -```java YourActivity.java -cometchatGroupMembers.setTitleView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null, false); - - } - - @Override - public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - LinearLayout layout = createdView.findViewById(R.id.user_layout); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - layout.setLayoutParams(layoutParams); - TextView name = createdView.findViewById(R.id.title); - name.setText(groupMember.getName()); - View role = createdView.findViewById(R.id.role); - if (UIKitConstants.GroupMemberScope.ADMIN.equals(groupMember.getScope())) { - role.setVisibility(View.VISIBLE); - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.marketing_head, null)); - } else if (UIKitConstants.GroupMemberScope.MODERATOR.equals(groupMember.getScope())) { - role.setVisibility(View.VISIBLE); - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.sr_manager, null)); - } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS.equals(groupMember.getScope())) { - role.setVisibility(View.VISIBLE); - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.content_manager, null)); - } else { - role.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.team_member, null)); - - } - } - }); + + + ``` - +> **What this does:** Defines a custom trailing view layout with a `MaterialCardView` containing a `TextView` that displays the member's scope as a colored badge. + -```kotlin YourActivity.kt -cometchatGroupMembers.setTitleView(object : GroupMembersViewHolderListeners() { - override fun createView(context: Context?, listItem: CometchatGroupMemberListItemBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.custom_title_view, null, false) - } - - override fun bindView( - context: Context, - createdView: View, - groupMember: GroupMember, - group: Group, - holder: RecyclerView.ViewHolder, - groupMemberList: List, - position: Int - ) { - val layout = createdView.findViewById(R.id.user_layout) - val layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - layout.layoutParams = layoutParams - val name = createdView.findViewById(R.id.title) - name.text = groupMember.name - val role = createdView.findViewById(R.id.role) - if (UIKitConstants.GroupMemberScope.ADMIN == groupMember.scope) { - role.visibility = View.VISIBLE - role.background = ResourcesCompat.getDrawable(resources, R.drawable.marketing_head, null) - } else if (UIKitConstants.GroupMemberScope.MODERATOR == groupMember.scope) { - role.visibility = View.VISIBLE - role.background = ResourcesCompat.getDrawable(resources, R.drawable.sr_manager, null) - } else if (UIKitConstants.GroupMemberScope.PARTICIPANTS == groupMember.scope) { - role.visibility = View.VISIBLE - role.background = ResourcesCompat.getDrawable(resources, R.drawable.content_manager, null) - } else { - role.background = ResourcesCompat.getDrawable(resources, R.drawable.team_member, null) - } - } - }) -``` +```kotlin YourActivity.kt lines +cometchatGroupMembers.setTrailingView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View { + return View.inflate(context, R.layout.custom_tail_view, null) + } + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + val cardView = createdView.findViewById(R.id.scope_card) + val tvName = createdView.findViewById(R.id.tv_scope) + cardView.setCardBackgroundColor(CometChatTheme.getExtendedPrimaryColor100(context)) + tvName.text = groupMember.scope + createdView.visibility = + if (groupMember.scope == UIKitConstants.GroupMemberScope.PARTICIPANTS) View.VISIBLE else View.GONE + } +}) +``` - - -*** - -#### setItemView - -Assigns a fully custom ListItem layout to the Group Members Component, replacing the default structure. - -Use Cases: - -* Include additional member details like joined date, bio, or status. -* Modify layout based on user roles. - - -```java -cometchatGroupMembers.setItemView(new GroupMembersViewHolderListeners() { +```java YourActivity.java lines +cometchatGroupMembers.setTrailingView(new GroupMembersViewHolderListeners() { @Override - public View createView(Context context, CometchatGroupMemberListItemBinding cometChatListItem) { - return null; + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return View.inflate(context, R.layout.custom_tail_view, null); } @Override - public void bindView(Context context, View view, GroupMember groupMember, Group group, RecyclerView.ViewHolder viewHolder, List list, int i) { - + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + MaterialCardView cardView = createdView.findViewById(R.id.scope_card); + TextView tvName = createdView.findViewById(R.id.tv_scope); + cardView.setCardBackgroundColor(CometChatTheme.getExtendedPrimaryColor100(context)); + tvName.setText(groupMember.getScope()); + createdView.setVisibility(groupMember.getScope().equals(UIKitConstants.GroupMemberScope.PARTICIPANTS) ? View.VISIBLE : View.GONE); } }); ``` + + - +> **What this does:** Inflates a custom trailing view that displays a scope badge for each group member. The badge background uses the extended primary color, the text shows the member's scope, and the badge is only visible for participants (hidden for admins, moderators, and owners). + +### `setItemView` +Replace the entire list item row. + + -```kotlin +```kotlin lines cometchatGroupMembers.setItemView(object : GroupMembersViewHolderListeners() { - override fun createView(context: Context, cometChatListItem: CometchatGroupMemberListItemBinding): View? { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View? { return null } override fun bindView( context: Context, - view: View, + createdView: View, groupMember: GroupMember, group: Group, - viewHolder: RecyclerView.ViewHolder, - list: List, - i: Int + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int ) { } }) ``` - + +```java lines +cometchatGroupMembers.setItemView(new GroupMembersViewHolderListeners() { + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + + } +}); +``` + -**Example** +Example with name and scope: -You can indeed create a custom layout file named `item_list.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: +Create a custom layout file named `item_list.xml`: -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: - -```xml item_list.xml +```xml item_list.xml lines - ``` +> **What this does:** Defines a custom list item layout with two `TextView` elements: one for the member name and one for the subtitle (scope), arranged vertically. + + +```kotlin YourActivity.kt lines +cometchatGroupMembers.setItemView(object : GroupMembersViewHolderListeners() { + override fun createView( + context: Context?, + listItem: CometchatGroupMemberListItemBinding? + ): View { + return View.inflate(context, R.layout.custom_group_list_item, null) + } + + override fun bindView( + context: Context, + createdView: View, + groupMember: GroupMember, + group: Group, + holder: RecyclerView.ViewHolder, + groupMemberList: List, + position: Int + ) { + val tvName = createdView.findViewById(R.id.tvName) + val tvScope = createdView.findViewById(R.id.tvSubtitle) + tvName.text = groupMember.name + tvScope.text = groupMember.scope + } +}) +``` + + -```java YourActivity.java +```java YourActivity.java lines cometchatGroupMembers.setItemView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { - return View.inflate(context, R.layout.custom_group_list_item, null); - } - - @Override - public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - TextView tvName = createdView.findViewById(R.id.tvName); - TextView tvScope = createdView.findViewById(R.id.tvSubtitle); - tvName.setText(groupMember.getName()); - tvScope.setText(groupMember.getScope()); - } - }); -``` + @Override + public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { + return View.inflate(context, R.layout.custom_group_list_item, null); + } + @Override + public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { + TextView tvName = createdView.findViewById(R.id.tvName); + TextView tvScope = createdView.findViewById(R.id.tvSubtitle); + tvName.setText(groupMember.getName()); + tvScope.setText(groupMember.getScope()); + } +}); +``` + +> **What this does:** Inflates a custom list item layout and populates it with the group member's name and scope. Each list item shows the member name in the primary text style and their scope (admin, moderator, participant) in the secondary text style. + +### `setOptions` + +Replace the long-press context menu entirely. + + -```kotlin YourActivity.kt -cometchatGroupMembers.setItemView(object : - GroupMembersViewHolderListeners() { - override fun createView( - context: Context?, - listItem: CometchatGroupMemberListItemBinding? - ): View { - return View.inflate(context, R.layout.custom_group_list_item, null) - } - - override fun bindView( - context: Context, - createdView: View, - groupMember: GroupMember, - group: Group, - holder: RecyclerView.ViewHolder, - groupMemberList: List, - position: Int - ) { - val tvName = createdView.findViewById(R.id.tvName) - val tvScope = createdView.findViewById(R.id.tvSubtitle) - tvName.text = groupMember.name - tvScope.text = groupMember.scope - } - }) +```kotlin lines +cometchatGroupMembers.setOptions { context, groupMember, group -> emptyList() } ``` - + +```java lines +cometchatGroupMembers.setOptions((context, groupMember, group) -> Collections.emptyList()); +``` + -*** +### `addOptions` -#### setSubTitleView +Append to the long-press context menu without removing defaults. + + + +```kotlin lines +cometchatGroupMembers.addOptions { context, groupMember, group -> emptyList() } +``` + -Customizes the subtitle view for each group member, typically used for extra details. + +```java lines +cometchatGroupMembers.addOptions((context, groupMember, group) -> Collections.emptyList()); +``` + + -Use Cases: +### `setLoadingStateView` -* Show "Last Active" time. -* Display a custom status message. +Sets a custom loading view displayed when data is being fetched. + +```kotlin lines +cometchatGroupMembers.setLoadingStateView(R.layout.your_loading_view) +``` + + -```java -cometchatGroupMembers.setSubtitleView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding cometChatListItem) { - return null; - } +```java lines +cometchatGroupMembers.setLoadingStateView(R.layout.your_loading_view); +``` + + - @Override - public void bindView(Context context, View view, GroupMember groupMember, Group group, RecyclerView.ViewHolder viewHolder, List list, int i) { +### `setEmptyStateView` - } -}); +Configures a custom view displayed when there are no group members in the list. + + + +```kotlin lines +cometchatGroupMembers.setEmptyStateView(R.layout.your_empty_view) ``` + + +```java lines +cometchatGroupMembers.setEmptyStateView(R.layout.your_empty_view); +``` + - -```kotlin -cometchatGroupMembers.setSubtitleView(object : GroupMembersViewHolderListeners() { - override fun createView(context: Context, cometChatListItem: CometchatGroupMemberListItemBinding?): View? { - return null - } +### `setErrorStateView` - override fun bindView( - context: Context, - view: View, - groupMember: GroupMember, - group: Group, - viewHolder: RecyclerView.ViewHolder, - list: List, - i: Int - ) { - } -}) -``` +Defines a custom error state view that appears when an issue occurs while loading group members. + + +```kotlin lines +cometchatGroupMembers.setErrorStateView(R.layout.your_error_view) +``` + +```java lines +cometchatGroupMembers.setErrorStateView(R.layout.your_error_view); +``` + -**Example** +### `setOverflowMenu` + +Replace the toolbar overflow menu. - + -You can indeed create a custom layout file named `subtitle_layout.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: - -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: - - -```java YourActivity.java -cometchatGroupMembers.setSubtitleView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { - return new TextView(context); - } - - @Override - public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - ((TextView) createdView).setText("Joined at: "+new SimpleDateFormat("dd/mm/yyyy").format(groupMember.getJoinedAt()*1000)); - } - }); + +```kotlin lines +val addMemberIv = ImageView(this) +addMemberIv.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_add, null)) +cometchatGroupMembers.setOverflowMenu(addMemberIv) ``` - - -```kotlin YourActivity.kt -cometchatGroupMembers.setSubtitleView(object : - GroupMembersViewHolderListeners() { - override fun createView( - context: Context?, - listItem: CometchatGroupMemberListItemBinding? - ): View { - return TextView(context) - } - - override fun bindView( - context: Context, - createdView: View, - groupMember: GroupMember, - group: Group, - holder: RecyclerView.ViewHolder, - groupMemberList: List, - position: Int - ) { - (createdView as TextView).text = - "Joined at: " + SimpleDateFormat("dd/mm/yyyy").format(groupMember.joinedAt * 1000) - } - }) + +```java lines +ImageView addMemberIv = new ImageView(this); +addMemberIv.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_add, null)); +cometchatGroupMembers.setOverflowMenu(addMemberIv); ``` - - -*** +> **What this does:** Creates an `ImageView` with an add icon and sets it as the overflow menu in the group members toolbar. This provides a quick action button for adding new members. -#### setTrailingView +- **Verify**: After setting any custom view slot, confirm the custom view renders in the correct position within the group member list item, and the data binding populates correctly for each member. -Customizes the trailing (right-end) section of each member item, typically used for action buttons. +## Common Patterns -Use Cases: - -* Show quick actions like Mute, Remove, or Promote. -* Display a "Last Active" timestamp. +### Hide all chrome — minimal list + +```kotlin lines +cometchatGroupMembers.setUserStatusVisibility(View.GONE) +cometchatGroupMembers.setSeparatorVisibility(View.GONE) +cometchatGroupMembers.setToolbarVisibility(View.GONE) +``` + + -```java -cometchatGroupMembers.setTrailingView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding cometChatListItem) { - return null; - } +```java lines +cometchatGroupMembers.setUserStatusVisibility(View.GONE); +cometchatGroupMembers.setSeparatorVisibility(View.GONE); +cometchatGroupMembers.setToolbarVisibility(View.GONE); +``` + + - @Override - public void bindView(Context context, View view, GroupMember groupMember, Group group, RecyclerView.ViewHolder viewHolder, List list, int i) { +### Admins-only list - } -}); + + +```kotlin lines +val builder = GroupMembersRequest.GroupMembersRequestBuilder("GROUP_ID") + .setScopes(listOf("admin")) +cometchatGroupMembers.setGroupMembersRequestBuilder(builder) ``` - - -```kotlin -cometchatGroupMembers.setTrailingView(object : GroupMembersViewHolderListeners() { - override fun createView(context: Context, cometChatListItem: CometchatGroupMemberListItemBinding?): View? { - return null - } + +```java lines +GroupMembersRequest.GroupMembersRequestBuilder builder = new GroupMembersRequest.GroupMembersRequestBuilder("GROUP_ID") + .setScopes(Arrays.asList("admin")); +cometchatGroupMembers.setGroupMembersRequestBuilder(builder); +``` + + - override fun bindView( - context: Context, - view: View, - groupMember: GroupMember, - group: Group, - viewHolder: RecyclerView.ViewHolder, - list: List, - i: Int - ) { +### Exclude group owner - } -}) + + +```kotlin lines +cometchatGroupMembers.excludeOwner(true) ``` - + +```java lines +cometchatGroupMembers.excludeOwner(true); +``` + -**Example** - - - - +### Hide kick/ban/scope options -You can indeed create a custom layout file named `tail_view_layout.xml` for more complex or unique list items. + + +```kotlin lines +cometchatGroupMembers.setKickMemberOptionVisibility(View.GONE) +cometchatGroupMembers.setBanMemberOptionVisibility(View.GONE) +cometchatGroupMembers.setScopeChangeOptionVisibility(View.GONE) +``` + -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: + +```java lines +cometchatGroupMembers.setKickMemberOptionVisibility(View.GONE); +cometchatGroupMembers.setBanMemberOptionVisibility(View.GONE); +cometchatGroupMembers.setScopeChangeOptionVisibility(View.GONE); +``` + + -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: +## Advanced Methods -```xml custom_tail_view.xml - - +### Programmatic Selection - +#### `selectGroupMember` - +Programmatically selects or deselects a group member. Works with both `SINGLE` and `MULTIPLE` selection modes. - + + +```kotlin lines +// Select a member in single-select mode +cometchatGroupMembers.selectGroupMember(groupMember, UIKitConstants.SelectionMode.SINGLE) - +// Select a member in multi-select mode +cometchatGroupMembers.selectGroupMember(groupMember, UIKitConstants.SelectionMode.MULTIPLE) ``` + - -```java YourActivity.java -cometchatGroupMembers.setTrailingView(new GroupMembersViewHolderListeners() { - @Override - public View createView(Context context, CometchatGroupMemberListItemBinding listItem) { - return View.inflate(context, R.layout.custom_tail_view, null); - } - - @Override - public void bindView(Context context, View createdView, GroupMember groupMember, Group group, RecyclerView.ViewHolder holder, List groupMemberList, int position) { - MaterialCardView cardView = createdView.findViewById(R.id.scope_card); - TextView tvName = createdView.findViewById(R.id.tv_scope); - cardView.setCardBackgroundColor(CometChatTheme.getExtendedPrimaryColor100(context)); - tvName.setText(groupMember.getScope()); - createdView.setVisibility(groupMember.getScope().equals(UIKitConstants.GroupMemberScope.PARTICIPANTS) ? View.VISIBLE : View.GONE); - } - }); -``` +```java lines +// Select a member in single-select mode +cometchatGroupMembers.selectGroupMember(groupMember, UIKitConstants.SelectionMode.SINGLE); +// Select a member in multi-select mode +cometchatGroupMembers.selectGroupMember(groupMember, UIKitConstants.SelectionMode.MULTIPLE); +``` + + +> In `SINGLE` mode, selecting a new member replaces the previous selection. In `MULTIPLE` mode, calling this on an already-selected member deselects it (toggle behavior). + +#### `getSelectedGroupMembers` +Returns the list of currently selected `GroupMember` objects. + + -```kotlin YourActivity.kt -cometchatGroupMembers.setTrailingView(object : - GroupMembersViewHolderListeners() { - override fun createView( - context: Context?, - listItem: CometchatGroupMemberListItemBinding? - ): View { - return View.inflate(context, R.layout.custom_tail_view, null) - } - - override fun bindView( - context: Context, - createdView: View, - groupMember: GroupMember, - group: Group, - holder: RecyclerView.ViewHolder, - groupMemberList: List, - position: Int - ) { - val cardView = createdView.findViewById(R.id.scope_card) - val tvName = createdView.findViewById(R.id.tv_scope) - cardView.setCardBackgroundColor(CometChatTheme.getExtendedPrimaryColor100(context)) - tvName.text = groupMember.scope - createdView.visibility = - if (groupMember.scope == UIKitConstants.GroupMemberScope.PARTICIPANTS) View.VISIBLE else View.GONE - } - }) +```kotlin lines +val selected = cometchatGroupMembers.selectedGroupMembers ``` - + +```java lines +List selected = cometchatGroupMembers.getSelectedGroupMembers(); +``` + -#### setOverflowMenu +### Selected Group Members List -Allows customization of the overflow menu (three-dot ⋮ icon) with additional options. +When using multi-select mode, a horizontal list of selected group members can be shown above the main list. -Use Cases: +| Method | Type | Description | +| --- | --- | --- | +| `setSelectedGroupMembersListVisibility` | `int (View.VISIBLE / View.GONE)` | Show or hide the selected members strip | +| `setSelectedGroupMemberAvatarStyle` | `@StyleRes int` | Avatar style for selected member chips | +| `setSelectedGroupMemberItemTextColor` | `@ColorInt int` | Text color for selected member names | +| `setSelectedGroupMemberItemTextAppearance` | `@StyleRes int` | Text appearance for selected member names | +| `setSelectedGroupMemberItemRemoveIcon` | `Drawable` | Icon for the remove button on each chip | +| `setSelectedGroupMemberItemRemoveIconTint` | `@ColorInt int` | Tint color for the remove icon | -* Add extra actions like "Report Member", "Restrict from Posting". -* Provide group admins with moderation options. +### Search Input Customization - - -```java -cometchatGroupMembers.setOverflowMenu(v); -``` +The built-in search box can be customized programmatically: - +| Method | Type | Description | +| --- | --- | --- | +| `setSearchInputTextColor` | `@ColorInt int` | Text color of the search input | +| `setSearchInputPlaceHolderTextColor` | `@ColorInt int` | Placeholder text color | +| `setSearchInputIcon` | `Drawable` | Leading icon in the search box | +| `setSearchInputIconTint` | `@ColorInt int` | Tint for the leading icon | +| `setSearchInputEndIcon` | `Drawable` | Trailing icon in the search box | +| `setSearchInputEndIconTint` | `@ColorInt int` | Tint for the trailing icon | +| `setSearchInputStrokeWidth` | `@Dimension int` | Stroke width of the search box border | +| `setSearchInputStrokeColor` | `@ColorInt int` | Stroke color of the search box border | +| `setSearchInputBackgroundColor` | `@ColorInt int` | Background color of the search box | +| `setSearchInputCornerRadius` | `@Dimension int` | Corner radius of the search box | +| `setSearchInputTextAppearance` | `@StyleRes int` | Text appearance of the search input | - -```kotlin -cometchatGroupMembers.setOverflowMenu(v) -``` +### Internal Access - +These methods provide direct access to internal components for advanced use cases. - +| Method | Returns | Description | +| --- | --- | --- | +| `getBinding()` | `CometchatGroupMembersListViewBinding` | The ViewBinding for the component's root layout | +| `getViewModel()` | `GroupMembersViewModel` | The ViewModel managing group member data and state | +| `getAdapter()` | `GroupMembersAdapter` | The adapter powering the RecyclerView | +| `setAdapter(GroupMembersAdapter)` | `void` | Replaces the default adapter with a custom one | +| `getRecyclerView()` | `RecyclerView` | The RecyclerView displaying the member list | + +> Use these only when the standard API is insufficient. Directly manipulating the adapter or ViewModel may conflict with the component's internal state management. + +## Style -Example: +The component uses XML theme styles. Define a custom style with parent `CometChatGroupMembersStyle` in `themes.xml`, then apply with `setStyle()`. - + - - -```java -ImageView addMemberIv = new ImageView(this); -addMemberIv.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_add, null)); -cometchatGroupMembers.setOverflowMenu(addMemberIv); -``` +```xml themes.xml lines + - + +``` + -```kotlin -val addMemberIv = ImageView(this) -addMemberIv.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_add, null)) -cometchatGroupMembers.setOverflowMenu(addMemberIv) +```kotlin lines +cometchatGroupMembers.setStyle(R.style.CustomGroupMembersStyle) ``` - + +```java lines +cometchatGroupMembers.setStyle(R.style.CustomGroupMembersStyle); +``` + + +> **What this does:** Applies the `CustomGroupMembersStyle` theme to the `CometChatGroupMembers` component, changing the avatar, separator, title text, and back icon appearance. + +To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_group_members.xml). + +### Programmatic Style Properties + +In addition to XML theme styles, the component exposes programmatic setters for fine-grained control: + +| Method | Type | Description | +| --- | --- | --- | +| `setBackgroundColor` | `@ColorInt int` | Background color of the component | +| `setBackIconTint` | `@ColorInt int` | Tint color for the back icon | +| `setBackIcon` | `Drawable` | Custom back icon drawable | +| `setTitleTextColor` | `@ColorInt int` | Title text color in the toolbar | +| `setTitleTextAppearance` | `@StyleRes int` | Title text appearance in the toolbar | +| `setItemTitleTextColor` | `@ColorInt int` | Text color for member item titles | +| `setItemTitleTextAppearance` | `@StyleRes int` | Text appearance for member item titles | +| `setSeparatorColor` | `@ColorInt int` | Color of list item separators | +| `setSeparatorHeight` | `@Dimension int` | Height of list item separators | +| `setCornerRadius` | `@Dimension int` | Corner radius of the component | +| `setEmptyStateTitleTextColor` | `@ColorInt int` | Title text color for the empty state | +| `setEmptyStateTitleTextAppearance` | `@StyleRes int` | Title text appearance for the empty state | +| `setEmptyStateSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the empty state | +| `setEmptyStateSubtitleTextAppearance` | `@StyleRes int` | Subtitle text appearance for the empty state | +| `setErrorStateTitleTextColor` | `@ColorInt int` | Title text color for the error state | +| `setErrorStateTitleTextAppearance` | `@StyleRes int` | Title text appearance for the error state | +| `setErrorStateSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the error state | +| `setErrorStateSubtitleTextAppearance` | `@StyleRes int` | Subtitle text appearance for the error state | +| `setAvatarStyle` | `@StyleRes int` | Style for member avatars | +| `setStatusIndicatorStyle` | `@StyleRes int` | Style for online/offline status indicators | + +### Checkbox Style Properties (Selection Mode) + +When using `SINGLE` or `MULTIPLE` selection mode, checkboxes appear on each item: + +| Method | Type | Description | +| --- | --- | --- | +| `setCheckBoxStrokeWidth` | `@Dimension int` | Stroke width of the checkbox border | +| `setCheckBoxCornerRadius` | `@Dimension int` | Corner radius of the checkbox | +| `setCheckBoxStrokeColor` | `@ColorInt int` | Stroke color of the checkbox border | +| `setCheckBoxBackgroundColor` | `@ColorInt int` | Background color of unchecked checkbox | +| `setCheckBoxCheckedBackgroundColor` | `@ColorInt int` | Background color of checked checkbox | +| `setSelectIcon` | `Drawable` | Icon shown when checkbox is checked | +| `setSelectIconTint` | `@ColorInt int` | Tint for the checkbox select icon | +| `setDiscardSelectionIcon` | `Drawable` | Icon for the discard selection button | +| `setDiscardSelectionIconTint` | `@ColorInt int` | Tint for the discard selection icon | +| `setSubmitSelectionIcon` | `Drawable` | Icon for the submit selection button | +| `setSubmitSelectionIconTint` | `@ColorInt int` | Tint for the submit selection icon | + +## Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on member interaction | Activity/Fragment | `setOn` callbacks | `setOnItemClick((v, pos, m) -> { ... })` | +| Filter which members appear | Activity/Fragment | `setGroupMembersRequestBuilder` | `setGroupMembersRequestBuilder(builder)` | +| Customize search results | Activity/Fragment | `setSearchRequestBuilder` | `setSearchRequestBuilder(builder)` | +| Toggle visibility of UI elements | Activity/Fragment | `setVisibility(int)` | `setUserStatusVisibility(View.GONE)` | +| Replace a section of the list item | Activity/Fragment | `setView` | `setLeadingView(listener)` | +| Change colors, fonts, spacing | `themes.xml` | `CometChatGroupMembersStyle` | `#F76808` | +| Avatar style (corner radius, background) | `themes.xml` | `cometchatGroupMembersAvatarStyle` | `8dp` | +| Apply a custom style | Activity/Fragment | `setStyle(int styleRes)` | `cometchatGroupMembers.setStyle(R.style.CustomGroupMembersStyle);` | +| Set the group | Activity/Fragment | `setGroup(Group)` | `.setGroup(group);` | +| Back button visibility | Activity/Fragment | `setBackIconVisibility(int)` | `.setBackIconVisibility(View.VISIBLE);` | +| Toolbar visibility | Activity/Fragment | `setToolbarVisibility(int)` | `.setToolbarVisibility(View.GONE);` | +| Error state visibility | Activity/Fragment | `setErrorStateVisibility(int)` | `.setErrorStateVisibility(View.GONE);` | +| Empty state visibility | Activity/Fragment | `setEmptyStateVisibility(int)` | `.setEmptyStateVisibility(View.GONE);` | +| Loading state visibility | Activity/Fragment | `setLoadingStateVisibility(int)` | `.setLoadingStateVisibility(View.GONE);` | +| Separator visibility | Activity/Fragment | `setSeparatorVisibility(int)` | `.setSeparatorVisibility(View.GONE);` | +| User online status visibility | Activity/Fragment | `setUserStatusVisibility(int)` | `.setUserStatusVisibility(View.GONE);` | +| Selection mode (single/multiple) | Activity/Fragment | `setSelectionMode(SelectionMode)` | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | +| Search keyword | Activity/Fragment | `setSearchKeyword(String)` | `.setSearchKeyword("anything");` | +| Search box visibility | Activity/Fragment | `setSearchBoxVisibility(int)` | `.setSearchBoxVisibility(View.GONE);` | +| Custom toolbar title | Activity/Fragment | `setTitleText(String)` | `.setTitleText("Members");` | +| Long-press options (replace) | Activity/Fragment | `setOptions(Function3)` | See `setOptions` code above | +| Long-press options (append) | Activity/Fragment | `addOptions(Function3)` | See `addOptions` code above | +| Loading view | Activity/Fragment | `setLoadingStateView(int)` | `.setLoadingStateView(R.layout.your_loading_view);` | +| Empty view | Activity/Fragment | `setEmptyStateView(int)` | `.setEmptyStateView(R.layout.your_empty_view);` | +| Error view | Activity/Fragment | `setErrorStateView(int)` | `.setErrorStateView(R.layout.your_error_view);` | +| Leading view (avatar area) | Activity/Fragment | `setLeadingView(GroupMembersViewHolderListeners)` | See `setLeadingView` code above | +| Title view | Activity/Fragment | `setTitleView(GroupMembersViewHolderListeners)` | See `setTitleView` code above | +| Subtitle view | Activity/Fragment | `setSubtitleView(GroupMembersViewHolderListeners)` | See `setSubtitleView` code above | +| Trailing view | Activity/Fragment | `setTrailingView(GroupMembersViewHolderListeners)` | See `setTrailingView` code above | +| Entire list item | Activity/Fragment | `setItemView(GroupMembersViewHolderListeners)` | See `setItemView` code above | +| Overflow menu | Activity/Fragment | `setOverflowMenu(View)` | `cometchatGroupMembers.setOverflowMenu(view);` | +| Kick member option visibility | Activity/Fragment | `setKickMemberOptionVisibility(int)` | `.setKickMemberOptionVisibility(View.GONE);` | +| Ban member option visibility | Activity/Fragment | `setBanMemberOptionVisibility(int)` | `.setBanMemberOptionVisibility(View.GONE);` | +| Scope change option visibility | Activity/Fragment | `setScopeChangeOptionVisibility(int)` | `.setScopeChangeOptionVisibility(View.GONE);` | +| Exclude group owner | Activity/Fragment | `excludeOwner(boolean)` | `.excludeOwner(true);` | +| Programmatic selection | Activity/Fragment | `selectGroupMember(GroupMember, SelectionMode)` | `.selectGroupMember(member, SelectionMode.SINGLE);` | +| Selected members strip | Activity/Fragment | `setSelectedGroupMembersListVisibility(int)` | `.setSelectedGroupMembersListVisibility(View.VISIBLE);` | +| Internal adapter access | Activity/Fragment | `getAdapter()` / `setAdapter()` | Advanced use only | + +## Accessibility + +The component renders a scrollable `RecyclerView` of interactive group member items. Each member row responds to tap and long-press gestures. Avatar images include the member name as content description. + +For custom views provided via `setLeadingView`, `setTitleView`, `setTrailingView`, or `setItemView`, ensure you set `android:contentDescription` on visual-only elements so TalkBack can announce them. The default views handle this automatically. + +Online/offline status dots are visual-only by default. If screen reader descriptions are needed, provide them via a custom view with appropriate `contentDescription` attributes. Scope badges (admin, moderator, participant) should also include content descriptions when using custom trailing views. + +## Next Steps + + + + Browse and search available groups + + + Browse and search available users + + + Browse recent conversations + + + Display messages in a conversation + + \ No newline at end of file diff --git a/ui-kit/android/groups.mdx b/ui-kit/android/groups.mdx index e9ae37801..09074400b 100644 --- a/ui-kit/android/groups.mdx +++ b/ui-kit/android/groups.mdx @@ -1,386 +1,526 @@ --- title: "Groups" +description: "Scrollable list of all available groups with search, avatars, names, and group type indicators." --- + + +```json +{ + "component": "CometChatGroups", + "package": "com.cometchat.chatuikit.groups", + "xmlElement": "", + "description": "Scrollable list of all available groups with search, avatars, names, and group type indicators (public, private, password-protected).", + "primaryOutput": { + "method": "setOnItemClick", + "type": "OnItemClick" + }, + "methods": { + "data": { + "setGroupsRequestBuilder": { + "type": "GroupsRequest.GroupsRequestBuilder", + "default": "SDK default", + "note": "Pass the builder, not the result of .build()" + }, + "setSearchRequestBuilder": { + "type": "GroupsRequest.GroupsRequestBuilder", + "default": "Same as main builder", + "note": "Separate builder for search results" + } + }, + "callbacks": { + "setOnItemClick": "OnItemClick", + "setOnItemLongClick": "OnItemLongClick", + "setOnBackPressListener": "OnBackPress", + "setOnSelection": "OnSelection", + "setOnError": "OnError", + "setOnLoad": "OnLoad", + "setOnEmpty": "OnEmpty" + }, + "visibility": { + "setBackIconVisibility": { "type": "int (View.VISIBLE | View.GONE)", "default": "View.GONE" }, + "setToolbarVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setLoadingStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setErrorStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setEmptyStateVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setSeparatorVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setGroupTypeVisibility": { "type": "int", "default": "View.VISIBLE" }, + "setSearchBoxVisibility": { "type": "int", "default": "View.VISIBLE" } + }, + "selection": { + "setSelectionMode": { + "type": "UIKitConstants.SelectionMode", + "values": ["NONE", "SINGLE", "MULTIPLE"], + "default": "NONE" + } + }, + "viewSlots": { + "setItemView": "GroupsViewHolderListener — entire list item row", + "setLeadingView": "GroupsViewHolderListener — avatar / left section", + "setTitleView": "GroupsViewHolderListener — name / title text", + "setSubtitleView": "GroupsViewHolderListener — subtitle text below name", + "setTrailingView": "GroupsViewHolderListener — right section", + "setLoadingView": "@LayoutRes int — loading spinner", + "setEmptyView": "@LayoutRes int — empty state", + "setErrorView": "@LayoutRes int — error state", + "setOverflowMenu": "View — toolbar menu", + "setOptions": "Function2> — long-press context menu (replaces defaults)", + "addOptions": "Function2> — long-press context menu (appends to defaults)" + }, + "advanced": { + "selectGroup": "Group, SelectionMode — programmatic selection", + "clearSelection": "void — clears all selected groups", + "getSelectedGroups": "List — returns selected items", + "setSearchKeyword": "String — programmatic search", + "setTitleText": "String — custom toolbar title", + "setSearchPlaceholderText": "String — search placeholder", + "getBinding": "CometchatGroupListBinding — root ViewBinding", + "getViewModel": "GroupsViewModel — internal ViewModel access", + "getAdapter": "GroupsAdapter — internal adapter access", + "setAdapter": "GroupsAdapter — replace the default adapter" + }, + "style": { + "setStyle": { + "type": "@StyleRes int", + "parent": "CometChatGroupsStyle" + } + } + }, + "events": [ + { + "name": "CometChatGroupEvents.ccGroupCreated", + "payload": "Group", + "description": "Logged-in user created a group" + }, + { + "name": "CometChatGroupEvents.ccGroupDeleted", + "payload": "Group", + "description": "Logged-in user deleted a group" + }, + { + "name": "CometChatGroupEvents.ccGroupLeft", + "payload": "Action, User, Group", + "description": "Logged-in user left a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberJoined", + "payload": "User, Group", + "description": "Logged-in user joined a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberAdded", + "payload": "List, List, Group, User", + "description": "Logged-in user added members to a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberKicked", + "payload": "Action, User, User, Group", + "description": "Logged-in user kicked a member from a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberBanned", + "payload": "Action, User, User, Group", + "description": "Logged-in user banned a member from a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberUnBanned", + "payload": "Action, User, User, Group", + "description": "Logged-in user unbanned a member from a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberScopeChanged", + "payload": "Action, User, String, String, Group", + "description": "Logged-in user changed a member's scope" + }, + { + "name": "CometChatGroupEvents.ccOwnershipChanged", + "payload": "Group, GroupMember", + "description": "Logged-in user transferred group ownership" + } + ], + "sdkListeners": [ + "onGroupMemberJoined", + "onGroupMemberLeft", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onGroupMemberUnbanned", + "onGroupMemberScopeChanged", + "onMemberAddedToGroup" + ] +} +``` -## Overview + -`CometChatGroups` functions as a standalone [component](/ui-kit/android/components-overview#components) designed to create a screen displaying a list of groups, with the added functionality of enabling groups to search for specific groups. Acting as a container component, CometChatGroups encapsulates and formats the `CometChatListBase` and `CometChatGroupList` components without introducing any additional behavior of its own. +## Where It Fits - - - +`CometChatGroups` is a list component. It renders all available groups and emits the selected `Group` via `setOnItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a group messaging layout. + + + +```kotlin ChatActivity.kt lines +class ChatActivity : AppCompatActivity() { + + private lateinit var groups: CometChatGroups + private lateinit var messageHeader: CometChatMessageHeader + private lateinit var messageList: CometChatMessageList + private lateinit var messageComposer: CometChatMessageComposer + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_chat) + + groups = findViewById(R.id.groups) + messageHeader = findViewById(R.id.message_header) + messageList = findViewById(R.id.message_list) + messageComposer = findViewById(R.id.message_composer) + + groups.setOnItemClick { view, position, group -> + messageHeader.setGroup(group) + messageList.setGroup(group) + messageComposer.setGroup(group) + } + } +} +``` + -*** + +```java ChatActivity.java lines +public class ChatActivity extends AppCompatActivity { -## Usage + private CometChatGroups groups; + private CometChatMessageHeader messageHeader; + private CometChatMessageList messageList; + private CometChatMessageComposer messageComposer; -*** + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat); + + groups = findViewById(R.id.groups); + messageHeader = findViewById(R.id.message_header); + messageList = findViewById(R.id.message_list); + messageComposer = findViewById(R.id.message_composer); + + groups.setOnItemClick((view, position, group) -> { + messageHeader.setGroup(group); + messageList.setGroup(group); + messageComposer.setGroup(group); + }); + } +} +``` + + -### Integration +## Quick Start -The following code snippet illustrates how you can can launch `CometChatGroups`. +Add the component to your layout XML: - - -```xml +```xml layout_activity.xml lines ``` - - - - -*** - -### Actions - -[Actions](/ui-kit/android/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and Group-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. + + + -##### setOnItemClick +Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()`, a user logged in, and the `cometchat-chat-uikit-android` dependency added. -Function invoked when a Group item is clicked, typically used to open a Group profile or chat screen. +To add programmatically in an Activity: - -```java YourActivity.java -cometchatGroups.setOnItemClick((view1, position, group) -> { - - }); + +```kotlin YourActivity.kt lines +override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(CometChatGroups(this)) +} ``` - - -```kotlin YourActivity.kt -cometchatGroups.onItemClick = OnItemClick { view, position, group -> - - } + +```java YourActivity.java lines +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(new CometChatGroups(this)); +} ``` - - -*** - -##### setOnItemLongClick - -Function executed when a Group item is long-pressed, allowing additional actions like delete or block. +Or in a Fragment: - -```java YourActivity.java -cometchatGroups.setOnItemLongClick((view1, position, group) -> { - - }); + +```kotlin YourFragment.kt lines +override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return CometChatGroups(requireContext()) +} ``` - - -```kotlin YourActivity.kt -cometchatGroups.onItemLongClick = OnItemLongClick({ view, position, group -> - - }) + +```java YourFragment.java lines +@Override +public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return new CometChatGroups(getContext()); +} ``` - - -*** +## Filtering Groups -##### setOnBackPressListener - -`OnBackPressListener` is triggered when you press the back button in the app bar. It has a predefined behavior; when clicked, it navigates to the previous activity. However, you can override this action using the following code snippet. +Pass a `GroupsRequest.GroupsRequestBuilder` to `setGroupsRequestBuilder`. Pass the builder instance — not the result of `.build()`. - -```java YourActivity.java -cometchatGroups.setOnBackPressListener(() -> { - - }); + +```kotlin lines +val builder = GroupsRequestBuilder() + .setLimit(10) + .joinedOnly(true) +cometchatGroups.setGroupsRequestBuilder(builder) ``` - - -```kotlin YourActivity.kt -cometchatGroups.onBackPressListener = OnBackPress { - - } + +```java lines +GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder() + .setLimit(10) + .joinedOnly(true); +cometchatGroups.setGroupsRequestBuilder(builder); ``` - - -*** - -##### setOnSelect +### Filter Recipes -Called when a item from the fetched list is selected, useful for multi-selection features. +| Recipe | Code | +| --- | --- | +| Joined only | `builder.joinedOnly(true)` | +| Limit to 10 per page | `builder.setLimit(10)` | +| Search by keyword | `builder.setSearchKeyWord("design")` | +| Filter by tags | `builder.setTags(Arrays.asList("vip"))` | +| With tags | `builder.withTags(true)` | - - -```java YourActivity.java -cometchatGroups.setOnSelect(t -> { +> The component uses infinite scroll — the next page loads as the user scrolls to the bottom. Refer to [GroupsRequestBuilder](/sdk/android/retrieve-groups) for the full builder API. - }); -``` +### Search Request Builder - +Use `setSearchRequestBuilder` to customize the search list separately from the main list: + -```kotlin YourActivity.kt -cometchatGroups.setOnSelect(object : OnSelection { - override fun onSelection(t: MutableList?) { - - } - }) +```kotlin lines +val searchBuilder = GroupsRequestBuilder() + .setLimit(10) + .setSearchKeyWord("**") +cometchatGroups.setSearchRequestBuilder(searchBuilder) ``` - + +```java lines +GroupsRequest.GroupsRequestBuilder searchBuilder = new GroupsRequest.GroupsRequestBuilder() + .setLimit(10) + .setSearchKeyWord("**"); +cometchatGroups.setSearchRequestBuilder(searchBuilder); +``` + -*** +## Actions and Events -##### OnError +### Callback Methods -This action doesn't change the behavior of the component but rather listens for any errors that occur in the groups component. +#### `setOnItemClick` - - -```java YourActivity.java -cometchatGroups.setOnError(cometchatException -> { +Fires when a group row is tapped. Primary navigation hook — set the active group and render the message view. - }); + + +```kotlin YourActivity.kt lines +cometchatGroups.onItemClick = OnItemClick { view, position, group -> + +} ``` - - -```kotlin YourActivity.kt -cometchatGroups.setOnError { - - } + +```java YourActivity.java lines +cometchatGroups.setOnItemClick((view1, position, group) -> { + +}); ``` - - -*** +> **What this does:** Replaces the default item-click behavior. When a user taps a group, your custom lambda executes instead of the built-in navigation. -##### setOnLoad +#### `setOnItemLongClick` -Invoked when the list is successfully fetched and loaded, helping track component readiness. +Fires when a group row is long-pressed. Use for additional actions like delete or leave. - -```java YourActivity.java -cometchatGroups.setOnLoad(list -> { - -}); + +```kotlin YourActivity.kt lines +cometchatGroups.onItemLongClick = OnItemLongClick({ view, position, group -> + +}) ``` - - -```kotlin YourActivity.kt -cometchatGroups.setOnLoad(object : OnLoad { - override fun onLoad(list: MutableList?) { + +```java YourActivity.java lines +cometchatGroups.setOnItemLongClick((view1, position, group) -> { - } -}) +}); ``` - - -*** - -##### setOnEmpty +#### `setOnBackPressListener` -Called when the list is empty, enabling custom handling such as showing a placeholder message. +Fires when the user presses the back button in the app bar. Default: navigates to the previous activity. - -```java YourActivity.java -cometchatGroups.setOnEmpty(() -> { - - }); -``` + +```kotlin YourActivity.kt lines +cometchatGroups.onBackPressListener = OnBackPress { +} +``` - -```kotlin YourActivity.kt -cometchatGroups.setOnEmpty{ + +```java YourActivity.java lines +cometchatGroups.setOnBackPressListener(() -> { - } +}); ``` - - -*** - -### Filters +#### `setOnSelection` -Filters allow you to customize the data displayed in a list within a Component. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using RequestBuilders of Chat SDK. - -##### 1. GroupsRequestBuilder - -The [GroupsRequestBuilder](/sdk/android/retrieve-groups) enables you to filter and customize the group list based on available parameters in GroupsRequestBuilder. This feature allows you to create more specific and targeted queries when fetching groups. The following are the parameters available in [GroupsRequestBuilder](/sdk/android/retrieve-groups) - -| Property | Description | Code | -| ------------------ | ------------------------------------------------------------------------------------------------------------------- | --------------------------- | -| **Limit** | Configure the maximum number of groups to fetch in a single request, optimizing pagination for smoother navigation. | `.setLimit(Int)` | -| **Search Keyword** | Employed to retrieve groups that match the provided string, facilitating precise searches. | `.setSearchKeyWord(String)` | -| **Joined Only** | Exclusively fetches joined groups. | `.joinedOnly(boolean)` | -| **Tags** | Utilized to fetch groups containing the specified tags. | `.setTags(List)` | -| **With Tags** | Utilized to retrieve groups with specific tags. | `.withTags(boolean)` | - -**Example** - -In the example below, we are applying a filter to the Group List based on only joined groups. +Fires when a group is checked/unchecked in multi-select mode. Requires `setSelectionMode` to be set. - -```java -GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder().setLimit(10).joinedOnly(true); -cometchatGroups.setGroupsRequestBuilder(builder); + +```kotlin YourActivity.kt lines +cometchatGroups.setOnSelection(object : OnSelection { + override fun onSelection(t: MutableList?) { + + } +}) ``` - - -```kotlin -val builder = GroupsRequestBuilder().setLimit(10).joinedOnly(true) -cometchatGroups.setGroupsRequestBuilder(builder) -``` + +```java YourActivity.java lines +cometchatGroups.setOnSelection(t -> { +}); +``` - -*** - -##### 2. SearchRequestBuilder +#### `setOnError` -The SearchRequestBuilder uses [GroupsRequestBuilder](/sdk/android/retrieve-groups) enables you to filter and customize the search list based on available parameters in GroupsRequestBuilder. This feature allows you to keep uniformity between the displayed Groups List and searched Group List. - -**Example** +Fires on internal errors (network failure, auth issue, SDK exception). - -```java -GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder().setLimit(10).setSearchKeyWord("**"); -cometchatGroups.setSearchRequestBuilder(builder); -``` + +```kotlin YourActivity.kt lines +cometchatGroups.setOnError { +} +``` - -```kotlin -val builder = GroupsRequestBuilder().setLimit(10).setSearchKeyWord("**") -cometchatGroups.setSearchRequestBuilder(builder) -``` + +```java YourActivity.java lines +cometchatGroups.setOnError(cometchatException -> { +}); +``` - -*** - -### Events - -[Events](/ui-kit/android/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +#### `setOnLoad` -The list of events emitted by the Groups component is as follows. - -| Events | Description | -| ----------------------------- | ---------------------------------------------------------------------------------------------------------- | -| `ccGroupCreated()` | This will get triggered when the logged in user creates a group | -| `ccGroupDeleted()` | This will get triggered when the logged in user deletes a group | -| `ccGroupLeft()` | This will get triggered when the logged in user leaves a group | -| `ccGroupMemberScopeChanged()` | This will get triggered when the logged in user changes the scope of another group member | -| `ccGroupMemberBanned()` | This will get triggered when the logged in user bans a group member from the group | -| `ccGroupMemberKicked()` | This will get triggered when the logged in user kicks another group member from the group | -| `ccGroupMemberUnbanned()` | This will get triggered when the logged in user unbans a user banned from the group | -| `ccGroupMemberJoined()` | This will get triggered when the logged in user joins a group | -| `ccGroupMemberAdded()` | This will get triggered when the logged in user add new members to the group | -| `ccOwnershipChanged` | This will get triggered when the logged in user transfer the ownership of their group to some other member | - -##### 1. Add `CometChatGroupEvents` Listener's +Fires when the list is successfully fetched and loaded. - -```java -CometChatGroupEvents.addGroupListener("LISTENER_TAG", new CometChatGroupEvents() { - @Override - public void ccGroupCreated(Group group) { - super.ccGroupCreated(group); - } - - @Override - public void ccGroupDeleted(Group group) { - super.ccGroupDeleted(group); - } - - @Override - public void ccGroupLeft(Action actionMessage, User leftUser, Group leftGroup) { - super.ccGroupLeft(actionMessage, leftUser, leftGroup); - } + +```kotlin YourActivity.kt lines +cometchatGroups.setOnLoad(object : OnLoad { + override fun onLoad(list: MutableList?) { - @Override - public void ccGroupMemberJoined(User joinedUser, Group joinedGroup) { - super.ccGroupMemberJoined(joinedUser, joinedGroup); } +}) +``` + - @Override - public void ccGroupMemberAdded(List actionMessages, List usersAdded, Group userAddedIn, User addedBy) { - super.ccGroupMemberAdded(actionMessages, usersAdded, userAddedIn, addedBy); - } + +```java YourActivity.java lines +cometchatGroups.setOnLoad(list -> { - @Override - public void ccGroupMemberKicked(Action actionMessage, User kickedUser, User kickedBy, Group kickedFrom) { - super.ccGroupMemberKicked(actionMessage, kickedUser, kickedBy, kickedFrom); - } +}); +``` + + - @Override - public void ccGroupMemberBanned(Action actionMessage, User bannedUser, User bannedBy, Group bannedFrom) { - super.ccGroupMemberBanned(actionMessage, bannedUser, bannedBy, bannedFrom); - } +#### `setOnEmpty` - @Override - public void ccGroupMemberUnBanned(Action actionMessage, User unbannedUser, User unBannedBy, Group unBannedFrom) { - super.ccGroupMemberUnBanned(actionMessage, unbannedUser, unBannedBy, unBannedFrom); - } +Fires when the list is empty, enabling custom handling such as showing a placeholder. - @Override - public void ccGroupMemberScopeChanged(Action actionMessage, User updatedUser, String scopeChangedTo, String scopeChangedFrom, Group group) { - super.ccGroupMemberScopeChanged(actionMessage, updatedUser, scopeChangedTo, scopeChangedFrom, group); - } + + +```kotlin YourActivity.kt lines +cometchatGroups.setOnEmpty { + +} +``` + - @Override - public void ccOwnershipChanged(Group group, GroupMember newOwner) { - super.ccOwnershipChanged(group, newOwner); - } + +```java YourActivity.java lines +cometchatGroups.setOnEmpty(() -> { + }); ``` - + +- **Verify**: After setting an action callback, trigger the corresponding user interaction (tap, long-press, back, select) and confirm your custom logic executes instead of the default behavior. + +### Global UI Events + +`CometChatGroupEvents` emits events subscribable from anywhere in the application. Add a listener and remove it when no longer needed. + +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccGroupCreated` | The logged-in user creates a group | `Group` | +| `ccGroupDeleted` | The logged-in user deletes a group | `Group` | +| `ccGroupLeft` | The logged-in user leaves a group | `Action, User, Group` | +| `ccGroupMemberJoined` | The logged-in user joins a group | `User, Group` | +| `ccGroupMemberAdded` | The logged-in user adds members to a group | `List, List, Group, User` | +| `ccGroupMemberKicked` | The logged-in user kicks a member | `Action, User, User, Group` | +| `ccGroupMemberBanned` | The logged-in user bans a member | `Action, User, User, Group` | +| `ccGroupMemberUnBanned` | The logged-in user unbans a member | `Action, User, User, Group` | +| `ccGroupMemberScopeChanged` | The logged-in user changes a member's scope | `Action, User, String, String, Group` | +| `ccOwnershipChanged` | The logged-in user transfers group ownership | `Group, GroupMember` | + + -```kotlin +```kotlin Add Listener lines CometChatGroupEvents.addGroupListener("LISTENER_TAG", object : CometChatGroupEvents() { override fun ccGroupCreated(group: Group?) { super.ccGroupCreated(group) @@ -456,299 +596,188 @@ CometChatGroupEvents.addGroupListener("LISTENER_TAG", object : CometChatGroupEve }) ``` - - - +Remove Listener -*** - -##### 2. Removing `CometChatGroupEvents` Listener's - - - -```java -CometChatGroupEvents.removeListeners(); ``` - - - - -```kotlin CometChatGroupEvents.removeListeners() ``` - - - -*** - -## Customization - -To fit your app's design requirements, you can customize the appearance of the groups component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. - -### Style - -Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component. - - - - - -```html - - - -``` - - -```java -cometchatGroups.setStyle(R.style.CustomGroupsStyle); -``` - - - - -```kotlin -cometchatGroups.setStyle(R.style.CustomGroupsStyle) -``` - - - - - -*** - -To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_groups.xml). - -### Functionality - -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. - -Below is a list of customizations along with corresponding code snippets - -| Methods | Description | Code | -| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -| setBackIconVisibility | Used to toggle visibility for back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | -| setToolbarVisibility | Used to toggle visibility for back button in the app bar | `.setToolbarVisibility(View.GONE);` | -| setLoadingStateVisibility | Used to hide loading state while fetching groups | `.setLoadingStateVisibility(View.GONE);` | -| setErrorStateVisibility | Used to hide error state on fetching groups | `.setErrorStateVisibility(View.GONE);` | -| setEmptyStateVisibility | Used to hide empty state on fetching groups | `.setEmptyStateVisibility(View.GONE);` | -| setSeparatorVisibility | Used to control visibility of Separators in the list view | `.setSeparatorVisibility(View.GONE);` | -| setGroupTypeVisibility | Used to control visibility of status indicator shown for the group type | `.setGroupTypeVisibility(View.GONE);` | -| setSearchBoxVisibility | Used to hide search box shown in the tool bar | `.setSearchBoxVisibility(View.GONE);` | -| setSelectionMode | This method determines the selection mode for groups, enabling user to select either a single groups or multiple groups at once. | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | -| setSearchkeyword | Used for fetching groups matching the passed keywords | `.setSearchkeyword("anything");` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -#### setOptions - -Defines the available actions when users interact with a group item, such as long-pressing or swiping. - -Use Cases: - -* Enable actions like "Mute Notifications", "Leave Group", "Pin Group". -* Provide admin-only actions like "Manage Members", "Delete Group". - - - -```java -cometchatGroups.setOptions((context, group) -> Collections.emptyList()); -``` - - - - -```kotlin -cometchatGroups.options = Function2?> { context, Group -> emptyList() } -``` - - +```java Add Listener lines +CometChatGroupEvents.addGroupListener("LISTENER_TAG", new CometChatGroupEvents() { + @Override + public void ccGroupCreated(Group group) { + super.ccGroupCreated(group); + } - + @Override + public void ccGroupDeleted(Group group) { + super.ccGroupDeleted(group); + } -*** + @Override + public void ccGroupLeft(Action actionMessage, User leftUser, Group leftGroup) { + super.ccGroupLeft(actionMessage, leftUser, leftGroup); + } -#### addOptions + @Override + public void ccGroupMemberJoined(User joinedUser, Group joinedGroup) { + super.ccGroupMemberJoined(joinedUser, joinedGroup); + } -This method extends the existing set of actions available when Groups long press a Group item. Unlike setOptionsDefines, which replaces the default options, addOptionsAdds allows developers to append additional actions without removing the default ones. Example use cases include: + @Override + public void ccGroupMemberAdded(List actionMessages, List usersAdded, Group userAddedIn, User addedBy) { + super.ccGroupMemberAdded(actionMessages, usersAdded, userAddedIn, addedBy); + } -* Adding a "Report Spam" action -* Introducing a "Save to Notes" option -* Integrating third-party actions such as "Share to Cloud Storage" + @Override + public void ccGroupMemberKicked(Action actionMessage, User kickedUser, User kickedBy, Group kickedFrom) { + super.ccGroupMemberKicked(actionMessage, kickedUser, kickedBy, kickedFrom); + } -This method provides flexibility in modifying Group interaction capabilities. + @Override + public void ccGroupMemberBanned(Action actionMessage, User bannedUser, User bannedBy, Group bannedFrom) { + super.ccGroupMemberBanned(actionMessage, bannedUser, bannedBy, bannedFrom); + } - - -```java -cometchatGroups.addOptions((context, group) -> Collections.emptyList()); -``` + @Override + public void ccGroupMemberUnBanned(Action actionMessage, User unbannedUser, User unBannedBy, Group unBannedFrom) { + super.ccGroupMemberUnBanned(actionMessage, unbannedUser, unBannedBy, unBannedFrom); + } - + @Override + public void ccGroupMemberScopeChanged(Action actionMessage, User updatedUser, String scopeChangedTo, String scopeChangedFrom, Group group) { + super.ccGroupMemberScopeChanged(actionMessage, updatedUser, scopeChangedTo, scopeChangedFrom, group); + } - -```kotlin -cometchatGroups.addOptions { context, group -> emptyList() } + @Override + public void ccOwnershipChanged(Group group, GroupMember newOwner) { + super.ccOwnershipChanged(group, newOwner); + } +}); ``` - - - - -*** - -#### setLoadingView - -Configures a custom loading view displayed while groups are being fetched. - -Use Cases: +Remove Listener -* Show a spinner with "Loading groups..." text. -* Display a skeleton loader for a smooth UI experience. - - - -```java -cometchatGroups.setLoadingView(R.layout.your_loading_view); ``` - - - - -```kotlin -cometchatGroups.loadingView = R.layout.your_loading_view +CometChatGroupEvents.removeListeners(); ``` - - -*** - -#### setEmptyView - -Defines a view that appears when no groups are available. - -Use Cases: - -* Show a message like "No groups found, create one now!". -* Display an illustration with a "Create New Group" button. +### SDK Events (Real-Time, Automatic) + +The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required. + +| SDK Listener | Internal behavior | +| --- | --- | +| `onGroupMemberJoined` | Updates the group list when a member joins | +| `onGroupMemberLeft` | Updates the group list when a member leaves | +| `onGroupMemberKicked` | Updates the group list when a member is kicked | +| `onGroupMemberBanned` | Updates the group list when a member is banned | +| `onGroupMemberUnbanned` | Updates the group list when a member is unbanned | +| `onGroupMemberScopeChanged` | Updates the group list when a member's scope changes | +| `onMemberAddedToGroup` | Updates the group list when members are added | + +> Automatic: group membership changes update the list in real time. + +## Functionality + +Small functional customizations such as toggling visibility of UI elements and configuring selection modes. + +| Methods | Description | Code | +| --- | --- | --- | +| `setBackIconVisibility` | Toggles visibility for the back button in the app bar | `.setBackIconVisibility(View.VISIBLE);` | +| `setToolbarVisibility` | Toggles visibility for the toolbar in the app bar | `.setToolbarVisibility(View.GONE);` | +| `setLoadingStateVisibility` | Hides the loading state while fetching groups | `.setLoadingStateVisibility(View.GONE);` | +| `setErrorStateVisibility` | Hides the error state on fetching groups | `.setErrorStateVisibility(View.GONE);` | +| `setEmptyStateVisibility` | Hides the empty state on fetching groups | `.setEmptyStateVisibility(View.GONE);` | +| `setSeparatorVisibility` | Controls visibility of separators in the list view | `.setSeparatorVisibility(View.GONE);` | +| `setGroupTypeVisibility` | Controls visibility of the group type indicator (public, private, password) | `.setGroupTypeVisibility(View.GONE);` | +| `setSearchBoxVisibility` | Controls visibility of the search box in the toolbar | `.setSearchBoxVisibility(View.GONE);` | +| `setSelectionMode` | Determines the selection mode (single or multiple) | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | +| `setSearchKeyword` | Programmatically triggers a search with the given keyword | `.setSearchKeyword("design");` | +| `setTitleText` | Sets a custom title in the toolbar | `.setTitleText("My Groups");` | +| `setTitleVisibility` | Toggles visibility for the title text in the toolbar | `.setTitleVisibility(View.GONE);` | +| `setSearchPlaceholderText` | Sets the placeholder text for the search input | `.setSearchPlaceholderText("Find groups...");` | + +- **Verify**: After calling a visibility method, confirm the corresponding UI element is shown or hidden. + +## Custom View Slots + +Each slot replaces a section of the default UI. Slots that accept a `Group` parameter receive the group object for that row via the `GroupsViewHolderListener` pattern (`createView` + `bindView`). + +| Slot | Method | Replaces | +| --- | --- | --- | +| Leading view | `setLeadingView(GroupsViewHolderListener)` | Avatar / left section | +| Title view | `setTitleView(GroupsViewHolderListener)` | Name / title text | +| Subtitle view | `setSubtitleView(GroupsViewHolderListener)` | Subtitle text below name | +| Trailing view | `setTrailingView(GroupsViewHolderListener)` | Right section | +| Item view | `setItemView(GroupsViewHolderListener)` | Entire list item row | +| Loading view | `setLoadingView(@LayoutRes int)` | Loading spinner | +| Empty view | `setEmptyView(@LayoutRes int)` | Empty state | +| Error view | `setErrorView(@LayoutRes int)` | Error state | +| Overflow menu | `setOverflowMenu(View)` | Toolbar menu | +| Options (replace) | `setOptions(Function2)` | Long-press context menu (replaces defaults) | +| Options (append) | `addOptions(Function2)` | Long-press context menu (appends to defaults) | + +### `setLeadingView` + +Replace the avatar / left section. - -```java -cometchatGroups.setEmptyView(R.layout.your_empty_view); -``` - - - -```kotlin -cometchatGroups.emptyView = R.layout.your_empty_view -``` - - - - - -*** - -#### setErrorView - -Configures the UI when an error occurs while fetching groups. - -Use Cases: - -* Display a retry button with "Failed to load groups, try again.". -* Show a friendly error illustration. +```kotlin lines +cometchatGroups.setLeadingView(object : GroupsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatListBaseItemsBinding? + ): View? { + return null + } - - -```java -cometchatGroups.setErrorView(R.layout.your_empty_view); + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + } +}) ``` - - -```kotlin -cometchatGroups.errorView = R.layout.your_error_view -``` - - - - - -*** - -#### setLeadingView - -Sets a custom leading view that appears at the start of each group item. - -Use Cases: - -* Display the group profile picture. -* Add an icon indicating Public or Private groups. - - -```java +```java lines cometchatGroups.setLeadingView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { - - } - }); -``` - - - - -```kotlin -cometchatGroups.setLeadingView(object: GroupsViewHolderListener { - override fun createView(context: Context, cometChatListItem: CometChatListItem): View? { - return null + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return null; } - override fun bindView(context: Context, view: View, Group: group, viewHolder: RecyclerView.ViewHolder, list: List, i: Int) { + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + } -}) +}); ``` - - +> **What this does:** Registers a `GroupsViewHolderListener` that provides a custom view for the leading (left) area of each group item. `createView` inflates your layout, and `bindView` populates it with group data. + +Join status badge example: + -You can indeed create a custom layout file named `custom_leading_avatar_view.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: - -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: +Create a `custom_leading_avatar_view.xml` layout: -```xml custom_leading_avatar_view.xml +```xml custom_leading_avatar_view.xml lines - -```java -cometchatGroups.setLeadingView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.custom_leading_avatar_view, null); - } - - @Override - public void bindView(Context context, - View createdView, - Group group, - RecyclerView.ViewHolder holder, - List groupList, - int position) { - LinearLayout groupAvatar = createdView.findViewById(R.id.leading_avatar_view); - groupAvatar.setBackground(group.isJoined() ? ResourcesCompat.getDrawable(getResources(), - R.drawable.group_leading_joined, - null) : ResourcesCompat.getDrawable(getResources(), - R.drawable.group_leading_join, - null)); - groupAvatar.setOnLongClickListener(v -> { - if (group.isJoined()) { - Toast.makeText(context, "Group already joined", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(context, "Joining group", Toast.LENGTH_SHORT).show(); - } - return true; - }); - } - }); -``` - - - -```kotlin +```kotlin lines cometchatGroups.setLeadingView(object : GroupsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatListBaseItemsBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.custom_leading_avatar_view, null) - } + override fun createView(context: Context?, listItem: CometchatListBaseItemsBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.custom_leading_avatar_view, null) + } - override fun bindView( - context: Context, - createdView: View, - group: Group, - holder: RecyclerView.ViewHolder, - groupList: List, - position: Int - ) { - val groupAvatar = createdView.findViewById(R.id.leading_avatar_view) - groupAvatar.background = if (group.isJoined) ResourcesCompat.getDrawable( - resources, - R.drawable.group_leading_joined, - null - ) else ResourcesCompat.getDrawable( - resources, - R.drawable.group_leading_join, - null - ) - groupAvatar.setOnLongClickListener { v: View? -> - if (group.isJoined) { - Toast.makeText(context, "Group already joined", Toast.LENGTH_SHORT).show() - } else { - Toast.makeText(context, "Joining group", Toast.LENGTH_SHORT).show() - } - true - } + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + val groupAvatar = createdView.findViewById(R.id.leading_avatar_view) + groupAvatar.background = if (group.isJoined) ResourcesCompat.getDrawable( + resources, + R.drawable.group_leading_joined, + null + ) else ResourcesCompat.getDrawable( + resources, + R.drawable.group_leading_join, + null + ) + groupAvatar.setOnLongClickListener { v: View? -> + if (group.isJoined) { + Toast.makeText(context, "Group already joined", Toast.LENGTH_SHORT).show() + } else { + Toast.makeText(context, "Joining group", Toast.LENGTH_SHORT).show() } - }) + true + } + } +}) ``` - - - -*** - -#### setTitleView - -Customizes the title view of each group item, which typically displays the group name. - -Use Cases: - -* Style group names with custom fonts and colors. -* Show a verified badge for official groups. - - -```java -cometchatGroups.setTitleView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { +```java lines +cometchatGroups.setLeadingView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.custom_leading_avatar_view, null); + } + @Override + public void bindView(Context context, + View createdView, + Group group, + RecyclerView.ViewHolder holder, + List groupList, + int position) { + LinearLayout groupAvatar = createdView.findViewById(R.id.leading_avatar_view); + groupAvatar.setBackground(group.isJoined() ? ResourcesCompat.getDrawable(getResources(), + R.drawable.group_leading_joined, + null) : ResourcesCompat.getDrawable(getResources(), + R.drawable.group_leading_join, + null)); + groupAvatar.setOnLongClickListener(v -> { + if (group.isJoined()) { + Toast.makeText(context, "Group already joined", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(context, "Joining group", Toast.LENGTH_SHORT).show(); } + return true; }); + } +}); ``` - + +### `setTitleView` + +Replace the name / title text. + + -```kotlin -cometchatGroups.setTitleView(object: GroupsViewHolderListener { - override fun createView(context: Context, cometChatListItem: CometChatListItem): View? { +```kotlin lines +cometchatGroups.setTitleView(object : GroupsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatListBaseItemsBinding? + ): View? { return null } - override fun bindView(context: Context, view: View, Group: group, viewHolder: RecyclerView.ViewHolder, list: List, i: Int) { + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { } }) ``` - + +```java lines +cometchatGroups.setTitleView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + + } +}); +``` + +Group type icon example: + -You can indeed create a custom layout file named `custom_title_view.xml` for more complex or unique list items. +Create a `custom_group_title_view.xml` layout: -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: - -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: - -```xml custom_title_view.xml +```xml custom_group_title_view.xml lines + +```kotlin lines +cometchatGroups.setTitleView(object : GroupsViewHolderListener() { + override fun createView(context: Context?, listItem: CometchatListBaseItemsBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.custom_group_title_view, null) + } + + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + val layout = createdView.findViewById(R.id.group_layout) + val layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + layout.layoutParams = layoutParams + val name = createdView.findViewById(R.id.title) + name.text = group.name + val type = createdView.findViewById(R.id.type) + if (CometChatConstants.GROUP_TYPE_PUBLIC == group.groupType) { + type.visibility = View.VISIBLE + type.background = ResourcesCompat.getDrawable(resources, R.drawable.public_icon, null) + } else if (CometChatConstants.GROUP_TYPE_PASSWORD == group.groupType) { + type.visibility = View.VISIBLE + type.background = ResourcesCompat.getDrawable(resources, R.drawable.passowrd_icon, null) + } else if (CometChatConstants.GROUP_TYPE_PRIVATE == group.groupType) { + type.visibility = View.VISIBLE + type.background = ResourcesCompat.getDrawable(resources, R.drawable.private_icon, null) + } else { + type.visibility = View.GONE + } + } +}) +``` + + -```java +```java lines cometchatGroups.setTitleView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.custom_group_title_view, null); - } - - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { - LinearLayout layout = createdView.findViewById(R.id.user_layout); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - layout.setLayoutParams(layoutParams); - TextView name = createdView.findViewById(R.id.title); - name.setText(group.getName()); - View type = createdView.findViewById(R.id.role); - - if (CometChatConstants.GROUP_TYPE_PUBLIC.equals(group.getType())) { - type.setVisibility(View.VISIBLE); - type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.public_icon, null)); - } else if (CometChatConstants.GROUP_TYPE_PASSWORD.equals(group.getType())) { - type.setVisibility(View.VISIBLE); - type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.passowrd_icon, null)); - } else if (CometChatConstants.GROUP_TYPE_PRIVATE.equals(roup.getType())) { - type.setVisibility(View.VISIBLE); - type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.private_icon, null)); - } else { - type.setVisibility(View.GONE); - } + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.custom_group_title_view, null); + } - } - }); + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + LinearLayout layout = createdView.findViewById(R.id.user_layout); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + layout.setLayoutParams(layoutParams); + TextView name = createdView.findViewById(R.id.title); + name.setText(group.getName()); + View type = createdView.findViewById(R.id.type); + + if (CometChatConstants.GROUP_TYPE_PUBLIC.equals(group.getGroupType())) { + type.setVisibility(View.VISIBLE); + type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.public_icon, null)); + } else if (CometChatConstants.GROUP_TYPE_PASSWORD.equals(group.getGroupType())) { + type.setVisibility(View.VISIBLE); + type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.passowrd_icon, null)); + } else if (CometChatConstants.GROUP_TYPE_PRIVATE.equals(group.getGroupType())) { + type.setVisibility(View.VISIBLE); + type.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.private_icon, null)); + } else { + type.setVisibility(View.GONE); + } + } +}); ``` - + + +### `setSubtitleView` + +Replace the subtitle text below the group's name. + + -```kotlin -cometchatGroups.setTitleView(object : GroupsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatListBaseItemsBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.custom_group_title_view, null) - } +```kotlin lines +cometchatGroups.setSubtitleView(object : GroupsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatListBaseItemsBinding? + ): View? { + return null + } - override fun bindView( - context: Context, - createdView: View, - group: Group, - holder: RecyclerView.ViewHolder, - groupList: List, - position: Int - ) { - val layout = createdView.findViewById(R.id.group_layout) - val layoutParams = LinearLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - layout.layoutParams = layoutParams - val name = createdView.findViewById(R.id.title) - name.text = group.name - val type = createdView.findViewById(R.id.type) - if (CometChatConstants.GROUP_TYPE_PUBLIC == group.groupType) { - type.visibility = View.VISIBLE - type.background = ResourcesCompat.getDrawable(resources, R.drawable.public_icon, null) - } else if (CometChatConstants.GROUP_TYPE_PASSWORD == group.groupType) { - type.visibility = View.VISIBLE - type.background = ResourcesCompat.getDrawable(resources, R.drawable.passowrd_icon, null) - } else if (CometChatConstants.GROUP_TYPE_PRIVATE == group.groupTyp) { - type.visibility = View.VISIBLE - type.background = ResourcesCompat.getDrawable(resources, R.drawable.private_icon, null) - } else { - type.visibility = View.GONE - } - } - }) + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + } +}) ``` - - - -*** + +```java lines +cometchatGroups.setSubtitleView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return null; + } -#### setTrailingView + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { -Allows custom elements to be added at the end of each group item, such as buttons or indicators. + } +}); +``` + + -Use Cases: +Example with member count and description: -* Show unread message counts. -* Add a quick Join or Leave button. + + + - -```java -cometchatGroups.setTrailingView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + +```kotlin YourActivity.kt lines +cometchatGroups.setSubtitleView(object : GroupsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatListBaseItemsBinding? + ): View { + return TextView(context) + } - } - }); + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + val textView = createdView as TextView + textView.text = + if (group.membersCount > 1) group.membersCount.toString() + " members" else group.membersCount.toString() + " member" + " • " + group.description + } +}) ``` + + + +```java YourActivity.java lines +cometchatGroups.setSubtitleView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return new TextView(context); + } + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + TextView textView = (TextView) createdView; + textView.setText(group.getMembersCount() > 1 ? group.getMembersCount() + " members" : group.getMembersCount() + " member" + " • " + group.getDescription()); + } +}); +``` + + +### `setTrailingView` + +Replace the right section of each group item. + -```kotlin -cometchatGroups.setTrailingView(object: GroupsViewHolderListener { - override fun createView(context: Context, cometChatListItem: CometChatListItem): View? { +```kotlin lines +cometchatGroups.setTrailingView(object : GroupsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatListBaseItemsBinding? + ): View? { return null } - override fun bindView(context: Context, view: View, Group: Group, viewHolder: RecyclerView.ViewHolder, list: List, i: Int) { + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { } }) ``` - + +```java lines +cometchatGroups.setTrailingView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + + } +}); +``` + +Join button example: + -You can indeed create a custom layout file named `custom_tail_view.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: - -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: +Create a `custom_tail_view.xml` layout: -```xml custom_tail_view.xml +```xml custom_tail_view.xml lines - -```java -cometchatGroups.setTrailingView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null); - } - - @Override - public void bindView(Context context, - View createdView, - Group group, - RecyclerView.ViewHolder holder, - List groupList, - int position) { - MaterialButton button = createdView.findViewById(R.id.button); - button.setText(group.isJoined() ? "Joined" : "+ Join"); - } - }); -``` - - - -```kotlin +```kotlin lines cometchatGroups.setTrailingView(object : GroupsViewHolderListener() { - override fun createView(context: Context?, listItem: CometchatListBaseItemsBinding?): View { - return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null) - } - - override fun bindView( - context: Context, - createdView: View, - group: Group, - holder: RecyclerView.ViewHolder, - groupList: List, - position: Int - ) { - val button = createdView.findViewById(R.id.button) - button.text = (if (group.isJoined) "Joined" else "+ Join") + override fun createView(context: Context?, listItem: CometchatListBaseItemsBinding?): View { + return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null) + } - } - }) + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + val button = createdView.findViewById(R.id.button) + button.text = (if (group.isJoined) "Joined" else "+ Join") + } +}) ``` - - - -*** - -#### setItemView - -Assigns a fully custom ListItem layout to the Groups component, replacing the default design. - -Use Cases: - -* Add a description below the group name. -* Customize layout to include additional metadata. - - -```java -cometchatGroups.setItemView(new GroupsViewHolderListener() { +```java lines +cometchatGroups.setTrailingView(new GroupsViewHolderListener() { @Override - public View createView(Context context, CometchatListBaseItemsBinding cometChatListItem) { - return null; + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return LayoutInflater.from(context).inflate(R.layout.custom_tail_view, null); } @Override - public void bindView(Context context, View view, Group group, RecyclerView.ViewHolder viewHolder, List list, int i) { - + public void bindView(Context context, + View createdView, + Group group, + RecyclerView.ViewHolder holder, + List groupList, + int position) { + MaterialButton button = createdView.findViewById(R.id.button); + button.setText(group.isJoined() ? "Joined" : "+ Join"); } }); ``` - + + +### `setItemView` +Replace the entire list item row. + + -```kotlin +```kotlin lines cometchatGroups.setItemView(object : GroupsViewHolderListener() { override fun createView( context: Context?, - CometchatListBaseItemsBinding: CometChatListItem? + listItem: CometchatListBaseItemsBinding? ): View? { return null } override fun bindView( - context: Context?, - view: View?, - group: Group?, - viewHolder: RecyclerView.ViewHolder?, - list: List?, - i: Int + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int ) { - } }) ``` - + +```java lines +cometchatGroups.setItemView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return null; + } + + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + + } +}); +``` + -**Example** +Custom list item example: -You can indeed create a custom layout file named `item_list.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: - -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: - -```xml custom_group_list_itemd.xml +Create a `custom_group_list_item.xml` layout: +```xml custom_group_list_item.xml lines - -```java YourActivity.java -cometChatGroup.setItemView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return View.inflate(context,R.layout.custom_group_list_item,null); - } + +```kotlin YourActivity.kt lines +cometchatGroups.setItemView(object : GroupsViewHolderListener() { + override fun createView( + context: Context?, + listItem: CometchatListBaseItemsBinding? + ): View { + return View.inflate(context, R.layout.custom_group_list_item, null) + } - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { - TextView groupName = createdView.findViewById(R.id.tvName); - TextView groupMemberCount = createdView.findViewById(R.id.tvSubtitle); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); - createdView.setLayoutParams(params); - groupName.setText(group.getName()); - groupMemberCount.setText(group.getMembersCount() > 1 ? group.getMembersCount() + " members" : group.getMembersCount() + " member" + " • " + group.getDescription()); - } - }); + override fun bindView( + context: Context, + createdView: View, + group: Group, + holder: RecyclerView.ViewHolder, + groupList: List, + position: Int + ) { + val groupName = createdView.findViewById(R.id.tvName) + val groupMemberCount = createdView.findViewById(R.id.tvSubtitle) + val params = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + createdView.layoutParams = params + groupName.text = group.name + groupMemberCount.text = + if (group.membersCount > 1) group.membersCount.toString() + " members" else group.membersCount.toString() + " member" + " • " + group.description + } +}) ``` - - -```kotlin YourActivity.kt -cometChatGroup.setItemView(object : GroupsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatListBaseItemsBinding? - ): View { - return View.inflate(context, R.layout.custom_group_list_item, null) - } + +```java YourActivity.java lines +cometchatGroups.setItemView(new GroupsViewHolderListener() { + @Override + public View createView(Context context, CometchatListBaseItemsBinding listItem) { + return View.inflate(context, R.layout.custom_group_list_item, null); + } - override fun bindView( - context: Context, - createdView: View, - group: Group, - holder: RecyclerView.ViewHolder, - groupList: List, - position: Int - ) { - val groupName = createdView.findViewById(R.id.tvName) - val groupMemberCount = createdView.findViewById(R.id.tvSubtitle) - val params = LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - createdView.layoutParams = params - groupName.text = group.name - groupMemberCount.text = - if (group.membersCount > 1) group.membersCount.toString() + " members" else group.membersCount.toString() + " member" + " • " + group.description - } - }) + @Override + public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { + TextView groupName = createdView.findViewById(R.id.tvName); + TextView groupMemberCount = createdView.findViewById(R.id.tvSubtitle); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + createdView.setLayoutParams(params); + groupName.setText(group.getName()); + groupMemberCount.setText(group.getMembersCount() > 1 ? group.getMembersCount() + " members" : group.getMembersCount() + " member" + " • " + group.getDescription()); + } +}); ``` - - -*** - -#### setSubTitleView - -Customizes the subtitle view for each group item, which typically displays extra information. - -Use Cases: +### `setOptions` -* Show last message preview. -* Display the number of members. +Replace the long-press context menu entirely. - -```java -CometChatGroup.setSubtitleView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return null; - } - - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { - - } - }); + +```kotlin lines +cometchatGroups.options = Function2?> { context, group -> emptyList() } ``` - - -```kotlin -cometChatGroup.setSubtitleView(object : GroupsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatListBaseItemsBinding? - ): View { - return null - } - - override fun bindView( - context: Context, - createdView: View, - group: Group, - holder: RecyclerView.ViewHolder, - groupList: List, - position: Int - ) { - - } - }) + +```java lines +cometchatGroups.setOptions((context, group) -> Collections.emptyList()); ``` - - -**Example** +### `addOptions` - - - - -You can indeed create a custom layout file named `subtitle_layout.xml` for more complex or unique list items. - -Once this layout file is made, you would inflate it inside the `createView()` method of the `GroupsViewHolderListener`. The inflation process prepares the layout for use in your application: - -Following this, you would use the `bindView()` method to initialize and assign values to your individual views. This could include setting text on TextViews, images on ImageViews, and so on based on the properties of the Group object: +Append to the long-press context menu without removing defaults. - -```java YourActivity.java -cometChatGroup.setSubtitleView(new GroupsViewHolderListener() { - @Override - public View createView(Context context, CometchatListBaseItemsBinding listItem) { - return new TextView(context); - } - - @Override - public void bindView(Context context, View createdView, Group group, RecyclerView.ViewHolder holder, List groupList, int position) { - TextView textView = (TextView) createdView; - textView.setText(group.getMembersCount() > 1 ? group.getMembersCount() + " members" : group.getMembersCount() + " member" + " • " + group.getDescription()); - - } - }); + +```kotlin lines +cometchatGroups.addOptions { context, group -> emptyList() } ``` - - -```kotlin YourActivity.kt -group.setSubtitleView(object : GroupsViewHolderListener() { - override fun createView( - context: Context?, - listItem: CometchatListBaseItemsBinding? - ): View { - return TextView(context) - } - - override fun bindView( - context: Context, - createdView: View, - group: Group, - holder: RecyclerView.ViewHolder, - groupList: List, - position: Int - ) { - val textView = createdView as TextView - textView.text = - if (group.membersCount > 1) group.membersCount.toString() + " members" else group.membersCount.toString() + " member" + " • " + group.description - } - }) + +```java lines +cometchatGroups.addOptions((context, group) -> Collections.emptyList()); ``` - - -*** +### `setLoadingView` + +Sets a custom loading view displayed when data is being fetched. -#### SetOverflowMenu + + +```kotlin lines +cometchatGroups.loadingView = R.layout.your_loading_view +``` + -Customizes the overflow menu (three-dot ⋮ icon) with additional options. + +```java lines +cometchatGroups.setLoadingView(R.layout.your_loading_view); +``` + + -Use Cases: +### `setEmptyView` -* Add options like "Invite Members", "Report Group". -* Enable admin-specific options like "Manage Group Settings". +Configures a custom view displayed when there are no groups in the list. - -```java -cometchatGroups.setOverflowMenu(View v); + +```kotlin lines +cometchatGroups.emptyView = R.layout.your_empty_view ``` + + +```java lines +cometchatGroups.setEmptyView(R.layout.your_empty_view); +``` + + +### `setErrorView` + +Defines a custom error state view that appears when an issue occurs while loading groups. + -```kotlin -cometchatGroups.setOverflowMenu(v) +```kotlin lines +cometchatGroups.errorView = R.layout.your_error_view ``` - + +```java lines +cometchatGroups.setErrorView(R.layout.your_error_view); +``` + -**Example** +### `setOverflowMenu` + +Replace the toolbar overflow menu. -You need to create a `overflow_menu_layout.xml` as a custom view file. Which we will inflate and pass to `.setOverflowMenu()`. +Create an `overflow_menu_layout.xml` layout: -```xml overflow_menu_layout.xml +```xml overflow_menu_layout.xml lines ``` -You inflate the view and pass it to `setOverflowMenu`. You can get the child view reference and can handle click actions. - + +```kotlin YourActivity.kt lines +val view: View = layoutInflater.inflate(R.layout.overflow_menu_layout, null) +val imgRefresh = view.findViewById(R.id.ivMenu) +imgRefresh.setOnClickListener { v: View? -> + Toast.makeText(requireContext(), "Clicked on Refresh", Toast.LENGTH_SHORT).show() +} +cometchatGroups.setOverflowMenu(view) +``` + + -```java YourActivity.java +```java YourActivity.java lines View view = getLayoutInflater().inflate(R.layout.overflow_menu_layout, null); ImageView imgRefresh = view.findViewById(R.id.ivMenu); imgRefresh.setOnClickListener(v -> { @@ -1496,19 +1544,342 @@ imgRefresh.setOnClickListener(v -> { }); cometchatGroups.setOverflowMenu(view); ``` + + + +- **Verify**: After setting any custom view slot, confirm the custom view renders in the correct position within the group list item, and the data binding populates correctly for each group. + + +## Common Patterns + +### Hide all chrome — minimal list + + + +```kotlin lines +cometchatGroups.setGroupTypeVisibility(View.GONE) +cometchatGroups.setSeparatorVisibility(View.GONE) +cometchatGroups.setToolbarVisibility(View.GONE) +``` + + +```java lines +cometchatGroups.setGroupTypeVisibility(View.GONE); +cometchatGroups.setSeparatorVisibility(View.GONE); +cometchatGroups.setToolbarVisibility(View.GONE); +``` + +### Joined groups only + + -```kotlin YourActivity.kt -val view: View = layoutInflater.inflate(R.layout.overflow_menu_layout, null) -val imgRefresh = view.findViewById(R.id.ivMenu) -imgRefresh.setOnClickListener { v: View? -> - Toast.makeText(requireContext(), "Clicked on Refresh", Toast.LENGTH_SHORT).show() -} -cometchatGroups.setOverflowMenu(view) +```kotlin lines +val builder = GroupsRequestBuilder() + .joinedOnly(true) +cometchatGroups.setGroupsRequestBuilder(builder) +``` + + + +```java lines +GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder() + .joinedOnly(true); +cometchatGroups.setGroupsRequestBuilder(builder); +``` + + + +### Filter by tags + + + +```kotlin lines +val builder = GroupsRequestBuilder() + .setTags(listOf("vip", "premium")) +cometchatGroups.setGroupsRequestBuilder(builder) +``` + + + +```java lines +GroupsRequest.GroupsRequestBuilder builder = new GroupsRequest.GroupsRequestBuilder() + .setTags(Arrays.asList("vip", "premium")); +cometchatGroups.setGroupsRequestBuilder(builder); +``` + + + +## Advanced Methods + +### Programmatic Selection + +#### `selectGroup` + +Programmatically selects or deselects a group. Works with both `SINGLE` and `MULTIPLE` selection modes. + + + +```kotlin lines +// Select a group in single-select mode +cometchatGroups.selectGroup(group, UIKitConstants.SelectionMode.SINGLE) + +// Select a group in multi-select mode +cometchatGroups.selectGroup(group, UIKitConstants.SelectionMode.MULTIPLE) +``` + + + +```java lines +// Select a group in single-select mode +cometchatGroups.selectGroup(group, UIKitConstants.SelectionMode.SINGLE); + +// Select a group in multi-select mode +cometchatGroups.selectGroup(group, UIKitConstants.SelectionMode.MULTIPLE); +``` + + + +> In `SINGLE` mode, selecting a new group replaces the previous selection. In `MULTIPLE` mode, calling this on an already-selected group deselects it (toggle behavior). + +#### `clearSelection` + +Clears all selected groups and resets the selection UI. + + + +```kotlin lines +cometchatGroups.clearSelection() +``` + + + +```java lines +cometchatGroups.clearSelection(); +``` + + + +#### `getSelectedGroups` + +Returns the list of currently selected `Group` objects. + + + +```kotlin lines +val selected = cometchatGroups.selectedGroups +``` + + + +```java lines +List selected = cometchatGroups.getSelectedGroups(); +``` + + + +### Selected Groups List + +When using multi-select mode, a horizontal list of selected groups can be shown above the main list. + +| Method | Type | Description | +| --- | --- | --- | +| `setSelectedGroupsListVisibility` | `int (View.VISIBLE / View.GONE)` | Show or hide the selected groups strip | +| `setSelectedGroupAvatarStyle` | `@StyleRes int` | Avatar style for selected group chips | +| `setSelectedGroupItemTextColor` | `@ColorInt int` | Text color for selected group names | +| `setSelectedGroupItemTextAppearance` | `@StyleRes int` | Text appearance for selected group names | +| `setSelectedGroupItemRemoveIcon` | `Drawable` | Icon for the remove button on each chip | +| `setSelectedGroupItemRemoveIconTint` | `@ColorInt int` | Tint color for the remove icon | + +### Search Input Customization + +The built-in search box can be customized programmatically: + +| Method | Type | Description | +| --- | --- | --- | +| `setSearchPlaceholderText` | `String` | Sets the placeholder text for the search input | +| `setSearchInputTextColor` | `@ColorInt int` | Text color of the search input | +| `setSearchInputTextAppearance` | `@StyleRes int` | Text appearance of the search input | +| `setSearchInputPlaceHolderTextColor` | `@ColorInt int` | Placeholder text color | +| `setSearchInputPlaceHolderTextAppearance` | `@StyleRes int` | Placeholder text appearance | +| `setSearchInputIcon` | `Drawable` | Leading icon in the search box | +| `setSearchInputIconTint` | `@ColorInt int` | Tint for the leading icon | +| `setSearchInputEndIcon` | `Drawable` | Trailing icon in the search box | +| `setSearchInputEndIconTint` | `@ColorInt int` | Tint for the trailing icon | +| `setSearchInputStrokeWidth` | `@Dimension int` | Stroke width of the search box border | +| `setSearchInputStrokeColor` | `@ColorInt int` | Stroke color of the search box border | +| `setSearchInputBackgroundColor` | `@ColorInt int` | Background color of the search box | +| `setSearchInputCornerRadius` | `@Dimension int` | Corner radius of the search box | + +### Internal Access + +These methods provide direct access to internal components for advanced use cases. + +| Method | Returns | Description | +| --- | --- | --- | +| `getBinding()` | `CometchatGroupListBinding` | The ViewBinding for the component's root layout | +| `getViewModel()` | `GroupsViewModel` | The ViewModel managing group data and state | +| `getAdapter()` | `GroupsAdapter` | The adapter powering the RecyclerView | +| `setAdapter(GroupsAdapter)` | `void` | Replaces the default adapter with a custom one | + +> Use these only when the standard API is insufficient. Directly manipulating the adapter or ViewModel may conflict with the component's internal state management. + +## Style + +The component uses XML theme styles. Define a custom style with parent `CometChatGroupsStyle` in `themes.xml`, then apply with `setStyle()`. + + + + + +```xml themes.xml lines + + ``` + + +```kotlin lines +cometchatGroups.setStyle(R.style.CustomGroupsStyle) +``` + +```java lines +cometchatGroups.setStyle(R.style.CustomGroupsStyle); +``` + + +To know more such attributes, visit the [attributes file](https://github.com/cometchat/cometchat-uikit-android/blob/v5/chatuikit/src/main/res/values/attr_cometchat_groups.xml). + +### Programmatic Style Properties + +In addition to XML theme styles, the component exposes programmatic setters for fine-grained control: + +| Method | Type | Description | +| --- | --- | --- | +| `setBackgroundColor` | `@ColorInt int` | Background color of the component | +| `setBackIconTint` | `@ColorInt int` | Tint color for the back icon | +| `setBackIcon` | `Drawable` | Custom back icon drawable | +| `setTitleTextColor` | `@ColorInt int` | Title text color in the toolbar | +| `setTitleTextAppearance` | `@StyleRes int` | Title text appearance in the toolbar | +| `setItemTitleTextColor` | `@ColorInt int` | Text color for group item titles | +| `setItemTitleTextAppearance` | `@StyleRes int` | Text appearance for group item titles | +| `setItemBackgroundColor` | `@ColorInt int` | Background color for list items | +| `setItemSelectedBackgroundColor` | `@ColorInt int` | Background color for selected list items | +| `setSeparatorColor` | `@ColorInt int` | Color of list item separators | +| `setStrokeColor` | `@ColorInt int` | Stroke color of the component border | +| `setStrokeWidth` | `@Dimension int` | Stroke width of the component border | +| `setCornerRadius` | `@Dimension int` | Corner radius of the component | +| `setSubtitleTextColor` | `@ColorInt int` | Text color for group item subtitles | +| `setSubtitleTextAppearance` | `@StyleRes int` | Text appearance for group item subtitles | +| `setEmptyStateTextColor` | `@ColorInt int` | Title text color for the empty state | +| `setEmptyStateTextAppearance` | `@StyleRes int` | Title text appearance for the empty state | +| `setEmptyStateSubtitleTextColor` | `@ColorInt int` | Subtitle text color for the empty state | +| `setEmptyStateSubTitleTextAppearance` | `@StyleRes int` | Subtitle text appearance for the empty state | +| `setErrorStateTextColor` | `@ColorInt int` | Title text color for the error state | +| `setErrorStateTextAppearance` | `@StyleRes int` | Title text appearance for the error state | +| `setErrorStateSubtitleColor` | `@ColorInt int` | Subtitle text color for the error state | +| `setErrorStateSubtitleTextAppearance` | `@StyleRes int` | Subtitle text appearance for the error state | +| `setRetryButtonTextColor` | `@ColorInt int` | Text color for the retry button | +| `setRetryButtonTextAppearance` | `@StyleRes int` | Text appearance for the retry button | +| `setRetryButtonBackgroundColor` | `@ColorInt int` | Background color for the retry button | +| `setRetryButtonStrokeColor` | `@ColorInt int` | Stroke color for the retry button | +| `setRetryButtonStrokeWidth` | `@Dimension int` | Stroke width for the retry button | +| `setRetryButtonCornerRadius` | `@Dimension int` | Corner radius for the retry button | +| `setAvatarStyle` | `@StyleRes int` | Style for group avatars | +| `setStatusIndicatorStyle` | `@StyleRes int` | Style for group type status indicators | + +### Checkbox Style Properties (Selection Mode) + +When using `SINGLE` or `MULTIPLE` selection mode, checkboxes appear on each item: + +| Method | Type | Description | +| --- | --- | --- | +| `setCheckBoxStrokeWidth` | `@Dimension int` | Stroke width of the checkbox border | +| `setCheckBoxCornerRadius` | `@Dimension int` | Corner radius of the checkbox | +| `setCheckBoxStrokeColor` | `@ColorInt int` | Stroke color of the checkbox border | +| `setCheckBoxBackgroundColor` | `@ColorInt int` | Background color of unchecked checkbox | +| `setCheckBoxCheckedBackgroundColor` | `@ColorInt int` | Background color of checked checkbox | +| `setCheckBoxSelectIcon` | `Drawable` | Icon shown when checkbox is checked | +| `setCheckBoxSelectIconTint` | `@ColorInt int` | Tint for the checkbox select icon | +| `setDiscardSelectionIcon` | `Drawable` | Icon for the discard selection button | +| `setDiscardSelectionIconTint` | `@ColorInt int` | Tint for the discard selection icon | +| `setSubmitSelectionIcon` | `Drawable` | Icon for the submit selection button | +| `setSubmitSelectionIconTint` | `@ColorInt int` | Tint for the submit selection icon | + +## Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on group interaction | Activity/Fragment | `setOn` callbacks | `setOnItemClick((v, pos, g) -> { ... })` | +| Filter which groups appear | Activity/Fragment | `setGroupsRequestBuilder` | `setGroupsRequestBuilder(builder)` | +| Customize search results | Activity/Fragment | `setSearchRequestBuilder` | `setSearchRequestBuilder(builder)` | +| Toggle visibility of UI elements | Activity/Fragment | `setVisibility(int)` | `setGroupTypeVisibility(View.GONE)` | +| Replace a section of the list item | Activity/Fragment | `setView` | `setLeadingView(listener)` | +| Change colors, fonts, spacing | `themes.xml` | `CometChatGroupsStyle` | `#F76808` | +| Avatar style (corner radius, background) | `themes.xml` | `cometchatGroupsAvatar` | `8dp` | +| Apply a custom style | Activity/Fragment | `setStyle(int styleRes)` | `cometchatGroups.setStyle(R.style.CustomGroupsStyle);` | +| Back button visibility | Activity/Fragment | `setBackIconVisibility(int)` | `.setBackIconVisibility(View.VISIBLE);` | +| Toolbar visibility | Activity/Fragment | `setToolbarVisibility(int)` | `.setToolbarVisibility(View.GONE);` | +| Error state visibility | Activity/Fragment | `setErrorStateVisibility(int)` | `.setErrorStateVisibility(View.GONE);` | +| Empty state visibility | Activity/Fragment | `setEmptyStateVisibility(int)` | `.setEmptyStateVisibility(View.GONE);` | +| Loading state visibility | Activity/Fragment | `setLoadingStateVisibility(int)` | `.setLoadingStateVisibility(View.GONE);` | +| Separator visibility | Activity/Fragment | `setSeparatorVisibility(int)` | `.setSeparatorVisibility(View.GONE);` | +| Group type indicator visibility | Activity/Fragment | `setGroupTypeVisibility(int)` | `.setGroupTypeVisibility(View.GONE);` | +| Selection mode (single/multiple) | Activity/Fragment | `setSelectionMode(SelectionMode)` | `.setSelectionMode(UIKitConstants.SelectionMode.MULTIPLE);` | +| Search keyword | Activity/Fragment | `setSearchKeyword(String)` | `.setSearchKeyword("design");` | +| Search box visibility | Activity/Fragment | `setSearchBoxVisibility(int)` | `.setSearchBoxVisibility(View.GONE);` | +| Custom toolbar title | Activity/Fragment | `setTitleText(String)` | `.setTitleText("My Groups");` | +| Title visibility | Activity/Fragment | `setTitleVisibility(int)` | `.setTitleVisibility(View.GONE);` | +| Search placeholder | Activity/Fragment | `setSearchPlaceholderText(String)` | `.setSearchPlaceholderText("Find groups...");` | +| Long-press options (replace) | Activity/Fragment | `setOptions(Function2)` | See `setOptions` code above | +| Long-press options (append) | Activity/Fragment | `addOptions(Function2)` | See `addOptions` code above | +| Loading view | Activity/Fragment | `setLoadingView(int)` | `.setLoadingView(R.layout.your_loading_view);` | +| Empty view | Activity/Fragment | `setEmptyView(int)` | `.setEmptyView(R.layout.your_empty_view);` | +| Error view | Activity/Fragment | `setErrorView(int)` | `.setErrorView(R.layout.your_error_view);` | +| Leading view (avatar area) | Activity/Fragment | `setLeadingView(GroupsViewHolderListener)` | See `setLeadingView` code above | +| Title view | Activity/Fragment | `setTitleView(GroupsViewHolderListener)` | See `setTitleView` code above | +| Trailing view | Activity/Fragment | `setTrailingView(GroupsViewHolderListener)` | See `setTrailingView` code above | +| Entire list item | Activity/Fragment | `setItemView(GroupsViewHolderListener)` | See `setItemView` code above | +| Subtitle view | Activity/Fragment | `setSubtitleView(GroupsViewHolderListener)` | See `setSubtitleView` code above | +| Overflow menu | Activity/Fragment | `setOverflowMenu(View)` | `cometchatGroups.setOverflowMenu(view);` | +| Programmatic selection | Activity/Fragment | `selectGroup(Group, SelectionMode)` | `.selectGroup(group, SelectionMode.SINGLE);` | +| Clear selection | Activity/Fragment | `clearSelection()` | `.clearSelection();` | +| Selected groups strip | Activity/Fragment | `setSelectedGroupsListVisibility(int)` | `.setSelectedGroupsListVisibility(View.VISIBLE);` | +| Internal adapter access | Activity/Fragment | `getAdapter()` / `setAdapter()` | Advanced use only | + +## Accessibility + +The component renders a scrollable `RecyclerView` of interactive group items. Each group row responds to tap and long-press gestures. Avatar images include the group name as content description. Group type indicators (public, private, password-protected) provide visual differentiation. + +For custom views provided via `setLeadingView`, `setTitleView`, `setTrailingView`, or `setItemView`, ensure you set `android:contentDescription` on visual-only elements so TalkBack can announce them. The default views handle this automatically. + +Group type status dots are visual-only by default. If screen reader descriptions are needed, provide them via a custom view with appropriate `contentDescription` attributes. + +## Next Steps + + + + Browse recent conversations + + + Browse and search available users + + + View and manage group members + + + Display messages in a conversation + + \ No newline at end of file diff --git a/ui-kit/android/guide-ai-agent.mdx b/ui-kit/android/guide-ai-agent.mdx index 5c3e55c8a..c6c15e4bd 100644 --- a/ui-kit/android/guide-ai-agent.mdx +++ b/ui-kit/android/guide-ai-agent.mdx @@ -1,8 +1,20 @@ --- title: "AI Agent Integration" sidebarTitle: "AI Agent Integration" +description: "Enable AI-powered conversational assistance with chat history, contextual responses, and seamless handoffs." --- + + +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Key components | `CometChatAIAssistantChatHistory`, `CometChatMessageList`, `CometChatMessageComposer`, `CometChatMessageHeader` | +| Purpose | Enable AI-powered conversational assistance with chat history, contextual responses, and seamless handoffs. | +| Related | [AI Assistant Chat History](/ui-kit/android/ai-assistant-chat-history), [AI Features](/ui-kit/android/ai-features), [All Guides](/ui-kit/android/guide-overview) | + + + Enable intelligent conversational AI capabilities in your Android app using CometChat UIKit v5 with AI Agent integration: - **AI Assistant Chat History** @@ -51,7 +63,9 @@ The AI Agent chat interface provides a familiar messaging experience enhanced wi Create the AI Assistant chat activity with proper theme and layout configuration. -```kotlin + + +```kotlin lines class AIAssistantChatActivity : AppCompatActivity() { private lateinit var binding: ActivityAiAssistantChatBinding @@ -63,19 +77,24 @@ class AIAssistantChatActivity : AppCompatActivity() { val messageJson = intent.getStringExtra(getString(R.string.app_base_message)) val userJson = intent.getStringExtra(getString(R.string.app_user)) - if (userJson != null && !userJson.isEmpty()) - val user = User.fromJson(userJson) - if (messageJson != null && !messageJson.isEmpty()) - val parentMessage = BaseMessage.processMessage(JSONObject(messageJson)) + var user: User? = null + var parentMessage: BaseMessage? = null + + if (!userJson.isNullOrEmpty()) + user = User.fromJson(userJson) + if (!messageJson.isNullOrEmpty()) + parentMessage = BaseMessage.processMessage(JSONObject(messageJson)) initializeComponents(user, parentMessage) initClickListeners() } - private fun initializeComponents(user: User, parentMessage: BaseMessage) { - binding.messageHeader.user = user // Set user for header - binding.messageList.user = user // Set user for message list - binding.messageComposer.user = user // Set user for composer + private fun initializeComponents(user: User?, parentMessage: BaseMessage?) { + user?.let { + binding.messageHeader.user = it // Set user for header + binding.messageList.user = it // Set user for message list + binding.messageComposer.user = it // Set user for composer + } if (parentMessage != null) { // Set message id of parent message to fetch messages with parent. @@ -90,15 +109,65 @@ class AIAssistantChatActivity : AppCompatActivity() { } } ``` + + + +```java lines +public class AIAssistantChatActivity extends AppCompatActivity { + private ActivityAiAssistantChatBinding binding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityAiAssistantChatBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + String messageJson = getIntent().getStringExtra(getString(R.string.app_base_message)); + String userJson = getIntent().getStringExtra(getString(R.string.app_user)); + + User user = null; + BaseMessage parentMessage = null; + + if (userJson != null && !userJson.isEmpty()) + user = User.fromJson(userJson); + if (messageJson != null && !messageJson.isEmpty()) + parentMessage = BaseMessage.processMessage(new JSONObject(messageJson)); + + initializeComponents(user, parentMessage); + initClickListeners(); + } + + private void initializeComponents(User user, BaseMessage parentMessage) { + if (user != null) { + binding.messageHeader.setUser(user); // Set user for header + binding.messageList.setUser(user); // Set user for message list + binding.messageComposer.setUser(user); // Set user for composer + } + + if (parentMessage != null) { + // Set message id of parent message to fetch messages with parent. + // Here we are setting parent message id to message list to fetch messages and message composer to send reply to that message. + // Here this is being used for AIAssistantChatHistory + binding.messageList.setParentMessage(parentMessage.getId()); + binding.messageComposer.setParentMessageId(parentMessage.getId()); + } + + binding.messageList.setStyle(R.style.CustomCometChatMessageListStyle); // Custom style for AI chat + binding.messageComposer.setStyle(R.style.CustomMessageComposerStyle); // Custom style for AI chat + } +} +``` + + **File reference:** -[`AIAssistantChatActivity.kt`](ai-builder/src/main/java/com/cometchat/ai/builder/ui/activity/AIAssistantChatActivity.kt) +[`AIAssistantChatActivity.kt`](https://github.com/cometchat/cometchat-uikit-android/blob/v5/ai-sample-app/src/main/java/com/cometchat/ai/sampleapp/ui/activity/AIAssistantChatActivity.kt) ### Step - 2 AIAssistantChatActivity layout: Add `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to your layout to enable a complete AI chat interface. Use the sample XML below as a reference for correct integration. -```xml +```xml lines ?attr/cometchatBackgroundColor2 @@ -176,8 +245,9 @@ Define custom styles for the message list and composer to differentiate AI agent Initialize click listeners of message header to handle new chat creation and chat history access. -```kotlin - + + +```kotlin lines private fun initClickListeners() { // New chat creation @@ -196,14 +266,40 @@ private fun initClickListeners() { startActivity(intent) } } +``` + + + +```java lines +private void initClickListeners() { + + // New chat creation + binding.messageHeader.setNewChatButtonClick(() -> { + Utils.hideKeyBoard(AIAssistantChatActivity.this, binding.getRoot()); + Intent intent = new Intent(AIAssistantChatActivity.this, AIAssistantChatActivity.class); + intent.putExtra(getString(R.string.app_user), user.toJson().toString()); // Pass user to create new chat + startActivity(intent); + finish(); + }); + // Chat history access + binding.messageHeader.setChatHistoryButtonClick(() -> { + Intent intent = new Intent(AIAssistantChatActivity.this, AIAssistantChatHistoryActivity.class); + intent.putExtra(getString(R.string.app_user), user.toJson().toString()); // Pass user to fetch chat history + startActivity(intent); + }); +} ``` + + ### Step 5 - Create an activity for AIAssistantChatHistory component. Create a new activity to host `CometChatAIAssistantChatHistory` component and handle its interactions. -```kotlin + + +```kotlin lines class AIAssistantChatHistoryActivity : AppCompatActivity() { private lateinit var binding: ActivityAiAssistantChatHistoryBinding private var user: User? = null @@ -248,7 +344,7 @@ class AIAssistantChatHistoryActivity : AppCompatActivity() { } // New chat creation from history screen - binding.cometchatAiAssistantChatHistory.setNewChatButtonClick { + binding.cometchatAiAssistantChatHistory.setOnNewChatClickListener { val intent = Intent(this@AIAssistantChatHistoryActivity, AIAssistantChatActivity::class.java) intent.putExtra(getString(R.string.app_user), user!!.toJson().toString()) // Pass user to create new chat startActivity(intent) @@ -256,18 +352,83 @@ class AIAssistantChatHistoryActivity : AppCompatActivity() { } // Close history screen - binding.cometchatAiAssistantChatHistory.setCloseButtonClick { + binding.cometchatAiAssistantChatHistory.setOnCloseClickListener { // finish the activity } } } ``` + + + +```java lines +public class AIAssistantChatHistoryActivity extends AppCompatActivity { + private ActivityAiAssistantChatHistoryBinding binding; + private User user; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + binding = ActivityAiAssistantChatHistoryBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + String userJson = getIntent().getStringExtra(getString(R.string.app_user)); + + if (userJson != null && !userJson.isEmpty()) { + user = User.fromJson(userJson); + + // Set user to fetch chat history + binding.cometchatAiAssistantChatHistory.setUser(user); + } + + // Use setStyle() method of the component to apply custom styles if needed + // binding.cometchatAiAssistantChatHistory.setStyle(R.style.CustomCometChatAIAssistantChatHistoryStyle); + // See docs of CometChatAIAssistantChatHistory for available style attributes + + // init click listeners + initClickListeners(); + } + + private void initClickListeners() { + // History item click + binding.cometchatAiAssistantChatHistory.setOnItemClickListener((view, position, message) -> { + AppEntity appEntity = message.getReceiver(); + if (appEntity instanceof User) { + user = (User) appEntity; + Intent intent = new Intent(AIAssistantChatHistoryActivity.this, AIAssistantChatActivity.class); + intent.putExtra(getString(R.string.app_user), ((User) appEntity).toJson().toString()); + intent.putExtra( + getString(R.string.app_base_message), + message.getRawMessage().toString() + ); + startActivity(intent); + finish(); + } + }); + + // New chat creation from history screen + binding.cometchatAiAssistantChatHistory.setOnNewChatClickListener(() -> { + Intent intent = new Intent(AIAssistantChatHistoryActivity.this, AIAssistantChatActivity.class); + intent.putExtra(getString(R.string.app_user), user.toJson().toString()); // Pass user to create new chat + startActivity(intent); + finish(); + }); + + // Close history screen + binding.cometchatAiAssistantChatHistory.setOnCloseClickListener(() -> { + // finish the activity + }); + } +} +``` + + ### Step 6 - AIAssistantChatActivity layout: Add `CometChatAIAssistantChatHistory` to your layout to enable access to AI chat history. Use the sample XML below as a reference for correct integration. -```xml +```xml lines + +```kotlin lines // In your main activity or chat list fun launchAIAssistantChat(aiUser: User, parentMessage: BaseMessage? = null) { val intent = Intent(this, AIAssistantChatActivity::class.java) @@ -294,6 +457,19 @@ fun launchAIAssistantChat(aiUser: User, parentMessage: BaseMessage? = null) { startActivity(intent) } ``` + + + +```java lines +// In your main activity or chat list +public void launchAIAssistantChat(User aiUser, BaseMessage parentMessage) { + Intent intent = new Intent(this, AIAssistantChatActivity.class); + intent.putExtra(getString(R.string.app_user), aiUser.toJson().toString()); + startActivity(intent); +} +``` + + ## Implementation Flow Summary @@ -323,7 +499,7 @@ fun launchAIAssistantChat(aiUser: User, parentMessage: BaseMessage? = null) { Explore this feature in the CometChat AI Builder: - [GitHub → AI Builder](https://github.com/cometchat/cometchat-uikit-android/tree/v5/ai-builder) + [GitHub → AI Builder](https://github.com/cometchat/cometchat-uikit-android/tree/v5/ai-sample-app) Explore this feature in the CometChat SampleApp: diff --git a/ui-kit/android/guide-block-unblock-user.mdx b/ui-kit/android/guide-block-unblock-user.mdx index 8249662ee..a82d6a629 100644 --- a/ui-kit/android/guide-block-unblock-user.mdx +++ b/ui-kit/android/guide-block-unblock-user.mdx @@ -1,8 +1,20 @@ --- title: "Block/Unblock User" sidebarTitle: "Block/Unblock User" +description: "Let users block and unblock others directly within chat to control unwanted communication." --- + + +| Field | Value | +| --- | --- | +| Package | `com.cometchat:chat-uikit-android` | +| Key components | `CometChatMessageComposer`, `CometChat.blockUsers()`, `CometChat.unblockUsers()`, `User.isBlockedByMe()` | +| Purpose | Let users block and unblock others directly within chat to control unwanted communication. | +| Related | [Message Composer](/ui-kit/android/message-composer), [Message List](/ui-kit/android/message-list), [All Guides](/ui-kit/android/guide-overview) | + + + Enable users to block and unblock others directly within chat using CometChat’s Android UI Kit v5+, preventing unwanted communication and giving users more control. ## Overview @@ -27,8 +39,8 @@ Blocking a user stops them from sending messages to the blocker. The CometChat U |:-------------------------------------|:------------------------------------------------------------| | `UserDetailActivity.java` | Displays user profile and provides block/unblock options. | | `MessagesActivity.java` | Hosts the chat screen and toggles UI based on block state. | -| `CometChatUIKit.blockUsers()` | API to block one or more users by UID. | -| `CometChatUIKit.unblockUsers()` | API to unblock one or more users by UID. | +| `CometChat.blockUsers()` | SDK API to block one or more users by UID. | +| `CometChat.unblockUsers()` | SDK API to unblock one or more users by UID. | | `User.isBlockedByMe()` | Checks if the current user has blocked this user. | | `unblockLayout` (View) | Layout shown when a user is blocked, containing unblock. | | `CometChatMessageComposer` | Hidden when chatting with a blocked user. | @@ -39,7 +51,20 @@ Blocking a user stops them from sending messages to the blocker. The CometChat U Update UI when block state changes. -```java + + +```kotlin lines +// In MessagesActivity.kt +private fun updateUserBlockStatus(user: User) { + val blocked = user.isBlockedByMe + binding.messageComposer.visibility = if (blocked) View.GONE else View.VISIBLE + binding.unblockLayout.visibility = if (blocked) View.VISIBLE else View.GONE +} +``` + + + +```java lines // In MessagesActivity.java private void updateUserBlockStatus(User user) { boolean blocked = user.isBlockedByMe(); @@ -47,9 +72,11 @@ private void updateUserBlockStatus(User user) { binding.unblockLayout.setVisibility(blocked ? View.VISIBLE : View.GONE); } ``` + + **File reference:** -[`MessagesActivity.java`](https://github.com/cometchat/cometchat-uikit-android/blob/v5/sample-app-java/app/src/main/java/com/cometchat/sampleapp/MessagesActivity.java#L120-L130) +[`MessagesActivity.java`](https://github.com/cometchat/cometchat-uikit-android/blob/v5/sample-app-java/src/main/java/com/cometchat/sampleapp/java/ui/activity/MessagesActivity.java) Ensures the composer and unblock UI reflect the current block state. @@ -57,20 +84,27 @@ Ensures the composer and unblock UI reflect the current block state. Define layout elements and their visibility toggles. -```xml +```xml activity_messages.xml lines - - + + + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:padding="12dp" + android:visibility="gone"> + ); }; - return ; -}; - -export default CallLogDemo; -``` - - - - -```js -import { CometChatCallLogs, CometChatUIKitLoginListener, isMissedCall, isSentByMe, verifyCallUser } from "@cometchat/chat-uikit-react"; - -const CallLogDemo = () => { - const getItemView = (call) => { - const missedCall = isMissedCall(call, CometChatUIKitLoginListener?.getLoggedInUser()!); - const isCallSentByMe = isSentByMe(call, CometChatUIKitLoginListener?.getLoggedInUser()!); - - let callStatus = missedCall - ? "Missed Call" - : isCallSentByMe - ? "Outgoing Call" - : "Incoming Call"; - - let callIcon = missedCall - ? missedIcon - : isCallSentByMe - ? outgoingIcon - : incomingIcon; - - function formatDate(timestamp: number) { - // Convert the timestamp from seconds to milliseconds - const date = new Date(timestamp * 1000); - - // Define options for formatting - const options: Object = { - day: '2-digit', - month: 'short', - hour: '2-digit', - minute: '2-digit', - hour12: true, - }; - - // Format the date with the specified options - return date.toLocaleDateString('en-GB', options); - } - - return ( -
- -
- ) - } - return ; -}; - -export default CallLogDemo; + return ; +} ``` -
- - -```css -.cometchat .cometchat-call-logs .cometchat-list-item__trailing-view { - width: auto; - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - font: 400 14px/120% roboto; - font-style: normal; -} - -.cometchat .cometchat-call-logs .cometchat-avatar { - background-color: #edeafa; -} - -.cometchat .cometchat-call-logs .cometchat-avatar__image { - height: 24px; - width: 24px; -} - -.cometchat .cometchat-call-logs .cometchat-list-item__body-title { - overflow: hidden; - color: #141414; - text-overflow: ellipsis; - white-space: nowrap; - font: 500 16px/19.2px roboto; - font-style: normal; -} - -.cometchat .cometchat-call-logs .cometchat-list-item__body-subtitle { - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - font: 400 14px/120% roboto; - font-style: normal; + +```css lines +.custom-call-log-trailing button { + background: var(--cometchat-primary-color); + color: var(--cometchat-static-white); + border: none; + border-radius: var(--cometchat-radius-2); + padding: 4px 12px; + cursor: pointer; } ``` - - -*** - -#### SubtitleView - -You can customize the subtitle view for each call logs item to meet your requirements. - -Shown below is the default chat interface. - - - - - -The customized chat interface is displayed below. - - - - +### callInitiatedDateTimeFormat -Use the following code to achieve the customization shown above. +Customize the call initiated timestamp format using a `CalendarObject`. - - -```ts +```tsx lines import { CometChatCallLogs, - CometChatUIKitLoginListener, - isMissedCall, - isSentByMe, + CalendarObject, } from "@cometchat/chat-uikit-react"; -import React from "react"; -const CallLogDemo = () => { - const getSubtitleView = (call: any): JSX.Element => { - const missedCall = isMissedCall( - call, - CometChatUIKitLoginListener?.getLoggedInUser()! - ); - const isCallSentByMe = isSentByMe( - call, - CometChatUIKitLoginListener?.getLoggedInUser()! - ); +function CustomDateCallLogs() { + const dateFormat = new CalendarObject({ + today: "hh:mm A", + yesterday: "[yesterday]", + otherDays: "DD MM YYYY", + }); - const iconClass = missedCall - ? "cometchat-call-logs__list-item-subtitle-icon-missed-call" - : isCallSentByMe - ? "cometchat-call-logs__list-item-subtitle-icon-outgoing-call" - : "cometchat-call-logs__list-item-subtitle-icon-incoming-call"; + return ; +} +``` - const callStatus = missedCall - ? "Missed Call" - : isCallSentByMe - ? "Outgoing Call" - : "Incoming Call"; + +If no property is passed in the [CalendarObject](/ui-kit/react/localize#calendarobject), the component checks the [global configuration](/ui-kit/react/localize#customisation) first. If also missing there, the component's default formatting applies. + - return ( - <> -
-
-
- {" "} - {callStatus} -
-
- - ); - }; +--- - return ; -}; +## Common Patterns + +### Custom empty state + +```tsx lines +import { CometChatCallLogs } from "@cometchat/chat-uikit-react"; -export default CallLogDemo; +function EmptyStateCallLogs() { + return ( + +

No call history

+
+ } + /> + ); +} ``` -
+### Filtered to video calls only - -```js -import { CometChatCallLogs,CometChatUIKitLoginListener,isMissedCall,isSentByMe } from "@cometchat/chat-uikit-react"; -import React from "react"; +```tsx lines +import { CallLogRequestBuilder } from "@cometchat/calls-sdk-javascript"; +import { CometChatCallLogs } from "@cometchat/chat-uikit-react"; -const CallLogDemo = () => { - const getSubtitleView = (call) => { +function VideoCallLogs({ authToken }: { authToken: string }) { + return ( + + ); +} +``` - const missedCall = isMissedCall(call, CometChatUIKitLoginListener?.getLoggedInUser()!); - const isCallSentByMe = isSentByMe(call, CometChatUIKitLoginListener?.getLoggedInUser()!); +--- - const iconClass = missedCall - ? "cometchat-call-logs__list-item-subtitle-icon-missed-call" - : isCallSentByMe - ? "cometchat-call-logs__list-item-subtitle-icon-outgoing-call" - : "cometchat-call-logs__list-item-subtitle-icon-incoming-call"; +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens are set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-call-logs`) consumes these tokens via `var()` with fallback values. +3. Overrides target `.cometchat-call-logs` descendant selectors in a global stylesheet. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-call-logs` | +| List item | `.cometchat-call-logs .cometchat-list-item` | +| Active item | `.cometchat-call-logs__list-item-active .cometchat-list-item` | +| Trailing view (video) | `.cometchat-call-logs__list-item-trailing-view-video` | +| Trailing view (audio) | `.cometchat-call-logs__list-item-trailing-view-audio` | +| Subtitle | `.cometchat-call-logs__list-item-subtitle` | +| Subtitle date | `.cometchat-call-logs__list-item-subtitle .cometchat-date` | +| Missed call icon | `.cometchat-call-logs__list-item-subtitle-icon-missed-call` | +| Outgoing call icon | `.cometchat-call-logs__list-item-subtitle-icon-outgoing-call` | +| Incoming call icon | `.cometchat-call-logs__list-item-subtitle-icon-incoming-call` | +| Empty state | `.cometchat-call-logs__empty-state-view` | +| Error state | `.cometchat-call-logs__error-state-view` | +| Shimmer loading | `.cometchat-call-logs__shimmer` | +| Outgoing call overlay | `.cometchat-call-logs__outgoing-call` | + +### Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Component props | `on` callbacks | `onItemClick={(c) => showDetails(c)}` | +| Filter which call logs appear | Component props | `callLogRequestBuilder` | `callLogRequestBuilder={new CallLogRequestBuilder().setLimit(5)}` | +| Replace a section of the list item | Component props | `View` render props | `subtitleView={(c) =>
{c.getStatus()}
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-call-logs` class | `.cometchat-call-logs .cometchat-list-item { background: #f9f8fd; }` | - const callStatus = missedCall - ? "Missed Call" - : isCallSentByMe - ? "Outgoing Call" - : "Incoming Call"; +--- - return ( - <> -
-
-
- {callStatus} -
-
- - ) - } +## Accessibility - return ; -}; +The component renders a scrollable list of interactive items. Each call log row is keyboard-focusable and activates on Enter/Space. Call direction icons (incoming/outgoing/missed) use CSS mask images — add `aria-label` attributes via `itemView` if screen reader descriptions are needed. -export default CallLogDemo; -``` +--- - +--- - -```css -.cometchat-call-logs__list-item-subtitle-text { - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - font: 400 14px/120% Roboto; - font-style: normal; -} -``` +## Props - +All props are optional. - +--- -*** +### activeCall -#### TrailingView +Highlights the currently active/selected call log entry. -You can customize the trailing view for each call logs item to meet your requirements. +| | | +| --- | --- | +| Type | `any` | +| Default | `undefined` | -Shown below is the default chat interface. +--- - - - +### callInitiatedDateTimeFormat -The customized chat interface is displayed below. +Format for displaying the call initiated timestamp. - - - +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default (`DD MMM, hh:mm A`) | -Use the following code to achieve the customization shown above. +Falls back to [global calendar configuration](/ui-kit/react/localize#customisation) if not set. - - -```ts -import { CallLog } from "@cometchat/calls-sdk-javascript"; -import { CometChatCallLogs } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const CallLogDemo = () => { - function formatDate(timestamp: number) { - // Convert the timestamp from seconds to milliseconds - const date = new Date(timestamp * 1000); - - // Define options for formatting - const options: Object = { - day: "2-digit", - month: "short", - hour: "2-digit", - minute: "2-digit", - hour12: true, - }; - - // Format the date with the specified options - return date.toLocaleDateString("en-GB", options); - } +--- - const getTrailingView = (call: any) => { - return ( -
- {formatDate(call?.getInitiatedAt())} -
- ); - }; +### callLogRequestBuilder - return ; -}; +Controls which call logs load and in what order. -export default CallLogDemo; -``` +| | | +| --- | --- | +| Type | `any` (CallLogRequestBuilder from `@cometchat/calls-sdk-javascript`) | +| Default | SDK default (30 per page) | -
+--- - -```js -import { CometChatCallLogs } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const CallLogDemo = () => { - function formatDate(timestamp) { - // Convert the timestamp from seconds to milliseconds - const date = new Date(timestamp * 1000); - - // Define options for formatting - const options = { - day: "2-digit", - month: "short", - hour: "2-digit", - minute: "2-digit", - hour12: true, - }; - - // Format the date with the specified options - return date.toLocaleDateString("en-GB", options); - } +### emptyView - const getTrailingView = (call) => { - return ( -
- {formatDate(call?.getInitiatedAt())} -
- ); - }; +Custom component displayed when there are no call logs. - return ; -}; +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in empty state | -export default CallLogDemo; -``` +--- -
+### errorView - -```css -.cometchat .cometchat-call-logs .cometchat-list-item__trailing-view { - width: auto; - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - font: 400 14px/120% roboto; - font-style: normal; -} -``` +Custom component displayed when an error occurs. - +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in error state | -
+--- -#### LeadingView +### itemView -You can customize the leading view for each call logs item to meet your requirements. +Custom renderer for the entire call log list item. -Shown below is the default chat interface. +| | | +| --- | --- | +| Type | `(call: any) => JSX.Element` | +| Default | Built-in list item | - - - +--- -The customized chat interface is displayed below. +### leadingView - - - +Custom renderer for the avatar / left section. -Use the following code to achieve the customization shown above. +| | | +| --- | --- | +| Type | `(call: any) => JSX.Element` | +| Default | Built-in avatar | - - -```ts -import { CallLog } from "@cometchat/calls-sdk-javascript"; -import { - CometChatUIKitLoginListener, - CometChatCallLogs, -} from "@cometchat/chat-uikit-react"; -import React from "react"; +--- -const CallLogDemo = () => { - const getLeadingView = (call: any) => { - const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - return ( -
- {call.status === "unanswered" || call.status === "cancelled" ? ( -
- ) : call.initiator?.uid === loggedInUser?.getUid() ? ( -
- ) : ( -
- )} -
- ); - }; +### loadingView - return ; -}; +Custom component displayed during the loading state. -export default CallLogDemo; -``` +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in shimmer | - +--- - -```js -import { - CometChatUIKitLoginListener, - CometChatCallLogs, -} from "@cometchat/chat-uikit-react"; -import React from "react"; +### onCallButtonClicked -const CallLogDemo = () => { - const getLeadingView = (call) => { - const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - return ( -
- {call.status === "unanswered" || call.status === "cancelled" ? ( -
- ) : call.initiator?.uid === loggedInUser?.getUid() ? ( -
- ) : ( -
- )} -
- ); - }; +Callback fired when the call-back button is clicked. - return ; -}; +| | | +| --- | --- | +| Type | `(call: any) => void` | +| Default | `undefined` | -export default CallLogDemo; -``` +--- - +### onError - -```css -.call-log-avatar { - display: flex; - width: 48px; - height: 48px; - padding: 8px; - justify-content: center; - align-items: center; - border-radius: 1000px; - background: #edeafa; -} +Callback fired when the component encounters an error. -.call-log-missed { - background-image: url(""); - background-size: contain; - height: 32px; - width: 32px; -} +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | -.call-log-incoming { - background-image: url(""); - background-size: contain; - height: 32px; - width: 32px; -} +--- -.call-log-outgoing { - background-image: url(""); - background-size: contain; - height: 32px; - width: 32px; -} -``` +### onItemClick - +Callback fired when a call log entry is clicked. - +| | | +| --- | --- | +| Type | `(call: any) => void` | +| Default | `undefined` | -#### TitleView +--- -You can customize the title view for each call logs item to meet your requirements. +### showScrollbar -Shown below is the default chat interface. +Shows the scrollbar in the call log list. - - - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -The customized chat interface is displayed below. +--- - - - +### subtitleView -Use the following code to achieve the customization shown above. +Custom renderer for the subtitle text. - - -```ts -import { CallLog } from "@cometchat/calls-sdk-javascript"; -import { CometChatCallLogs } from "@cometchat/chat-uikit-react"; -import React from "react"; +| | | +| --- | --- | +| Type | `(call: any) => JSX.Element` | +| Default | Built-in subtitle | -const CallLogDemo = () => { - const getTitleView = (call: any) => { - return ( -
- {call.initiator?.name} - {call.status !== "unanswered" && call.status !== "cancelled" && ( - <>{" • 🕚️ " + Math.ceil(call.totalDurationInMinutes) + " mins"} - )} -
- ); - }; +--- - return ; -}; +### titleView -export default CallLogDemo; -``` +Custom renderer for the name / title text. -
+| | | +| --- | --- | +| Type | `(call: any) => JSX.Element` | +| Default | Built-in title | - -```js -import { CometChatCallLogs } from "@cometchat/chat-uikit-react"; -import React from "react"; +--- -const CallLogDemo = () => { - const getTitleView = (call) => { - return ( -
- {call.initiator?.name} - {call.status !== "unanswered" && call.status !== "cancelled" && ( - <>{" • 🕚️ " + Math.ceil(call.totalDurationInMinutes) + " mins"} - )} -
- ); - }; +### trailingView - return ; -}; +Custom renderer for the right section. -export default CallLogDemo; -``` +| | | +| --- | --- | +| Type | `(call: any) => JSX.Element` | +| Default | Built-in trailing view | -
+--- - -```css -.call-log-title { - overflow: hidden; - color: #141414; - text-overflow: ellipsis; - white-space: nowrap; - font: 500 16px Roboto; -} -``` +## Events - +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatMessageEvents.ccMessageSent` | `IMessages` | Call message sent | -
+--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-call-logs` | +| List item | `.cometchat-call-logs .cometchat-list-item` | +| Active item | `.cometchat-call-logs__list-item-active .cometchat-list-item` | +| Trailing view (video) | `.cometchat-call-logs__list-item-trailing-view-video` | +| Trailing view (audio) | `.cometchat-call-logs__list-item-trailing-view-audio` | +| Subtitle | `.cometchat-call-logs__list-item-subtitle` | +| Subtitle date | `.cometchat-call-logs__list-item-subtitle .cometchat-date` | +| Missed call icon | `.cometchat-call-logs__list-item-subtitle-icon-missed-call` | +| Outgoing call icon | `.cometchat-call-logs__list-item-subtitle-icon-outgoing-call` | +| Incoming call icon | `.cometchat-call-logs__list-item-subtitle-icon-incoming-call` | +| Empty state | `.cometchat-call-logs__empty-state-view` | +| Error state | `.cometchat-call-logs__error-state-view` | +| Shimmer loading | `.cometchat-call-logs__shimmer` | +| Outgoing call overlay | `.cometchat-call-logs__outgoing-call` | diff --git a/ui-kit/react/components-overview.mdx b/ui-kit/react/components-overview.mdx index dfc456255..f72976221 100644 --- a/ui-kit/react/components-overview.mdx +++ b/ui-kit/react/components-overview.mdx @@ -1,29 +1,167 @@ --- title: "Overview" +description: "Browse all prebuilt UI components in the CometChat React UI Kit — conversations, messages, users, groups, calls, search, and AI." --- -CometChat's **UI Kit** is a set of pre-built UI components that allows you to easily craft an in-app chat with all the essential messaging features. + -## Actions +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Required setup | `CometChatUIKit.init()` + `CometChatUIKit.login()` before rendering any component | +| Callback actions | `on={(param) => {}}` | +| Data filtering | `RequestBuilder={new CometChat.RequestBuilder()}` | +| Toggle features | `hide={true}` or `show={true}` | +| Custom rendering | `View={() => JSX}` | +| CSS overrides | Target `.cometchat-` class in global CSS | +| Calling | Requires separate `@cometchat/calls-sdk-javascript` package | -Actions direct the operational behavior of a component. They are split into two categories: Predefined Actions and User-Defined Actions. + -### Predefined Actions +## Architecture -These are actions that are inherently programmed into a UI component. They are ingrained in the component itself by default, and they execute automatically in response to user interaction, without needing any additional user input. +The UI Kit is a set of independent components that compose into chat layouts. A typical two-panel layout uses four core components: -### User-Defined Actions +- **CometChatConversations** — sidebar listing recent conversations (users and groups) +- **CometChatMessageHeader** — toolbar showing avatar, name, online status, and typing indicator +- **CometChatMessageList** — scrollable message feed with reactions, receipts, and threads +- **CometChatMessageComposer** — rich text input with attachments, mentions, and voice notes -These are actions that must be explicitly specified by the user. They are not innately part of the component like predefined actions. Instead, they must be developed based on the unique needs of the user or the application. User-defined actions provide adaptability and allow for the creation of custom behaviors that align with the individual needs of the application. +Data flow: selecting a conversation in CometChatConversations yields a `CometChat.User` or `CometChat.Group` object. That object is passed as a prop (`user` or `group`) to CometChatMessageHeader, CometChatMessageList, and CometChatMessageComposer. The message components use the SDK internally — CometChatMessageComposer sends messages, CometChatMessageList receives them via real-time listeners. -To customize the behavior of a component, actions can be overridden by you. This provides you with control over how the component responds to specific events or interactions. +Components communicate through a publish/subscribe event bus (`CometChatMessageEvents`, `CometChatConversationEvents`, `CometChatGroupEvents`, etc.). A component emits events that other components or application code can subscribe to without direct references. See [Events](/ui-kit/react/events) for the full list. -All components expose actions to the user, which means that users can interact with these types of components through predefined or user-defined actions. +Each component accepts callback props (`on`), view slot props (`View`) for replacing UI sections, `RequestBuilder` props for data filtering, and CSS variable overrides on `.cometchat-` classes. -*** +--- + +## Component Catalog + +All components are imported from `@cometchat/chat-uikit-react`. + +### Conversations and Lists + +| Component | Purpose | Key Props | Page | +| --- | --- | --- | --- | +| CometChatConversations | Scrollable list of recent conversations | `conversationsRequestBuilder`, `onItemClick`, `onError` | [Conversations](/ui-kit/react/conversations) | +| CometChatUsers | Scrollable list of users | `usersRequestBuilder`, `onItemClick`, `onError` | [Users](/ui-kit/react/users) | +| CometChatGroups | Scrollable list of groups | `groupsRequestBuilder`, `onItemClick`, `onError` | [Groups](/ui-kit/react/groups) | +| CometChatGroupMembers | Scrollable list of group members | `group`, `groupMemberRequestBuilder`, `onItemClick` | [Group Members](/ui-kit/react/group-members) | + +### Messages + +| Component | Purpose | Key Props | Page | +| --- | --- | --- | --- | +| CometChatMessageHeader | Toolbar with avatar, name, status, typing indicator | `user`, `group`, `enableAutoSummaryGeneration` | [Message Header](/ui-kit/react/message-header) | +| CometChatMessageList | Scrollable message list with reactions, receipts, threads | `user`, `group`, `messagesRequestBuilder`, `goToMessageId` (string) | [Message List](/ui-kit/react/message-list) | +| CometChatMessageComposer | Rich text input with attachments, mentions, voice notes | `user`, `group`, `onSendButtonClick`, `placeholderText` | [Message Composer](/ui-kit/react/message-composer) | +| CometChatMessageTemplate | Pre-defined structure for custom message bubbles | `type`, `category`, `contentView`, `headerView`, `footerView` | [Message Template](/ui-kit/react/message-template) | +| CometChatThreadHeader | Parent message bubble and reply count for threaded view | `parentMessage`, `onClose`, `hideReceipts`, `textFormatters` | [Thread Header](/ui-kit/react/thread-header) | + +### Calling + +| Component | Purpose | Key Props | Page | +| --- | --- | --- | --- | +| CometChatCallButtons | Voice and video call initiation buttons | `user`, `group`, `onVoiceCallClick`, `onVideoCallClick` | [Call Buttons](/ui-kit/react/call-buttons) | +| CometChatIncomingCall | Incoming call notification with accept/decline | `call`, `onAccept(call)`, `onDecline(call)` | [Incoming Call](/ui-kit/react/incoming-call) | +| CometChatOutgoingCall | Outgoing call screen with cancel control | `call`, `onCloseClicked` | [Outgoing Call](/ui-kit/react/outgoing-call) | +| CometChatCallLogs | Scrollable list of call history | `callLogsRequestBuilder`, `onItemClick` | [Call Logs](/ui-kit/react/call-logs) | + +### Search and AI + +| Component | Purpose | Key Props | Page | +| --- | --- | --- | --- | +| CometChatSearch | Real-time search across conversations and messages | `onConversationClicked(conversation, searchKeyword?)`, `onMessageClicked(message, searchKeyword?)`, `uid`, `guid`, `textFormatters` | [Search](/ui-kit/react/search) | +| CometChatAIAssistantChat | AI agent chat with streaming, suggestions, history | `user`, `onSendButtonClick(message, previewMessageMode?)`, `aiAssistantTools` | [AI Assistant Chat](/ui-kit/react/ai-assistant-chat) | + +## Component API Pattern + +All components share a consistent API surface. + +### Actions + +Actions control component behavior. They split into two categories: + +**Predefined Actions** are built into the component and execute automatically on user interaction (e.g., clicking send dispatches the message). No configuration needed. + +**User-Defined Actions** are callback props that fire on specific events. Override them to customize behavior: -## Events +```tsx lines + openThreadPanel(message)} + onError={(error) => logError(error)} +/> +``` + +### Events + +Events enable decoupled communication between components. A component emits events that other parts of the application can subscribe to without direct references. + +```tsx lines +import { CometChatMessageEvents } from "@cometchat/chat-uikit-react"; + +const sub = CometChatMessageEvents.ccMessageSent.subscribe((message) => { + // react to sent message +}); + +// cleanup +sub?.unsubscribe(); +``` + +Each component page documents its emitted events in the Events section. + +### Filters + +List-based components accept `RequestBuilder` props to control which data loads: + +```tsx lines + +``` + +### Custom View Slots + +Components expose named view slots to replace sections of the default UI: + +```tsx lines +} + subtitleView={} + leadingView={} +/> +``` + +### CSS Overrides + +Every component has a root CSS class (`.cometchat-`) for style customization: + +```css lines +.cometchat-message-list .cometchat-text-bubble__body-text { + font-family: "SF Pro"; +} +``` + +--- -Events allow for a decoupled, flexible architecture where different parts of the application can interact without having to directly reference each other. This makes it easier to create complex, interactive experiences, as well as to extend and customize the functionality provided by the CometChat UI Kit. +## Next Steps -All Components have the ability to emit events. These events are dispatched in response to certain changes or user interactions within the component. By emitting events, these components allow other parts of the application to react to changes or interactions, thus enabling dynamic and interactive behavior within the application. + + + Chat features included out of the box + + + Customize colors, fonts, and styles + + + Add-on features like polls, stickers, and translation + + + Task-oriented tutorials for common patterns + + diff --git a/ui-kit/react/conversations.mdx b/ui-kit/react/conversations.mdx index a148e2bb6..0f42cc5cd 100644 --- a/ui-kit/react/conversations.mdx +++ b/ui-kit/react/conversations.mdx @@ -1,380 +1,505 @@ --- title: "Conversations" +description: "Scrollable list of recent one-on-one and group conversations for the logged-in user." --- + +```json +{ + "component": "CometChatConversations", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatConversations } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Scrollable list of recent one-on-one and group conversations for the logged-in user.", + "cssRootClass": ".cometchat-conversations", + "primaryOutput": { + "prop": "onItemClick", + "type": "(conversation: CometChat.Conversation) => void" + }, + "props": { + "data": { + "conversationsRequestBuilder": { + "type": "CometChat.ConversationsRequestBuilder", + "default": "SDK default (30 per page)", + "note": "Pass the builder, not the result of .build()" + }, + "activeConversation": { + "type": "CometChat.Conversation", + "default": "undefined" + }, + "lastMessageDateTimeFormat": { + "type": "CalendarObject", + "default": "Component default (hh:mm A today, [yesterday], DD/MM/YYYY other days)", + "note": "Falls back to global CometChatLocalize.calendarObject if not set" + } + }, + "callbacks": { + "onItemClick": "(conversation: CometChat.Conversation) => void", + "onSelect": "(conversation: CometChat.Conversation, selected: boolean) => void", + "onError": "((error: CometChat.CometChatException) => void) | null", + "onSearchBarClicked": "() => void" + }, + "visibility": { + "hideReceipts": { "type": "boolean", "default": false }, + "hideError": { "type": "boolean", "default": false }, + "hideDeleteConversation": { "type": "boolean", "default": false }, + "hideUserStatus": { "type": "boolean", "default": false }, + "hideGroupType": { "type": "boolean", "default": false }, + "showSearchBar": { "type": "boolean", "default": false }, + "showScrollbar": { "type": "boolean", "default": false } + }, + "sound": { + "disableSoundForMessages": { "type": "boolean", "default": false }, + "customSoundForMessages": { "type": "string", "default": "built-in" } + }, + "selection": { + "selectionMode": { + "type": "SelectionMode", + "values": ["SelectionMode.single (0)", "SelectionMode.multiple (1)", "SelectionMode.none (2)"], + "default": "SelectionMode.none" + } + }, + "viewSlots": { + "itemView": "(conversation: CometChat.Conversation) => JSX.Element", + "leadingView": "(conversation: CometChat.Conversation) => JSX.Element", + "titleView": "(conversation: CometChat.Conversation) => JSX.Element", + "subtitleView": "(conversation: CometChat.Conversation) => JSX.Element", + "trailingView": "(conversation: CometChat.Conversation) => JSX.Element", + "headerView": "JSX.Element", + "searchView": "JSX.Element", + "loadingView": "JSX.Element", + "emptyView": "JSX.Element", + "errorView": "JSX.Element", + "options": "((conversation: CometChat.Conversation) => CometChatOption[]) | null" + }, + "formatting": { + "textFormatters": { + "type": "CometChatTextFormatter[]", + "default": "default formatters from data source" + } + } + }, + "events": [ + { + "name": "CometChatConversationEvents.ccConversationDeleted", + "payload": "CometChat.Conversation", + "description": "Conversation deleted from list" + }, + { + "name": "CometChatConversationEvents.ccUpdateConversation", + "payload": "CometChat.Conversation", + "description": "Conversation updated" + }, + { + "name": "CometChatConversationEvents.ccMarkConversationAsRead", + "payload": "CometChat.Conversation", + "description": "Conversation marked as read" + } + ], + "sdkListeners": [ + "onTextMessageReceived", + "onMediaMessageReceived", + "onCustomMessageReceived", + "onTypingStarted", + "onTypingEnded", + "onMessagesDelivered", + "onMessagesRead", + "onMessagesDeliveredToAll", + "onMessagesReadByAll", + "onUserOnline", + "onUserOffline", + "onGroupMemberJoined", + "onGroupMemberLeft", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onMemberAddedToGroup" + ], + "compositionExample": { + "description": "Sidebar conversations wired to message view", + "components": [ + "CometChatConversations", + "CometChatMessageHeader", + "CometChatMessageList", + "CometChatMessageComposer" + ], + "flow": "onItemClick emits CometChat.Conversation -> extract User/Group via getConversationWith() -> pass to MessageHeader, MessageList, MessageComposer" + }, + "types": { + "CalendarObject": { + "today": "string | undefined", + "yesterday": "string | undefined", + "lastWeek": "string | undefined", + "otherDays": "string | undefined", + "relativeTime": { + "minute": "string | undefined", + "minutes": "string | undefined", + "hour": "string | undefined", + "hours": "string | undefined" + } + }, + "CometChatOption": { + "id": "string | undefined", + "title": "string | undefined", + "iconURL": "string | undefined", + "onClick": "(() => void) | undefined" + }, + "SelectionMode": { + "single": 0, + "multiple": 1, + "none": 2 + } + } +} +``` + -## Overview - -The Conversations is a Component, that shows all conversations related to the currently logged-in user. - -This component lists the most recent or latest conversations or contacts with whom you have exchanged messages. It provides a convenient way to quickly access and resume conversations with the people you have been in contact with recently. - - - - - -## Usage +## Where It Fits -### Integration +`CometChatConversations` is a sidebar list component. It renders recent conversations and emits the selected `CometChat.Conversation` via `onItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a standard two-panel chat layout. - - -```tsx +```tsx lines +import { useState } from "react"; import { CometChatConversations, - TitleAlignment, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatApp() { + const [selectedUser, setSelectedUser] = useState(); + const [selectedGroup, setSelectedGroup] = useState(); + + const handleItemClick = (conversation: CometChat.Conversation) => { + const entity = conversation.getConversationWith(); + if (entity instanceof CometChat.User) { + setSelectedUser(entity); + setSelectedGroup(undefined); + } else if (entity instanceof CometChat.Group) { + setSelectedGroup(entity); + setSelectedUser(undefined); + } + }; -function ConversationsDemo() { return ( -
-
- +
+
+
+ {selectedUser || selectedGroup ? ( +
+ + + +
+ ) : ( +
+ Select a conversation +
+ )}
); } - -export default ConversationsDemo; ``` - +[Open in CodeSandbox](https://link.cometchat.com/react-conversation-list-message) + + + + + +--- + +## Minimal Render - -```tsx -import { ConversationsDemo } from "./ConversationsDemo"; +```tsx lines +import { CometChatConversations } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; -export default function App() { +function ConversationsDemo() { return ( -
- +
+
); } -``` - +export default ConversationsDemo; +``` - + + + -### Actions +Root CSS class: `.cometchat-conversations` -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +--- -#### 1. OnItemClick +## Filtering Conversations -`OnItemClick` is triggered when you click on a ListItem of the Conversations component. The `OnItemClick` action doesn't have a predefined behavior. You can override this action using the following code snippet. +Pass a `CometChat.ConversationsRequestBuilder` to `conversationsRequestBuilder`. Pass the builder instance — not the result of `.build()`. - - -```tsx +```tsx lines import { CometChatConversations } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const getOnItemClick = (conversation: CometChat.Conversation) => { - console.log("ItemClick:", conversation); - // Your custom action here -}; - -; +function FilteredConversations() { + return ( + + ); +} ``` - - - - -*** - -#### 2. OnSelect +### Filter Recipes -The `OnSelect` event is triggered upon the completion of a selection in `SelectionMode`. It does not have a default behavior. However, you can override its behavior using the following code snippet. +| Recipe | Code | +| --- | --- | +| Only user conversations | `new CometChat.ConversationsRequestBuilder().setConversationType("user")` | +| Only group conversations | `new CometChat.ConversationsRequestBuilder().setConversationType("group")` | +| Limit to 10 per page | `new CometChat.ConversationsRequestBuilder().setLimit(10)` | +| With specific tags | `new CometChat.ConversationsRequestBuilder().setTags(["vip"])` | +| Filter by user tags | `new CometChat.ConversationsRequestBuilder().withUserAndGroupTags(true).setUserTags(["premium"])` | +| Filter by group tags | `new CometChat.ConversationsRequestBuilder().withUserAndGroupTags(true).setGroupTags(["support"])` | - - -```tsx -import { - CometChatConversations, - SelectionMode, -} from "@cometchat/chat-uikit-react"; +Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom. -const getOnSelect = ( - conversation: CometChat.Conversation, - selected: boolean -) => { - console.log("Selected, ", conversation.getConversationId(), selected); - // Your custom action on select -}; - -; -``` +Refer to [ConversationRequestBuilder](/sdk/javascript/retrieve-conversations) for the full builder API. - +--- - +## Actions and Events -*** +### Callback Props -#### 3. OnError +#### onItemClick -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Conversations component. +Fires when a conversation row is tapped. Primary navigation hook — set the active conversation and render the message view. - - -```tsx +```tsx lines import { CometChatConversations } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const handleOnError = (error: CometChat.CometChatException) => { - // Your exception handling code -}; +function ConversationsWithClick() { + const handleItemClick = (conversation: CometChat.Conversation) => { + console.log("Selected:", conversation.getConversationId()); + }; -; + return ; +} ``` - - - - -*** +#### onSelect -#### 4. onSearchBarClicked +Fires when a conversation is checked/unchecked in multi-select mode. Requires `selectionMode` to be set. -The `onSearchBarClicked` event is triggered when the user clicks the search bar. It does not have a default behavior. However, you can override its behavior using the following code snippet. +```tsx lines +import { useState } from "react"; +import { + CometChatConversations, + SelectionMode, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; - - -```tsx -import { CometChatConversations } from "@cometchat/chat-uikit-react"; +function BatchSelectDemo() { + const [selected, setSelected] = useState>(new Set()); -const handleSearchClick = () => { - console.log("Search bar clicked"); -}; + const handleSelect = (conversation: CometChat.Conversation, isSelected: boolean) => { + setSelected((prev) => { + const next = new Set(prev); + const id = conversation.getConversationId(); + isSelected ? next.add(id) : next.delete(id); + return next; + }); + }; -; + return ( + + ); +} ``` - - - - -*** - -### Filters - -You can set `ConversationsRequestBuilder` in the Conversations Component to filter the conversation list. You can modify the builder as per your specific requirements with multiple options available to know more refer to [ConversationRequestBuilder](/sdk/javascript/retrieve-conversations). +#### onError -You can set filters using the following parameters. +Fires on internal errors (network failure, auth issue, SDK exception). -1. **Conversation Type:** Filters on type of Conversation, `User` or `Groups` -2. **Limit:** Number of conversations fetched in a single request. -3. **WithTags:** Filter on fetching conversations containing tags -4. **Tags:** Filters on specific `Tag` -5. **UserTags:** Filters on specific User `Tag` -6. **GroupTags:** Filters on specific Group `Tag` - - - -```tsx +```tsx lines import { CometChatConversations } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -; -``` - - - - - -*** - -### Events - -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. - - - -```tsxtsx -const ccConversationDeleted = - CometChatConversationEvents.ccConversationDeleted.subscribe( - (conversation: CometChat.Conversation) => { - // Your code here - } +function ConversationsWithErrorHandler() { + return ( + { + console.error("CometChatConversations error:", error); + }} + /> ); +} ``` - - - - -*** - - - -```tsxtsx -ccConversationDeleted?.unsubscribe(); -``` - - - - - -## Customization - -To fit your app's design requirements, you can customize the appearance of the conversation component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. +#### onSearchBarClicked -### Style +Fires when the search bar is clicked. Requires `showSearchBar={true}`. -Using CSS you can customize the look and feel of the component in your app like the color, size, shape, and fonts. - - - - +```tsx lines +import { CometChatConversations } from "@cometchat/chat-uikit-react"; - - -```tsx - +function ConversationsWithSearch() { + return ( + { + console.log("Search bar clicked"); + }} + /> + ); +} ``` - +### Global UI Events - -```css -.cometchat-conversations .cometchat-list-item__body-title, -.cometchat-conversations .cometchat-list__header-title, -.cometchat-conversations .cometchat-avatar__text, -.cometchat-conversations .cometchat-badge, -.cometchat-conversations .cometchat-conversations__subtitle-text { - font-family: "SF Pro"; -} +`CometChatConversationEvents` emits events subscribable from anywhere in the application. Subscribe in a `useEffect` and unsubscribe on cleanup. -.cometchat-conversations .cometchat-list__header-title { - background: #fef8f8; - border-bottom: 2px solid #f4b6b8; -} +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccConversationDeleted` | A conversation is deleted from the list | `CometChat.Conversation` | +| `ccUpdateConversation` | A conversation is updated (last message change, metadata update) | `CometChat.Conversation` | +| `ccMarkConversationAsRead` | A conversation is marked as read | `CometChat.Conversation` | -.cometchat-conversations .cometchat-avatar { - background: #f0999b; -} +When to use: sync external UI with conversation state changes. For example, update an unread count badge in a tab bar when `ccMarkConversationAsRead` fires, or remove a conversation from a custom sidebar when `ccConversationDeleted` fires. -.cometchat-conversations .cometchat-status-indicator { - min-width: 10px; - height: 10px; -} +```tsx lines +import { useEffect } from "react"; +import { CometChatConversationEvents } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -.cometchat-conversations .cometchat-badge { - background: #e5484d; -} +function useConversationEvents() { + useEffect(() => { + const deletedSub = CometChatConversationEvents.ccConversationDeleted.subscribe( + (conversation: CometChat.Conversation) => { + console.log("Deleted:", conversation.getConversationId()); + } + ); + const updatedSub = CometChatConversationEvents.ccUpdateConversation.subscribe( + (conversation: CometChat.Conversation) => { + console.log("Updated:", conversation.getConversationId()); + } + ); + const readSub = CometChatConversationEvents.ccMarkConversationAsRead.subscribe( + (conversation: CometChat.Conversation) => { + console.log("Marked as read:", conversation.getConversationId()); + } + ); -.cometchat-conversations .cometchat-receipts-read { - background: #e96b6f; + return () => { + deletedSub?.unsubscribe(); + updatedSub?.unsubscribe(); + readSub?.unsubscribe(); + }; + }, []); } ``` - - - - -### Functionality +### SDK Events (Real-Time, Automatic) -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. +The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required. - - -```tsx -
-
- -
-
-``` +| SDK Listener | Internal behavior | +| --- | --- | +| `onTextMessageReceived` / `onMediaMessageReceived` / `onCustomMessageReceived` | Moves conversation to top, updates last message preview and unread count | +| `onTypingStarted` / `onTypingEnded` | Shows/hides typing indicator in the subtitle | +| `onMessagesDelivered` / `onMessagesRead` / `onMessagesDeliveredToAll` / `onMessagesReadByAll` | Updates receipt ticks (unless `hideReceipts={true}`) | +| `onUserOnline` / `onUserOffline` | Updates online/offline status dot (unless `hideUserStatus={true}`) | +| `onGroupMemberJoined` / `onGroupMemberLeft` / `onGroupMemberKicked` / `onGroupMemberBanned` / `onMemberAddedToGroup` | Updates group conversation metadata | -
+Automatic: new messages, typing indicators, receipts, user presence, group membership changes. -
+Manual: deleting a conversation via the SDK directly (not through the component's context menu) requires emitting `CometChatConversationEvents.ccConversationDeleted` for the UI to update. -Below is a list of customizations along with corresponding code snippets + +In React 18 StrictMode, `useEffect` runs twice on mount in development. The component handles listener cleanup internally, but any additional listeners added alongside the component need cleanup in the `useEffect` return function to avoid duplicate event handling. + -| Property | Description | Code | -| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | -| **Hide Receipts** | Disables the display of message read receipts. If set to `true`, the receipt status of the sent message won't be displayed. | `hideReceipts={false}` | -| **Hide Error** | Hides the default and the custom error view passed in the `errorView` prop. | `hideError={true}` | -| **Hide Delete Conversation** | Hides the delete conversation option in the default context menu. | `hideDeleteConversation={false}` | -| **Hide User Status** | Hides the user's online/offline status indicator. | `hideUserStatus={true}` | -| **Hide Group Type** | Hides the group type icon. | `hideGroupType={false}` | -| **Show Search Bar** | Shows the search bar. | `showSearchBar={true}` | -| **Active Conversation** | Specifies the conversation to highlight in the list. | `activeConversation={activeConversation}` | -| **Selection Mode** | Determines the selection mode for the component. | `selectionMode={SelectionMode.multiple}` | -| **Disable Sound For Messages** | Used to Disable sound for incoming messages. | `disableSoundForMessages={false}` | -| **Custom Sound For Messages** | Custom audio sound for incoming messages. | `customSoundForMessages="Your custom sound url"` | -| **Search View** | A custom search view which replaces the default search bar. | `searchView={<>Custom Search View}` | -| **Loading View** | A custom component to display during the loading state. | `loadingView={<>Custom Loading View}` | -| **Empty View** | A custom component to display when there are no conversations available. | `emptyView={<>Custom Empty View}` | -| **Error View** | A custom component to display when an error occurs. | `errorView={<>Custom Error View}` | +--- -### Advanced +## Custom View Slots -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. +Each slot replaces a section of the default UI. Slots that accept a conversation parameter receive the `CometChat.Conversation` object for that row. -*** +| Slot | Signature | Replaces | +| --- | --- | --- | +| `itemView` | `(conversation: CometChat.Conversation) => JSX.Element` | Entire list item row | +| `leadingView` | `(conversation: CometChat.Conversation) => JSX.Element` | Avatar / left section | +| `titleView` | `(conversation: CometChat.Conversation) => JSX.Element` | Name / title text | +| `subtitleView` | `(conversation: CometChat.Conversation) => JSX.Element` | Last message preview | +| `trailingView` | `(conversation: CometChat.Conversation) => JSX.Element` | Timestamp / badge / right section | +| `headerView` | `JSX.Element` | Entire header bar | +| `searchView` | `JSX.Element` | Search bar | +| `loadingView` | `JSX.Element` | Loading spinner | +| `emptyView` | `JSX.Element` | Empty state | +| `errorView` | `JSX.Element` | Error state | +| `options` | `(conversation: CometChat.Conversation) => CometChatOption[]` | Context menu / hover actions | -#### ItemView +### itemView -With this function, you can assign a custom ListItem to the Conversations Component. +Replace the entire list item row. -Shown below is the default chat interface. +Default: -The customized chat interface is displayed below. +Customized: -Use the following code to achieve the customization shown above. - -```ts +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatListItem, CometChatConversations, + CometChatDate, } from "@cometchat/chat-uikit-react"; -const getItemView = (conversation: CometChat.Conversation) => { - const title = conversation.getConversationWith().getName(); - const timestamp = conversation?.getLastMessage()?.getSentAt(); +function CustomItemViewConversations() { + const getItemView = (conversation: CometChat.Conversation) => { + const title = conversation.getConversationWith().getName(); + const timestamp = conversation?.getLastMessage()?.getSentAt(); - return ( - } - onListItemClicked={() => { - // Logic here - }} - /> - ); -}; + return ( + } + onListItemClicked={() => { + // handle click + }} + /> + ); + }; -; + return ; +} ``` - - - -```css + +```css lines .cometchat-conversations .cometchat-avatar { border-radius: 8px; width: 32px; @@ -385,165 +510,140 @@ const getItemView = (conversation: CometChat.Conversation) => { gap: 4px; } ``` - - -*** +### leadingView -#### LeadingView - -The customized chat interface is displayed below. +Replace the avatar / left section. Typing-aware avatar example. -Use the following code to achieve the customization shown above. - - - -```ts -import React from "react"; +```tsx lines +import { useEffect, useRef, useState } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatConversations, CometChatAvatar, + CometChatUIKitLoginListener, } from "@cometchat/chat-uikit-react"; -import { useEffect, useRef, useState } from "react"; -const [isTyping, setIsTyping] = useState(false); -const typingObjRef = useRef(null); - -useEffect(() => { - //adding typing listeners - const messageListenerId: string = "typing_demo_" + new Date().getTime(); - CometChat.addMessageListener( - messageListenerId, - new CometChat.MessageListener({ - onTypingStarted: (typingIndicator: CometChat.TypingIndicator) => { - typingObjRef.current = typingIndicator; - setIsTyping(true); - }, - onTypingEnded: (typingIndicator: CometChat.TypingIndicator) => { - if ( - typingObjRef.current && - typingObjRef.current.getSender().getUid() == - typingIndicator.getSender().getUid() - ) { - typingObjRef.current = null; - setIsTyping(false); - } - }, - }) - ); - return () => { - CometChat.removeMessageListener(messageListenerId); - }; -}, [setIsTyping]); - -// Custom leading view component -const CustomLeadingView = (conversation: CometChat.Conversation) => { - const conversationObj = conversation.getConversationWith(); - const isUser = conversationObj instanceof CometChat.User; - const isGroup = conversationObj instanceof CometChat.Group; - - // Check if the current user is typing - const isMyTyping = isUser - ? (conversationObj as CometChat.User).getUid() === - typingObjRef.current?.getSender().getUid() && - loggedInUser?.getUid() === typingObjRef.current?.getReceiverId() - : isGroup && - (conversationObj as CometChat.Group).getGuid() === - typingObjRef.current?.getReceiverId(); - - // Determine avatar and name - const avatar = isUser - ? (conversationObj as CometChat.User).getAvatar() - : (conversationObj as CometChat.Group).getIcon(); - const name = isTyping && isMyTyping ? undefined : conversationObj.getName(); - const image = isTyping && isMyTyping ? "TYPING_ICON_HERE" : avatar; - return ( -
- -
- ); -}; -; -``` +function TypingAwareConversations() { + const [isTyping, setIsTyping] = useState(false); + const typingObjRef = useRef(null); + const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); + + useEffect(() => { + const listenerId = "typing_demo_" + Date.now(); + CometChat.addMessageListener( + listenerId, + new CometChat.MessageListener({ + onTypingStarted: (typingIndicator: CometChat.TypingIndicator) => { + typingObjRef.current = typingIndicator; + setIsTyping(true); + }, + onTypingEnded: (typingIndicator: CometChat.TypingIndicator) => { + if ( + typingObjRef.current && + typingObjRef.current.getSender().getUid() === + typingIndicator.getSender().getUid() + ) { + typingObjRef.current = null; + setIsTyping(false); + } + }, + }) + ); + return () => { + CometChat.removeMessageListener(listenerId); + }; + }, []); -
+ const getLeadingView = (conversation: CometChat.Conversation) => { + const entity = conversation.getConversationWith(); + const isUser = entity instanceof CometChat.User; + const isGroup = entity instanceof CometChat.Group; -
+ const isMyTyping = isUser + ? (entity as CometChat.User).getUid() === + typingObjRef.current?.getSender().getUid() && + loggedInUser?.getUid() === typingObjRef.current?.getReceiverId() + : isGroup && + (entity as CometChat.Group).getGuid() === + typingObjRef.current?.getReceiverId(); + + const avatar = isUser + ? (entity as CometChat.User).getAvatar() + : (entity as CometChat.Group).getIcon(); + + return ( +
+ +
+ ); + }; -*** + return ; +} +``` -#### TrailingView +### trailingView -The customized chat interface is displayed below. +Replace the timestamp / badge / right section. Relative time badge example. -Use the following code to achieve the customization shown above. - -```ts -import React from "react"; +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatConversations } from "@cometchat/chat-uikit-react"; -// Custom trailing view component -const CustomTrailingButtonView = (conv: CometChat.Conversation) => { - if (!conv.getLastMessage()) { - return <>; - } - const timestamp = conv.getLastMessage()?.getSentAt() * 1000; - const now = new Date(); - const time = new Date(timestamp); - - // Calculate time difference - const diffInMs = now.getTime() - time.getTime(); - const diffInMinutes = Math.floor(diffInMs / (1000 * 60)); - const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60)); - - // Determine the labels - let backgroundColorClass = "conversations__trailing-view-min"; // Default (less than 1 hour) - let topLabel = `${diffInMinutes}`; // Default minutes - let bottomLabel = `${diffInMinutes === 1 ? "Min ago" : "Mins ago"}`; // Default "Mins ago" - - if (diffInHours >= 1 && diffInHours <= 10) { - // 1-10 hours - backgroundColorClass = "conversations__trailing-view-hour"; - topLabel = `${diffInHours}`; - bottomLabel = `${diffInHours === 1 ? "Hour ago" : "Hours ago"}`; - } else if (diffInHours > 10) { - // More than 10 hours - backgroundColorClass = "conversations__trailing-view-date"; - topLabel = time.toLocaleDateString("en-US", { day: "numeric" }); - bottomLabel = time.toLocaleDateString("en-US", { - month: "short", - year: "numeric", - }); - } - return ( -
- {topLabel} - {bottomLabel} -
- ); -}; +function RelativeTimeConversations() { + const getTrailingView = (conv: CometChat.Conversation) => { + if (!conv.getLastMessage()) return <>; + + const timestamp = conv.getLastMessage()?.getSentAt() * 1000; + const now = Date.now(); + const diffInMinutes = Math.floor((now - timestamp) / (1000 * 60)); + const diffInHours = Math.floor((now - timestamp) / (1000 * 60 * 60)); + + let className = "conversations__trailing-view-min"; + let topLabel = `${diffInMinutes}`; + let bottomLabel = diffInMinutes === 1 ? "Min ago" : "Mins ago"; + + if (diffInHours >= 1 && diffInHours <= 10) { + className = "conversations__trailing-view-hour"; + topLabel = `${diffInHours}`; + bottomLabel = diffInHours === 1 ? "Hour ago" : "Hours ago"; + } else if (diffInHours > 10) { + className = "conversations__trailing-view-date"; + const time = new Date(timestamp); + topLabel = time.toLocaleDateString("en-US", { day: "numeric" }); + bottomLabel = time.toLocaleDateString("en-US", { month: "short", year: "numeric" }); + } -; -``` + return ( +
+ {topLabel} + {bottomLabel} +
+ ); + }; + return ; +} +```
- - -```css + +```css lines .conversations__trailing-view { display: flex; flex-direction: column; @@ -553,283 +653,192 @@ const CustomTrailingButtonView = (conv: CometChat.Conversation) => { height: 40px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - font-family: Arial, sans-serif; -} - -.conversations__trailing-view-min { - background-color: #e0d4f7; -} - -.conversations__trailing-view-hour { - background-color: #fff3cd; } -.conversations__trailing-view-date { - background-color: #f8d7da; -} +.conversations__trailing-view-min { background-color: #e0d4f7; } +.conversations__trailing-view-hour { background-color: #fff3cd; } +.conversations__trailing-view-date { background-color: #f8d7da; } .conversations__trailing-view-time { - font-size: 20px; - font-weight: bold; + font: 600 18px Roboto; color: #4a3f99; margin-bottom: 4px; - font: 600 18px Roboto; } .conversations__trailing-view-status { font: 600 8px Roboto; color: #6a5b99; } + .cometchat-conversations .cometchat-list-item__trailing-view { height: 50px; } ``` - -
-*** +### titleView -#### TextFormatters +Replace the name / title text. Inline user status example. -Assigns the list of text formatters. If the provided list is not null, it sets the list. Otherwise, it assigns the default text formatters retrieved from the data source. To configure the existing Mentions look and feel check out [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide) + + + - -```ts -import { CometChatTextFormatter } from "@cometchat/chat-uikit-react"; -import DialogHelper from "./Dialog"; + +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatConversations } from "@cometchat/chat-uikit-react"; -class ShortcutFormatter extends CometChatTextFormatter { - private shortcuts: { [key: string]: string } = {}; - private dialogIsOpen: boolean = false; - private dialogHelper = new DialogHelper(); - private currentShortcut: string | null = null; // Track the currently open shortcut - - constructor() { - super(); - this.setTrackingCharacter("!"); - CometChat.callExtension("message-shortcuts", "GET", "v1/fetch", undefined) - .then((data: any) => { - if (data && data.shortcuts) { - this.shortcuts = data.shortcuts; - } - }) - .catch((error) => console.log("error fetching shortcuts", error)); - } - - onKeyDown(event: KeyboardEvent) { - const caretPosition = - this.currentCaretPosition instanceof Selection - ? this.currentCaretPosition.anchorOffset - : 0; - const textBeforeCaret = this.getTextBeforeCaret(caretPosition); - - const match = textBeforeCaret.match(/!([a-zA-Z]+)$/); - if (match) { - const shortcut = match[0]; - const replacement = this.shortcuts[shortcut]; - if (replacement) { - // Close the currently open dialog, if any - if (this.dialogIsOpen && this.currentShortcut !== shortcut) { - this.closeDialog(); - } - this.openDialog(replacement, shortcut); - } - } - } +function StatusTitleConversations() { + const getTitleView = (conversation: CometChat.Conversation) => { + const user = + conversation.getConversationType() === "user" + ? (conversation.getConversationWith() as CometChat.User) + : undefined; - getCaretPosition() { - if (!this.currentCaretPosition?.rangeCount) return { x: 0, y: 0 }; - const range = this.currentCaretPosition?.getRangeAt(0); - const rect = range.getBoundingClientRect(); - return { - x: rect.left, - y: rect.top, - }; - } - - openDialog(buttonText: string, shortcut: string) { - this.dialogHelper.createDialog( - () => this.handleButtonClick(buttonText), - buttonText + return ( +
+ + {user + ? conversation.getConversationWith().getName() + " · " + : conversation.getConversationWith().getName()} + + {user && ( + + {user.getStatusMessage()} + + )} +
); - this.dialogIsOpen = true; - this.currentShortcut = shortcut; - } - - closeDialog() { - this.dialogHelper.closeDialog(); // Use DialogHelper to close the dialog - this.dialogIsOpen = false; - this.currentShortcut = null; - } - - handleButtonClick = (buttonText: string) => { - if (this.currentCaretPosition && this.currentRange) { - // Inserting the replacement text corresponding to the shortcut - const shortcut = Object.keys(this.shortcuts).find( - (key) => this.shortcuts[key] === buttonText - ); - if (shortcut) { - const replacement = this.shortcuts[shortcut]; - this.addAtCaretPosition( - replacement, - this.currentCaretPosition, - this.currentRange - ); - } - } - if (this.dialogIsOpen) { - this.closeDialog(); - } }; - getFormattedText(text: string): string { - return text; - } + return ; +} +``` +
+ +```css lines +.cometchat-conversations .conversations__title-view { + display: flex; + gap: 4px; + width: 100%; +} - private getTextBeforeCaret(caretPosition: number): string { - if ( - this.currentRange && - this.currentRange.startContainer && - typeof this.currentRange.startContainer.textContent === "string" - ) { - const textContent = this.currentRange.startContainer.textContent; - if (textContent.length >= caretPosition) { - return textContent.substring(0, caretPosition); - } - } - return ""; - } +.conversations__title-view-name { + color: #141414; + font: 500 16px/19.2px Roboto; } -export default ShortcutFormatter; +.conversations__title-view-status { + color: #6852d6; + font: 400 16px/19.2px Roboto; +} ``` - +
- -```tsx -import React from "react"; -import ReactDOM from "react-dom"; +### subtitleView -interface DialogProps { - onClick: () => void; - buttonText: string; -} +Replace the last message preview text. -const Dialog: React.FC = ({ onClick, buttonText }) => { - console.log("buttonText", buttonText); +Default: - return ( -
- -
- ); -}; + + + -export default class DialogHelper { - private dialogContainer: HTMLDivElement | null = null; +Customized: - createDialog(onClick: () => void, buttonText: string) { - this.dialogContainer = document.createElement("div"); - document.body.appendChild(this.dialogContainer); + + + - ReactDOM.render( - , - this.dialogContainer - ); - } + + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatConversations } from "@cometchat/chat-uikit-react"; + +function formatTimestamp(timestamp: number): string { + return new Date(timestamp * 1000).toLocaleString(); +} - closeDialog() { - if (this.dialogContainer) { - ReactDOM.unmountComponentAtNode(this.dialogContainer); - this.dialogContainer.remove(); - this.dialogContainer = null; +function SubtitleConversations() { + const getSubtitleView = (conversation: CometChat.Conversation) => { + if (conversation.getConversationType() === "user") { + return ( + <> + Last active:{" "} + {formatTimestamp( + (conversation.getConversationWith() as CometChat.User).getLastActiveAt() + )} + + ); } - } + return ( + <> + Created:{" "} + {formatTimestamp( + (conversation.getConversationWith() as CometChat.Group).getCreatedAt() + )} + + ); + }; + + return ; } ``` - - - -```tsx -import ShortcutFormatter from "./ShortCutFormatter"; - -; + +```css lines +.cometchat-conversations .cometchat-list-item__body-subtitle { + overflow: hidden; + color: var(--cometchat-text-color-secondary, #727272); + text-overflow: ellipsis; + white-space: nowrap; + font: var(--cometchat-font-body-regular); +} ``` - - -#### Header View - -You can set the Custom Header view to add more options to the Conversations component. +### headerView -The customized chat interface is displayed below. +Replace the entire header bar. -Use the following code to achieve the customization shown above. - -```ts +```tsx lines import { CometChatButton, CometChatConversations, + getLocalizedString, } from "@cometchat/chat-uikit-react"; -const getHeaderView = () => { +function CustomHeaderConversations() { return ( -
-
{localize("CHATS")}
- { - // logic here - }} - iconURL={ICON_URL} - /> -
+ +
+ {getLocalizedString("CHATS")} +
+ { /* handle click */ }} /> +
+ } + /> ); -}; - -; +} ``` -
- - -```css + +```css lines .conversations__header { display: flex; width: 100%; @@ -837,332 +846,732 @@ const getHeaderView = () => { align-items: center; justify-content: space-between; gap: 12px; - flex: 1 0 0; - align-self: stretch; border-radius: 10px; border: 1px solid #e8e8e8; background: #edeafa; } + .conversations__header__title { overflow: hidden; color: #141414; text-overflow: ellipsis; font: 700 24px Roboto; } + .conversations__header .cometchat-button .cometchat-button__icon { background: #141414; } + .conversations__header .cometchat-button { width: 24px; border: none; background: transparent; border-radius: 0; - display: block; } ``` - - -*** +### options -#### Last Message Date Time Format +Replace the context menu / hover actions on each conversation item. -The `lastMessageDateTimeFormat` property allows you to customize the **Last Message** timestamp is displayed in the conversations. +Default: -Default Date Time Format: + + + -```ruby -new CalendarObject({ - today: `hh:mm A`, // Example: "10:30 AM" - yesterday: `[yesterday]`, // Example: "yesterday" - otherDays: `DD/MM/YYYY`, // Example: "25/05/2025" -}); -``` +Customized: -The following example demonstrates how to modify the **Last Message** timestamp format using a custom [`CalendarObject`](/ui-kit/react/localize#calendarobject). + + + -```ts +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; import { + CometChatOption, CometChatConversations, - CalendarObject, } from "@cometchat/chat-uikit-react"; -// Define a custom date format pattern -function getDateFormat() { - const dateFormat = new CalendarObject({ - today: `DD MMM, hh:mm A`, // Example: "25 Jan, 10:30 AM" - yesterday: `DD MMM, hh:mm A`, // Example: "25 Jan, 10:30 AM" - otherDays: `DD MMM, hh:mm A`, // Example: "25 Jan, 10:30 AM" - }); - return dateFormat; -} +function CustomOptionsConversations() { + const getOptions = (conversation: CometChat.Conversation) => [ + new CometChatOption({ + title: "Delete", + id: "delete", + onClick: () => { /* delete logic */ }, + }), + new CometChatOption({ + title: "Mute Notification", + id: "mute", + onClick: () => { /* mute logic */ }, + }), + new CometChatOption({ + title: "Mark as Unread", + id: "unread", + onClick: () => { /* mark unread logic */ }, + }), + new CometChatOption({ + title: "Block", + id: "block", + onClick: () => { /* block logic */ }, + }), + ]; -// Apply the custom format to the CometChatConversations component -; + return ; +} ``` - + +```css lines +.cometchat-conversations .cometchat-menu-list__main-menu-item-icon-delete { + background: red; +} +.cometchat-conversations .cometchat-menu-list__sub-menu { + background: transparent; + box-shadow: none; +} +``` + - +```ts lines +// CometChatOption interface +interface CometChatOption { + id?: string; // Unique identifier + title?: string; // Display text + iconURL?: string; // Icon asset URL + onClick?: () => void; // Click handler +} +``` -**Fallback Mechanism** +### textFormatters -* If you **do not** pass any property in the [**CalendarObject**](/ui-kit/react/localize#calendarobject), the component will first check the [**global configuration**](/ui-kit/react/localize#customisation). If the property is **also missing in the global configuration**, it will **fallback to the component's default formatting**. +Custom text formatters for the conversation subtitle. Array of `CometChatTextFormatter` instances. If not provided, default formatters from the data source are used. - +```tsx lines +import { CometChatConversations } from "@cometchat/chat-uikit-react"; +import ShortcutFormatter from "./ShortCutFormatter"; -*** +function FormattedConversations() { + return ( + + ); +} +``` -#### TitleView +See [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide) for mention formatting. -The customized chat interface is displayed below. +### lastMessageDateTimeFormat - - - +Customize the last message timestamp format using a `CalendarObject`. -Use the following code to achieve the customization shown above. +```ts lines +// CalendarObject interface (from source) +class CalendarObject { + today?: string; + yesterday?: string; + lastWeek?: string; + otherDays?: string; + relativeTime?: { + minute?: string; + minutes?: string; + hour?: string; + hours?: string; + }; +} +``` - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines +import { + CometChatConversations, + CalendarObject, +} from "@cometchat/chat-uikit-react"; + +function CustomDateConversations() { + const dateFormat = new CalendarObject({ + today: "DD MMM, hh:mm A", + yesterday: "DD MMM, hh:mm A", + otherDays: "DD MMM, hh:mm A", + }); + + return ; +} +``` + + +If no property is passed in the [CalendarObject](/ui-kit/react/localize#calendarobject), the component checks the [global configuration](/ui-kit/react/localize#customisation) first. If also missing there, the component's default formatting applies. + + +--- + +## Common Patterns + +### Custom empty state with CTA + +```tsx lines import { CometChatConversations } from "@cometchat/chat-uikit-react"; -// Custom title view component -const customTitleView = (conversation: CometChat.Conversation) => { - let user = - conversation.getConversationType() == "user" - ? (conversation.getConversationWith() as CometChat.User) - : undefined; +function EmptyStateConversations() { return ( -
- - {user - ? conversation.getConversationWith().getName() + " • " - : conversation.getConversationWith().getName()} - - {user ? ( - - {user.getStatusMessage()} - - ) : null} -
+ +

No conversations yet

+ +
+ } + /> ); -}; - -; +} ``` - +### Hide all chrome — minimal list - -```css -.cometchat-conversations .conversations__title-view { - display: flex; - gap: 4px; - width: 100%; -} +```tsx lines +import { CometChatConversations } from "@cometchat/chat-uikit-react"; -.cometchat-conversations - .conversations__title-view - .conversations__title-view-name { - color: #141414; - font: 500 16px/19.2px Roboto; - text-align: left; +function MinimalConversations() { + return ( + + ); } -.cometchat-conversations - .conversations__title-view - .conversations__title-view-status { - color: #6852d6; - font: 400 16px/19.2px Roboto; - text-align: left; +``` + +### Conversations with search + +```tsx lines +import { CometChatConversations } from "@cometchat/chat-uikit-react"; + +function SearchableConversations() { + return ( + + ); } ``` - +--- - +## CSS Architecture -*** +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: -#### SubtitleView +1. Global tokens (e.g., `--cometchat-primary-color`, `--cometchat-background-color-01`) are set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-conversations`) consumes these tokens via `var()` with fallback values. +3. Overrides target `.cometchat-conversations` descendant selectors in a global stylesheet. -You can customize the subtitle view for each conversation item to meet your requirements. +To scope overrides to a single instance when multiple `CometChatConversations` exist on the same page, wrap the component in a container and scope selectors: -Shown below is the default chat interface. +```css lines +.sidebar-left .cometchat-conversations .cometchat-badge { + background: #e5484d; +} +``` - - - +Overrides survive component updates because the component never sets inline styles on these elements — all styling flows through CSS classes and custom properties. + +### Key Selectors -The customized chat interface is displayed below. +| Target | Selector | +| --- | --- | +| Root | `.cometchat-conversations` | +| Header title | `.cometchat-conversations .cometchat-list__header-title` | +| List item | `.cometchat-conversations .cometchat-list-item` | +| Body title | `.cometchat-conversations .cometchat-list-item__body-title` | +| Avatar | `.cometchat-conversations .cometchat-avatar` | +| Avatar text | `.cometchat-conversations .cometchat-avatar__text` | +| Unread badge | `.cometchat-conversations .cometchat-badge` | +| Subtitle text | `.cometchat-conversations .cometchat-conversations__subtitle-text` | +| Status indicator | `.cometchat-conversations .cometchat-status-indicator` | +| Read receipts | `.cometchat-conversations .cometchat-receipts-read` | +| Active item | `.cometchat-conversations__list-item-active .cometchat-list-item` | +| Typing indicator | `.cometchat-conversations__subtitle-typing` | +| Trailing view | `.cometchat-conversations__trailing-view` | + +### Example: Brand-themed conversations - + -Use the following code to achieve the customization shown above. +```css lines +.cometchat-conversations .cometchat-list-item__body-title, +.cometchat-conversations .cometchat-list__header-title, +.cometchat-conversations .cometchat-avatar__text, +.cometchat-conversations .cometchat-badge, +.cometchat-conversations .cometchat-conversations__subtitle-text { + font-family: "SF Pro"; +} - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatConversations } from "@cometchat/chat-uikit-react"; +.cometchat-conversations .cometchat-list__header-title { + background: #fef8f8; + border-bottom: 2px solid #f4b6b8; +} -const subtitleView = (conversation: CometChat.Conversation) => { - if (conversation.getConversationType() === "user") { - return ( - <> - Last Message at:{" "} - {getFormattedTimestamp( - ( - conversation.getConversationWith() as CometChat.User - ).getLastActiveAt() - )} - - ); - } else { - return ( - <> - Created at:{" "} - {getFormattedTimestamp( - (conversation.getConversationWith() as CometChat.Group).getCreatedAt() - )} - - ); - } -}; +.cometchat-conversations .cometchat-avatar { + background: #f0999b; +} -function getFormattedTimestamp(timestamp: number): string { - const date = new Date(timestamp * 1000); - return date.toLocaleString(); +.cometchat-conversations .cometchat-status-indicator { + min-width: 10px; + height: 10px; } -; +.cometchat-conversations .cometchat-badge { + background: #e5484d; +} + +.cometchat-conversations .cometchat-receipts-read { + background: #e96b6f; +} ``` - +### Customization Matrix - -```css -.cometchat-conversations .cometchat-list-item__body-subtitle { - overflow: hidden; - color: var(--cometchat-text-color-secondary, #727272); - text-overflow: ellipsis; - white-space: nowrap; - font: var(--cometchat-font-body-regular); - font-family: "SF Pro"; - font-style: normal; +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Component props | `on` callbacks | `onItemClick={(c) => setActive(c)}` | +| Filter which conversations appear | Component props | `conversationsRequestBuilder` | `conversationsRequestBuilder={new CometChat.ConversationsRequestBuilder().setLimit(10)}` | +| Toggle visibility of UI elements | Component props | `hide` boolean props | `hideReceipts={true}` | +| Replace a section of the list item | Component props | `View` render props | `itemView={(conversation) =>
...
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-conversations` class | `.cometchat-conversations .cometchat-badge { background: #e5484d; }` | + +--- + +## Accessibility + +The component renders a scrollable list of interactive items. Each conversation row is keyboard-focusable and activates on Enter/Space. The context menu (options) is accessible via keyboard. The unread badge count is exposed as text content. Avatar images include the conversation name as alt text. + +For screen readers, the conversation list is rendered as a semantic list. Status indicators (online/offline, group type icons) use CSS mask images — add `aria-label` attributes via `itemView` if screen reader descriptions are needed for these visual indicators. + +--- + +--- + +## Props + +All props are optional. Sorted alphabetically. + +### activeConversation + +Highlights the specified conversation in the list. + +| | | +| --- | --- | +| Type | `CometChat.Conversation` | +| Default | `undefined` | + +Must be a reference-equal object from the SDK; a manually constructed object will not match. + +--- + +### conversationsRequestBuilder + +Controls which conversations load and in what order. + +| | | +| --- | --- | +| Type | `CometChat.ConversationsRequestBuilder` | +| Default | SDK default (30 per page) | + +Pass the builder instance, not the result of `.build()`. + +--- + +### customSoundForMessages + +URL to a custom audio file for incoming message notifications. + +| | | +| --- | --- | +| Type | `string` | +| Default | Built-in sound | + +Must be a valid audio URL accessible from the browser. + +--- + +### disableSoundForMessages + +Disables the notification sound for incoming messages. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### emptyView + +Custom component displayed when there are no conversations. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in empty state | + +--- + +### errorView + +Custom component displayed when an error occurs. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in error state | + +Hidden when `hideError={true}`. + +--- + +### headerView + +Custom component rendered as the entire header bar. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in header with title | + +--- + +### hideDeleteConversation + +Hides the delete option in the context menu. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideError + +Hides the default and custom error views. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +Also suppresses `errorView` if set. + +--- + +### hideGroupType + +Hides the group type icon (public/private/password). + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideReceipts + +Hides message read/delivery receipt indicators. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideUserStatus + +Hides the online/offline status indicator. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### itemView + +Custom renderer for the entire list item row. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => JSX.Element` | +| Default | Built-in list item | + +--- + +### lastMessageDateTimeFormat + +Format for displaying the timestamp of the last message. + +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default (`hh:mm A` today, `[yesterday]`, `DD/MM/YYYY` other days) | + +```ts lines +class CalendarObject { + today?: string; + yesterday?: string; + lastWeek?: string; + otherDays?: string; + relativeTime?: { + minute?: string; + minutes?: string; + hour?: string; + hours?: string; + }; } ``` -
+Falls back to [global calendar configuration](/ui-kit/react/localize#customisation) if not set. -
+--- -*** +### leadingView -#### Options +Custom renderer for the avatar / left section. -A function that returns a list of actions available when hovering over a conversation item. +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => JSX.Element` | +| Default | Built-in avatar | -Shown below is the default chat interface. +--- - - - +### loadingView -The customized chat interface is displayed below. +Custom component displayed during the loading state. - - - +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in shimmer | -Use the following code to achieve the customization shown above. +--- - - -```ts -import { - CometChatOption, - CometChatConversations, -} from "@cometchat/chat-uikit-react"; +### onError -const getOptions = (conversation: CometChat.Conversation) => { - return [ - new CometChatOption({ - title: "Delete", - iconURL: deleteIcon, - id: "delete", - onClick: () => { - // Logic here - }, - }), - new CometChatOption({ - title: "Mute Notification", - id: "mute", - onClick: () => { - // Logic here - }, - }), - new CometChatOption({ - title: "Mark as Unread", - id: "unread", - onClick: () => { - // Logic here - }, - }), - new CometChatOption({ - title: "Block", - id: "block", - onClick: () => { - // Logic here - }, - }), - ]; -}; +Callback fired when the component encounters an error. -; -``` +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | - +--- - -```css -.cometchat-conversations .cometchat-menu-list__main-menu-item-icon-delete { - background: red; -} +### onItemClick -.cometchat-conversations .cometchat-menu-list__sub-menu { - background: transparent; - box-shadow: none; +Callback fired when a conversation row is clicked. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => void` | +| Default | `undefined` | + +--- + +### onSearchBarClicked + +Callback fired when the search bar is clicked. Requires `showSearchBar={true}`. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onSelect + +Callback fired when a conversation is selected/deselected. Requires `selectionMode` to be set. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation, selected: boolean) => void` | +| Default | `undefined` | + +--- + +### options + +Custom context menu / hover actions for each conversation item. + +| | | +| --- | --- | +| Type | `((conversation: CometChat.Conversation) => CometChatOption[]) \| null` | +| Default | Built-in delete option | + +```ts lines +class CometChatOption { + id?: string; + title?: string; + iconURL?: string; + onClick?: () => void; } +``` + +--- + +### searchView + +Custom search bar component in the header. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in search bar | -.cometchat-conversations .cometchat-menu-list__sub-menu-icon { - -webkit-mask: url(./assets/down-arrow.svg) center center no-repeat; - -webkit-mask-size: contain; +--- + +### selectionMode + +Enables single or multi-select checkboxes on list items. + +| | | +| --- | --- | +| Type | `SelectionMode` | +| Default | `SelectionMode.none` | + +```ts lines +enum SelectionMode { + single, // 0 + multiple, // 1 + none, // 2 } ``` - +Must pair with `onSelect` to capture selections. - +--- + +### showScrollbar + +Shows the scrollbar in the conversation list. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showSearchBar -##### Structure of CometChatOption +Shows a search bar at the top of the list. -| Name | Description | -| ----------- | ----------------------------------------------------- | -| **id** | Unique identifier for each option. | -| **title** | Heading text for each option. | -| **iconURL** | Sets the asset URL of the icon for each option. | -| **onClick** | Method to be invoked when user clicks on each option. | +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### subtitleView + +Custom renderer for the last message preview text. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => JSX.Element` | +| Default | Built-in subtitle | + +--- + +### textFormatters + +Custom text formatters for the conversation subtitle. + +| | | +| --- | --- | +| Type | `CometChatTextFormatter[]` | +| Default | Default formatters from data source | + +See [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide) for mention formatting. + +--- + +### titleView + +Custom renderer for the name / title text. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => JSX.Element` | +| Default | Built-in title | + +--- + +### trailingView + +Custom renderer for the timestamp / badge / right section. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => JSX.Element` | +| Default | Built-in trailing view | + +--- + +## Events + +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatConversationEvents.ccConversationDeleted` | `CometChat.Conversation` | Conversation deleted from list | +| `CometChatConversationEvents.ccUpdateConversation` | `CometChat.Conversation` | Conversation updated | +| `CometChatConversationEvents.ccMarkConversationAsRead` | `CometChat.Conversation` | Conversation marked as read | + +All events are `Subject` from RxJS. Subscribe with `.subscribe()`, unsubscribe with the returned subscription's `.unsubscribe()`. + +--- -*** +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-conversations` | +| Header title | `.cometchat-conversations .cometchat-list__header-title` | +| List item | `.cometchat-conversations .cometchat-list-item` | +| Body title | `.cometchat-conversations .cometchat-list-item__body-title` | +| Avatar | `.cometchat-conversations .cometchat-avatar` | +| Avatar text | `.cometchat-conversations .cometchat-avatar__text` | +| Unread badge | `.cometchat-conversations .cometchat-badge` | +| Subtitle text | `.cometchat-conversations .cometchat-conversations__subtitle-text` | +| Subtitle sender | `.cometchat-conversations__subtitle-text-sender` | +| Status indicator (online) | `.cometchat-conversations__list-item-online .cometchat-list-item__status` | +| Group type (password) | `.cometchat-conversations__list-item-password .cometchat-list-item__status` | +| Group type (private) | `.cometchat-conversations__list-item-private .cometchat-list-item__status` | +| Read receipts | `.cometchat-conversations__subtitle-receipts-read` | +| Delivered receipts | `.cometchat-conversations__subtitle-receipts-delivered` | +| Sent receipts | `.cometchat-conversations__subtitle-receipts-sent` | +| Error receipts | `.cometchat-conversations__subtitle-receipts-error` | +| Active item | `.cometchat-conversations__list-item-active .cometchat-list-item` | +| Typing indicator | `.cometchat-conversations__subtitle-typing` | +| Trailing view | `.cometchat-conversations__trailing-view` | +| Badge count | `.cometchat-conversations__trailing-view-badge-count` | +| Empty state | `.cometchat-conversations__empty-state-view` | +| Error state | `.cometchat-conversations__error-state-view` | +| Shimmer loading | `.cometchat-conversations__shimmer` | +| Context menu | `.cometchat-conversations__trailing-view-options` | +| Mentions highlight | `.cometchat-conversations__subtitle-text .cometchat-mentions` | +| @you mentions | `.cometchat-conversations__subtitle-text .cometchat-mentions-you` | diff --git a/ui-kit/react/core-features.mdx b/ui-kit/react/core-features.mdx index 78a6de7de..9f43e0375 100644 --- a/ui-kit/react/core-features.mdx +++ b/ui-kit/react/core-features.mdx @@ -1,12 +1,22 @@ --- title: "Core" +description: "Overview of CometChat's core chat features including instant messaging, media sharing, read receipts, typing indicators, user presence, reactions, mentions, threaded conversations, search, and moderation — with the UI Kit components that power each feature." --- -## Overview + -The UI Kit comprises a variety of components, each designed to work seamlessly with one another to deliver a comprehensive and intuitive chat experience. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` — must complete before rendering any component | +| Core features | Instant Messaging, Media Sharing, Read Receipts, Mark as Unread, Typing Indicator, User Presence, Reactions, Mentions, Quoted Reply, Search, Threaded Conversations, Moderation, Report Message, Group Chat | +| Key components | `CometChatConversations` → [Conversations](/ui-kit/react/conversations), `CometChatMessageList` → [Message List](/ui-kit/react/message-list), `CometChatMessageComposer` → [Message Composer](/ui-kit/react/message-composer), `CometChatMessageHeader` → [Message Header](/ui-kit/react/message-header), `CometChatUsers` → [Users](/ui-kit/react/users), `CometChatGroups` → [Groups](/ui-kit/react/groups), `CometChatGroupMembers` → [Group Members](/ui-kit/react/group-members) | +| CSS class prefix | `.cometchat-` | +| Theming | Override CSS variables on `.cometchat` class. See [Theming](/ui-kit/react/theme) | -Here's how different UI Kit components work together to achieve CometChat's Core features: + + +The UI Kit components work together to deliver a complete chat experience. The sections below map each core feature to the components that power it. ## Instant Messaging @@ -23,7 +33,7 @@ At the heart of CometChat's functionality is the ability to support real-time te ## Media Sharing -Beyond text, CometChat allows users to share various media types within their conversations. This includes images, videos, audio files, and documents, enriching the chat experience and enabling more comprehensive communication. +CometChat supports sharing images, videos, audio files, and documents within conversations. @@ -86,7 +96,7 @@ CometChat's User Presence feature allows users to see whether their contacts are | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Conversations](/ui-kit/react/conversations) | [Conversations](/ui-kit/react/conversations) is a component that renders conversation list item. Conversations item also shows user presence information. | | [Message Header](/ui-kit/react/message-header) | [Message Header](/ui-kit/react/message-header) that renders details of user/group. The Message Header also handles user presence information. | -| [Users](/ui-kit/react/users) | [Users](/ui-kit/react/users) renders list of users available in your app.It also responsible to render users presence information. | +| [Users](/ui-kit/react/users) | [Users](/ui-kit/react/users) renders the list of available users with presence information. | | [Group Members](/ui-kit/react/group-members) | [Group Members](/ui-kit/react/group-members) renders list of users available in the group. The Group Members component also handles user presence information. | ## Reactions @@ -115,45 +125,40 @@ Mentions is a robust feature provided by CometChat that enhances the interactivi | [Message Composer](/ui-kit/react/message-composer) | [Message Composer](/ui-kit/react/message-composer) is a component that allows users to craft and send various types of messages, including the usage of the mentions feature for direct addressing within the conversation. | | [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) is a component that displays a list of sent and received messages. It also supports the rendering of Mentions, enhancing the readability and interactivity of conversations. | -## Quoted Reply +## Threaded Conversations -Quoted Reply is a robust feature provided by CometChat that enables users to quickly reply to specific messages by selecting the "Reply" option from a message's action menu. This enhances context, keeps conversations organized, and improves overall chat experience in both 1-1 and group chats. +The Threaded Conversations feature enables users to respond directly to a specific message in a chat. This keeps conversations organized and enhances the user experience by maintaining context, especially in group chats. - + -| Components | Functionality | -| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) supports replying to messages via the "Reply" option. Users can select "Reply" on a message to open the composer with the quoted reply pre-filled, maintaining context. | -| [Message Composer](/ui-kit/react/message-composer) | [Message Composer](/ui-kit/react/message-composer) works seamlessly with Quoted Message by showing the quoted reply above the input field, letting users compose their response in proper context. | +| Components | Functionality | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| [Threaded Message Preview](/ui-kit/react/threaded-message-preview) | [Threaded Message Preview](/ui-kit/react/threaded-message-preview) component displays the parent message along with the number of replies. | -## Conversation and Advanced Search +## Quoted Replies -Conversation and Advanced Search is a powerful feature provided by CometChat that enables users to quickly find conversations, messages, and media across chats in real time. It supports filters, scopes, and custom actions, allowing users to locate content efficiently while keeping the chat experience smooth and intuitive. +Quoted Replies is a robust feature provided by CometChat that enables users to quickly reply to specific messages by selecting the "Reply" option from a message's action menu. This enhances context, keeps conversations organized, and improves overall chat experience in both 1-1 and group chats. - + | Components | Functionality | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Search](/ui-kit/react/search) | [Search](/ui-kit/react/search) allows users to search across conversations and messages in real time. Users can click on a result to open the conversation or jump directly to a specific message. | -| [Message Header](/ui-kit/react/message-header) | [Message Header](/ui-kit/react/message-header) shows the search button in the chat header, allowing users to search within a conversation. | -| [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) shows the selected message when clicked from search results and highlights it in the message list. | -| [Conversations](/ui-kit/react/conversations) | [Conversations](/ui-kit/react/conversations) displays the search input. | +| [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) supports replying to messages via the "Reply" option. Users can select "Reply" on a message to open the composer with the quoted reply pre-filled, maintaining context. | +| [Message Composer](/ui-kit/react/message-composer) | [Message Composer](/ui-kit/react/message-composer) shows the quoted reply above the input field, providing context for the response. | -## Threaded Conversations +## Group Chat -The Threaded Conversations feature enables users to respond directly to a specific message in a chat. This keeps conversations organized and enhances the user experience by maintaining context, especially in group chats. +CometChat facilitates Group Chats, allowing users to have conversations with multiple participants simultaneously. This feature is crucial for team collaborations, group discussions, social communities, and more. - + -| Components | Functionality | -| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| [Threaded Message Preview](/ui-kit/react/threaded-message-preview) | [Threaded Message Preview](/ui-kit/react/threaded-message-preview) component displays the parent message along with the number of replies. | +See the [Groups](/ui-kit/react/groups) component page for details. ## Moderation @@ -169,9 +174,9 @@ Learn more about setting up moderation rules and managing content in the [Modera | Components | Functionality | | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) automatically handles moderated messages, displaying blocked content appropriately based on your moderation settings. | +| [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) automatically handles moderated messages, displaying blocked content based on moderation settings. | -After implementing moderation rules, users can report messages they find inappropriate or harmful. As a next step, you can enable the **[Report Message](#report-message)** feature to allow users to flag messages for review by moderators. +The **[Report Message](#report-message)** feature enables users to flag messages for review by moderators. ## Report Message @@ -189,12 +194,37 @@ Learn more about how flagged messages are handled, reviewed, and moderated in th | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) provides the "Report Message" option in the message actions menu, allowing users to initiate the reporting process for inappropriate messages. | -## Group Chat +## Conversation and Advanced Search -CometChat facilitates Group Chats, allowing users to have conversations with multiple participants simultaneously. This feature is crucial for team collaborations, group discussions, social communities, and more. +Conversation and Advanced Search is a powerful feature provided by CometChat that enables users to quickly find conversations, messages, and media across chats in real time. It supports filters, scopes, and custom actions, allowing users to locate content efficiently while keeping the chat experience smooth and intuitive. - + -For a comprehensive understanding and guide on implementing and using the Groups feature in CometChat, you should refer to our detailed guide on [Groups](/ui-kit/react/groups). +| Components | Functionality | +| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Search](/ui-kit/react/search) | [Search](/ui-kit/react/search) allows users to search across conversations and messages in real time. Users can click on a result to open the conversation or jump directly to a specific message. | +| [Message Header](/ui-kit/react/message-header) | [Message Header](/ui-kit/react/message-header) shows the search button in the chat header, allowing users to search within a conversation. | +| [Message List](/ui-kit/react/message-list) | [Message List](/ui-kit/react/message-list) shows the selected message when clicked from search results and highlights it in the message list. | +| [Conversations](/ui-kit/react/conversations) | [Conversations](/ui-kit/react/conversations) displays the search input. | + +See the [Groups](/ui-kit/react/groups) component page for details. +--- + +## Next Steps + + + + Browse all available UI Kit components + + + Customize the look and feel of your chat UI + + + Add audio and video calling + + + Explore AI-powered chat capabilities + + diff --git a/ui-kit/react/custom-text-formatter-guide.mdx b/ui-kit/react/custom-text-formatter-guide.mdx index eadbdc933..98f07e1e0 100644 --- a/ui-kit/react/custom-text-formatter-guide.mdx +++ b/ui-kit/react/custom-text-formatter-guide.mdx @@ -1,46 +1,59 @@ --- title: "Custom Text Formatter" +description: "Extend the CometChatTextFormatter base class to implement custom inline text patterns with regex and callbacks." --- -## Overview + -You can create your custom text formatter for CometChat using the `CometChatTextFormatter`. `CometChatTextFormatter` is an abstract utility class that serves as a foundational structure for enabling text formatting in the message composer and text message bubbles. It can be extended to create custom formatter classes, tailored to suit specific application needs, making it a valuable tool for text customization and enhancement in chat interfaces. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key class | `CometChatTextFormatter` (abstract base class for custom formatters) | +| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Purpose | Extend to create custom inline text patterns with regex, styling, and callbacks | +| Features | Text formatting, customizable styles, dynamic text replacement, input field integration, key event callbacks | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [ShortCut Formatter](/ui-kit/react/shortcut-formatter-guide) \| [Mentions Formatter](/ui-kit/react/mentions-formatter-guide) \| [All Guides](/ui-kit/react/guide-overview) | -## Features + -* **Text Formatting:**: Enables automatic formatting of text within messages based on specified styles and settings, enhancing the visual presentation of chat content. -* **Customizable Styles:**: Tailor text styles, including colors, fonts, and background colors, to match the desired appearance for formatted text. -* **Dynamic Text Replacement:**: Utilizes regular expression patterns to identify and replace specific text patterns with formatted content, offering flexibility in text manipulation. -* **Input Field Integration:**: Seamlessly integrates with the text input field, allowing for real-time monitoring and processing of user input for formatting purposes. -* **Callback Functions:**: Implement callback functions for key up and key down events, providing hooks for custom actions or formatting logic based on user interactions. +`CometChatTextFormatter` is an abstract class for formatting text in the message composer and message bubbles. Extend it to build custom formatters — hashtags, keywords, or any regex-based pattern. + +| Capability | Description | +| --- | --- | +| Text formatting | Auto-format text based on regex patterns and styles | +| Custom styles | Set colors, fonts, and backgrounds for matched text | +| Dynamic replacement | Regex-based find-and-replace in user input | +| Input integration | Real-time monitoring of the composer input field | +| Key event callbacks | Hooks for `keyUp` and `keyDown` events | -Always wrap formatted data in a span with a unique CSS class (for example, "custom-hashtag"). This lets the UI Kit render it as-is instead of sanitizing it along with other tags. +Always wrap formatted output in a `` with a unique CSS class (e.g. `"custom-hashtag"`). This tells the UI Kit to render it as-is instead of sanitizing it. -## Usage - -here are the steps to create your custom text formatter for CometChat using the `CometChatTextFormatter`: +--- -To integrate the `CometChatTextFormatter` class into your application: +## Steps -1. Firstly, you need to import `CometChatTextFormatter` from the CometChat UI Kit react library. +### 1. Import the base class -```javascript +```javascript lines import { CometChatTextFormatter } from "@cometchat/chat-uikit-react"; ``` -2. Now, extend the `CometChatTextFormatter` class to create your custom text formatter class. In this case, let's create a `HashTagTextFormatter`. +### 2. Extend it -```java +```javascript lines class HashTagTextFormatter extends CometChatTextFormatter { ... } ``` -3. set up the `trackCharacter`, `regexPatterns` and `regexToReplaceFormatting`. For a hashtag formatter, we're setting the track character to `#`. +### 3. Configure tracking character and regex + +Set the character that triggers formatting, the regex to match, and the regex to strip formatting back to plain text. -```csharp +```javascript lines this.setTrackingCharacter("#"); this.setRegexPatterns([/\B#(\w+)\b/g]); this.setRegexToReplaceFormatting([ @@ -48,24 +61,26 @@ this.setRegexToReplaceFormatting([ ]); ``` -4. Set callback functions for key up and key down events. +### 4. Set key event callbacks -```javascript +```javascript lines this.setKeyUpCallBack(this.onKeyUp.bind(this)); this.setKeyDownCallBack(this.onKeyDown.bind(this)); ``` -5. Implement the `getFormattedText`, `getOriginalText` and custom logic to format text methods. +### 5. Implement formatting methods -```typescript +```typescript lines getFormattedText(inputText:string) { ... } getOriginalText(inputText:string) { ... } customLogicToFormatText(inputText: string) { ... } ``` +--- + ## Example -Below is an example demonstrating how to use a custom formatter class in components such as [CometChatConversations](/ui-kit/react/conversations), [CometChatMessageList](/ui-kit/react/message-list), [CometChatMessageComposer](/ui-kit/react/message-composer). +A hashtag formatter used with [CometChatMessageList](/ui-kit/react/message-list) and [CometChatMessageComposer](/ui-kit/react/message-composer). @@ -73,75 +88,49 @@ Below is an example demonstrating how to use a custom formatter class in compone -```ts +```ts lines import { CometChatTextFormatter } from "@cometchat/chat-uikit-react"; class HashTagTextFormatter extends CometChatTextFormatter { constructor() { super(); - // Set the tracking character to # this.setTrackingCharacter("#"); - - // Define regex patterns to find specific text patterns - this.setRegexPatterns([ - /\B#(\w+)\b/g, // Matches hashtags starting with # - ]); - - // Define regex patterns to replace formatter text with original text - this.setRegexToReplaceFormatting([ - /#(\w+)/g, // Replace hashtags without formatting - ]); - - // Set callback functions for key up and key down events + this.setRegexPatterns([/\B#(\w+)\b/g]); + this.setRegexToReplaceFormatting([/#(\w+)/g]); this.setKeyUpCallBack(this.onKeyUp.bind(this)); this.setKeyDownCallBack(this.onKeyDown.bind(this)); - - // Set the re-render callback function this.setReRender(() => { - // Trigger re-rendering of the message composer component - // This could involve updating the UI with the formatted text console.log("Re-rendering message composer to update text content."); }); - - // Initialize composer tracking this.initializeComposerTracking(); } initializeComposerTracking() { - // Get the reference to the input field (composer) const composerInput = document.getElementById("yourComposerInputId"); - - // Set the reference to the input field this.setInputElementReference(composerInput); } getCaretPosition(): number { if (!this.inputElementReference) return 0; - const selection = window.getSelection(); if (!selection || selection.rangeCount === 0) return 0; - const range = selection.getRangeAt(0); const clonedRange = range.cloneRange(); clonedRange.selectNodeContents(this.inputElementReference); clonedRange.setEnd(range.endContainer, range.endOffset); - return clonedRange.toString().length; } setCaretPosition(position: number) { if (!this.inputElementReference) return; - const range = document.createRange(); const selection = window.getSelection(); if (!selection) return; - range.setStart( this.inputElementReference.childNodes[0] || this.inputElementReference, position ); range.collapse(true); - selection.removeAllRanges(); selection.addRange(range); } @@ -150,14 +139,11 @@ class HashTagTextFormatter extends CometChatTextFormatter { if (event.key === this.trackCharacter) { this.startTracking = true; } - // Custom logic to format hashtags as users type in the composer if (this.startTracking && (event.key === " " || event.key === "Enter")) { const caretPosition = this.getCaretPosition(); this.formatText(); this.setCaretPosition(caretPosition); } - // Check if the last character typed was not a space or enter - // and if the caret position is at the end, then we need to set start tracking to false if ( this.startTracking && event.key !== " " && @@ -174,29 +160,20 @@ class HashTagTextFormatter extends CometChatTextFormatter { this.inputElementReference?.textContent || ""; const formattedText = this.getFormattedText(inputValue); - // Update the composer with formatted text if (this.inputElementReference) { this.inputElementReference.innerHTML = formattedText || ""; - // Trigger re-render of the composer this.reRender(); } } - onKeyDown(event: KeyboardEvent) { - // Custom onKeyDown logic can be added here - } + onKeyDown(event: KeyboardEvent) {} getFormattedText(inputText: string) { - if (!inputText) { - // Edit at cursor position and return void - return; - } - // Perform custom logic to format text (e.g., formatting hashtags) + if (!inputText) return; return this.customLogicToFormatText(inputText); } customLogicToFormatText(inputText: string) { - // Replace hashtags with HTML span elements to change color to green return inputText.replace( /\B#(\w+)\b/g, '#$1' @@ -204,19 +181,13 @@ class HashTagTextFormatter extends CometChatTextFormatter { } getOriginalText(inputText: string) { - // Sample implementation - if (!inputText) { - return ""; - } - // Remove formatting and return original text + if (!inputText) return ""; for (let i = 0; i < this.regexToReplaceFormatting.length; i++) { let regexPattern = this.regexToReplaceFormatting[i]; - if (inputText) { inputText = inputText.replace(regexPattern, "#$1"); } } - return inputText; } } @@ -227,11 +198,13 @@ export default HashTagTextFormatter; -```tsx + +Pass the formatter via the `textFormatters` prop. + +```tsx lines import { HashTagTextFormatter } from "./HashTagTextFormatter"; export default function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); React.useEffect(() => { @@ -239,83 +212,70 @@ export default function MessageListDemo() { setChatUser(user); }) }, []) - return ( -
-
+ + return ( -
-
- ); + ); } ```
-
-## Methods - -| Methods | Setter | Description | -| ------------------------------------ | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| protected `trackCharacter` | `setTrackingCharacter(trackCharacter: string)` | The character to track in the text input field. This can be used to start capturing texts to format. Example: This would be `#` in case of HashTags. And a HashTag formatter would start capturing texts as soon as it encounters `#`. | -| protected `currentCaretPosition` | `setCaretPositionAndRange(currentCaretPosition: Selection, currentRange: Range)` | Message Composer sets the current selection in this field. | -| protected `currentRange` | `setCaretPositionAndRange(currentCaretPosition: Selection, currentRange: Range)` | Message Composer sets the text range that the user has selected or the cursor position in this field. | -| protected `inputElementReference` | `setInputElementReference(inputElementReference: HTMLElement)` | Message Composer sets the Reference to the text input field(DOM element) in this field. This can be used to `read` the `textContent`. | -| protected `regexPatterns` | `setRegexPatterns(regexPatterns: Array)` | Array of regex patterns to find specific text pattern in the user input text in order to replace those with formatted texts. | -| protected `regexToReplaceFormatting` | `setRegexToReplaceFormatting(regexToReplaceFormatting: Array)` | Array of regex patterns to replace the formatter text with original text. | -| protected `keyUpCallBack` | `setKeyUpCallBack(keyUpCallBack: Function)` | The callback function to be called for key up events. | -| protected `keyDownCallBack` | `setKeyDownCallBack(keyDownCallBack: Function)` | The callback function to be called for key down events. | -| protected `reRender` | `setReRender(reRender: Function)` | Callback function to be called in order to trigger a re-render of the message composer component. This is useful for force rerendering the composer in order to update text content on the UI. | -| protected `loggedInUser` | `setLoggedInUser(loggedInUser: CometChat.User)` | Composer and text bubbles will set the logged in user object in this field. | -| protected `id` | `setId(id: string)` | Use this to set a unique id for the formatter instance. | - - +--- -The `textContent` or `innerHtml` of the reference element should not be directly modified in a formatter. The formatters should instead call the `reRender` callback to force the composer to call the `getFormattedText` function of the formatter instead. +## Methods Reference + +| Field | Setter | Description | +| --- | --- | --- | +| `trackCharacter` | `setTrackingCharacter(char)` | Character that starts tracking (e.g. `#` for hashtags) | +| `currentCaretPosition` | `setCaretPositionAndRange(selection, range)` | Current selection set by the composer | +| `currentRange` | `setCaretPositionAndRange(selection, range)` | Text range or cursor position set by the composer | +| `inputElementReference` | `setInputElementReference(element)` | DOM reference to the composer input field | +| `regexPatterns` | `setRegexPatterns(patterns)` | Regex patterns to match text for formatting | +| `regexToReplaceFormatting` | `setRegexToReplaceFormatting(patterns)` | Regex patterns to strip formatting back to plain text | +| `keyUpCallBack` | `setKeyUpCallBack(fn)` | Callback for key up events | +| `keyDownCallBack` | `setKeyDownCallBack(fn)` | Callback for key down events | +| `reRender` | `setReRender(fn)` | Triggers a re-render of the composer to update displayed text | +| `loggedInUser` | `setLoggedInUser(user)` | Logged-in user object, set by composer and text bubbles | +| `id` | `setId(id)` | Unique identifier for the formatter instance | + +Don't modify `textContent` or `innerHTML` of the input element directly. Call `reRender` instead — the composer will invoke `getFormattedText` for all formatters in order. - - -Upon calling `reRender`, the composer will invoke the `getFormattedText` function for all text formatters, following the same order in which they were received as props. - - +--- -## Methods to be overriden for your custom formatter implementations: +## Override Methods -```js - /** - * If the input text is provided, it returns the formatted text. Otherwise, it edits the text using the current cursor position. - * @param {string|null} inputText - The text to format. - * @return {string|void} - The original or formatted input text, or void if editing was done based on cursor position. - */ - getFormattedText(inputText: string | null, params: any): string | void { - if (!inputText) { - //edit at cursor position and return void - return; - } - return this.customLogicToFromatText(inputText); + +Returns formatted HTML from input text, or edits at cursor position if `inputText` is null. + +```js lines +getFormattedText(inputText: string | null, params: any): string | void { + if (!inputText) { + return; // edit at cursor position } + return this.customLogicToFromatText(inputText); +} ``` -```js -/** - * Handles 'keydown' events. - * @param {KeyboardEvent} event - The keyboard event. - */ + +Handles `keyup` events. Start tracking when the track character is typed. + +```js lines onKeyUp(event: KeyboardEvent) { if (event.key == this.trackCharacter) { this.startTracking = true; } - //sample implementation if (this.startTracking && event.key == " ") { this.debouncedFormatTextOnKeyUp(); } @@ -325,32 +285,23 @@ onKeyUp(event: KeyboardEvent) { -```js -/** - * Handles 'keydown' events. - * @param {KeyboardEvent} event - The keyboard event. - */ + +Handles `keydown` events. + +```js lines onKeyDown(event: KeyboardEvent) {} ``` -```js -/** - * Composer and Text Bubbles will call this function when rendering the HTML content. - * This will be called for each HTML Element present in the formatted string. - * Each formatter will check if the HTML Element belongs to the formatter before registering event listeners - * Formatters can identify the respective HTML Element using unique css classes - * @param {HTMLElement} element - The element on which the events need to be registered - * @param {DOMTokenList} domTokenList - The classes to be added - * @return {HTMLElement} - The element with the registered event listeners - */ + +Called by the composer and text bubbles for each HTML element in the formatted string. Check for your formatter's CSS class before attaching listeners. + +```js lines registerEventListeners(element: HTMLElement, domTokenList: DOMTokenList) { - //sample implementation let classList: string[] = Array.from(domTokenList); for (let i = 0; i < classList.length; i++) { - //mentionsCssClassMapping is a list of unique css classes Mentions Formatter checks for if (classList[i] in this.mentionsCssClassMapping) { element.addEventListener("click", (event: Event) => { clearTimeout(this.timeoutID); @@ -407,30 +358,40 @@ registerEventListeners(element: HTMLElement, domTokenList: DOMTokenList) { -```js - /** - * Returns the original unformatted text from the input text. - * @param {string|null|undefined} inputText - The input text to get original text from. - * @return {string} - The original text. - */ - getOriginalText(inputText: string | null | undefined): string { - //sample implmentation - if (!inputText) { - return ""; - } - for (let i = 0; i < this.regexToReplaceFormatting.length; i++) { - let regexPattern = this.regexToReplaceFormatting[i]; - - if (inputText) { - inputText = inputText.replace(regexPattern, "$1"); - } - } - return inputText; +Strips formatting and returns plain text. +```js lines +getOriginalText(inputText: string | null | undefined): string { + if (!inputText) return ""; + for (let i = 0; i < this.regexToReplaceFormatting.length; i++) { + let regexPattern = this.regexToReplaceFormatting[i]; + if (inputText) { + inputText = inputText.replace(regexPattern, "$1"); + } + } + return inputText; } ``` + + +--- - \ No newline at end of file +## Next Steps + + + + Add @mentions with styled tokens. + + + Customize the message input component. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + diff --git a/ui-kit/react/events.mdx b/ui-kit/react/events.mdx index 0ba3e00fc..9d491bd7e 100644 --- a/ui-kit/react/events.mdx +++ b/ui-kit/react/events.mdx @@ -1,96 +1,98 @@ --- title: "Events" +description: "Reference for CometChat React UI Kit events including conversation, user, group, message, and call events." --- -## Overview + -Events allow for a decoupled, flexible architecture where different parts of the application can interact without having to directly reference each other. This makes it easier to create complex, interactive experiences, as well as to extend and customize the functionality provided by the CometChat UI Kit. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Conversation events | `ccConversationDeleted`, `ccUpdateConversation` | +| User events | `ccUserBlocked`, `ccUserUnblocked` | +| Group events | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnbanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` | +| Message events | `ccMessageSent`, `ccMessageEdited`, `ccReplyToMessage`, `ccMessageDeleted`, `ccMessageRead`, `ccLiveReaction`, plus SDK listener events | +| Call events | `ccOutgoingCall`, `ccCallAccepted`, `ccCallRejected`, `ccCallEnded` | +| UI events | `ccActiveChatChanged` | +| Purpose | Decoupled communication between UI Kit components — subscribe to events to react to changes without direct component references | -All components have the ability to emit events. These events are dispatched in response to certain changes or user interactions within the component. By emitting events, these components allow other parts of the application to react to changes or interactions, thus enabling dynamic and interactive behavior within the application. + + +Events provide decoupled communication between UI Kit components. Components emit events in response to user interactions or state changes, allowing other parts of the application to react without direct component references. ### CometChatConversationEvents -`CometChatConversationEvents` emits events when the logged-in user executes some action on a conversation object. +`CometChatConversationEvents` emits events when the logged-in user acts on a conversation object. | Name | Description | | ------------------------- | ------------------------------------------------------------------------------------------------ | -| ccConversationDeleted | This event is triggered when the user successfully deletes a conversation. | -| ccUpdateConversation | This event is triggered to update a conversation in the conversation list. Takes a Conversation object to update. | +| **ccConversationDeleted** | This event is triggered when the user successfully deletes a conversation. | +| **ccUpdateConversation** | This event is triggered to update a conversation in the conversation list. Takes a Conversation object to update. | ### CometChatUserEvents -`CometChatUserEvents` emits events when the logged-in user executes some action on an user object. - -It consists of the following events: +`CometChatUserEvents` emits events when the logged-in user acts on another user object. | Name | Description | | --------------- | ------------------------------------------------------------------------- | -| ccUserBlocked | This event is triggered when the user successfully blocks another user. | -| ccUserUnblocked | This event is triggered when the user successfully unblocks another user. | +| **ccUserBlocked** | This event is triggered when the user successfully blocks another user. | +| **ccUserUnblocked** | This event is triggered when the user successfully unblocks another user. | ### CometChatGroupEvents -`CometChatGroupEvents` emits events when the logged-in user executes some action on a group object. - -It consists of the following events: +`CometChatGroupEvents` emits events when the logged-in user acts on a group object. | Name | Description | | ------------------------- | ------------------------------------------------------------------------------------ | -| ccGroupCreated | This event is triggered when the user creates a group successfully | -| ccGroupDeleted | This event is triggered when the group member deletes the group successfully | -| ccGroupLeft | This event is triggered when the group member leaves the group successfully | -| ccGroupMemberScopeChanged | This event is triggered when the group member's scope is updated successfully | -| ccGroupMemberKicked | This event is triggered when the group member is kicked | -| ccGroupMemberBanned | This event is triggered when the group member is banned | -| ccGroupMemberUnbanned | This event is triggered when the group member is un-banned | -| ccGroupMemberJoined | This event is triggered when a user joins the group | -| ccGroupMemberAdded | This event is triggered when a user is added to the group | -| ccOwnershipChanged | This event is triggered when the group ownership is assigned to another group member | +| **ccGroupCreated** | This event is triggered when the user creates a group successfully | +| **ccGroupDeleted** | This event is triggered when the group member deletes the group successfully | +| **ccGroupLeft** | This event is triggered when the group member leaves the group successfully | +| **ccGroupMemberScopeChanged** | This event is triggered when the group member's scope is updated successfully | +| **ccGroupMemberKicked** | This event is triggered when the group member is kicked | +| **ccGroupMemberBanned** | This event is triggered when the group member is banned | +| **ccGroupMemberUnbanned** | This event is triggered when the group member is un-banned | +| **ccGroupMemberJoined** | This event is triggered when a user joins the group | +| **ccGroupMemberAdded** | This event is triggered when a user is added to the group | +| **ccOwnershipChanged** | This event is triggered when the group ownership is assigned to another group member | ### CometChatMessageEvents -`CometChatMessageEvents` emits events when the logged-in user executes some action on a message object. - -It consists of the following events: +`CometChatMessageEvents` emits events when the logged-in user acts on a message object. | Name | Description | | -------------------------- | --------------------------------------------------------------------------------------------------------- | -| ccMessageSent | This event is triggered when the sent message is in transit and also when it is received by the receiver. | -| ccMessageEdited | This event is triggered when the user successfully edits the message. | -| ccReplyToMessage | This event is triggered when the user successfully replies to a message. | -| ccMessageDeleted | This event is triggered when the user successfully deletes the message. | -| ccMessageRead | This event is triggered when the sent message is read by the receiver. | -| ccLiveReaction | This event is triggered when the user sends a live reaction. | -| onTextMessageReceived | This event is emitted when the CometChat SDK listener emits a text message. | -| onMediaMessageReceived | This event is emitted when the CometChat SDK listener emits a media message. | -| onCustomMessageReceived | This event is emitted when the CometChat SDK listener emits a custom message. | -| onTypingStarted | This event is emitted when the CometChat SDK listener indicates that a user has started typing. | -| onTypingEnded | This event is emitted when the CometChat SDK listener indicates that a user has stopped typing. | -| onMessagesDelivered | This event is emitted when the CometChat SDK listener indicates that messages have been delivered. | -| onMessagesRead | This event is emitted when the CometChat SDK listener indicates that messages have been read. | -| onMessageEdited | This event is emitted when the CometChat SDK listener indicates that a message has been edited. | -| onMessageDeleted | This event is emitted when the CometChat SDK listener indicates that a message has been deleted. | -| onTransientMessageReceived | This event is emitted when the CometChat SDK listener emits a transient message. | +| **ccMessageSent** | This event is triggered when the sent message is in transit and also when it is received by the receiver. | +| **ccMessageEdited** | This event is triggered when the user successfully edits the message. | +| **ccReplyToMessage** | This event is triggered when the user successfully replies to a message. | +| **ccMessageDeleted** | This event is triggered when the user successfully deletes the message. | +| **ccMessageRead** | This event is triggered when the sent message is read by the receiver. | +| **ccLiveReaction** | This event is triggered when the user sends a live reaction. | +| **onTextMessageReceived** | This event is emitted when the CometChat SDK listener emits a text message. | +| **onMediaMessageReceived** | This event is emitted when the CometChat SDK listener emits a media message. | +| **onCustomMessageReceived** | This event is emitted when the CometChat SDK listener emits a custom message. | +| **onTypingStarted** | This event is emitted when the CometChat SDK listener indicates that a user has started typing. | +| **onTypingEnded** | This event is emitted when the CometChat SDK listener indicates that a user has stopped typing. | +| **onMessagesDelivered** | This event is emitted when the CometChat SDK listener indicates that messages have been delivered. | +| **onMessagesRead** | This event is emitted when the CometChat SDK listener indicates that messages have been read. | +| **onMessageEdited** | This event is emitted when the CometChat SDK listener indicates that a message has been edited. | +| **onMessageDeleted** | This event is emitted when the CometChat SDK listener indicates that a message has been deleted. | +| **onTransientMessageReceived** | This event is emitted when the CometChat SDK listener emits a transient message. | ### CometChatCallEvents -`CometChatCallEvents` emits events when the logged-in user executes some action on a call object. - -It consists of the following events: +`CometChatCallEvents` emits events when the logged-in user acts on a call object. | Name | Description | | -------------- | ---------------------------------------------------------------------------- | -| ccOutgoingCall | This event is triggered when the user initiates a voice/video call. | -| ccCallAccepted | This event is triggered when the initiated call is accepted by the receiver. | -| ccCallRejected | This event is triggered when the initiated call is rejected by the receiver. | -| ccCallEnded | This event is triggered when the initiated call successfully ends. | +| **ccOutgoingCall** | This event is triggered when the user initiates a voice/video call. | +| **ccCallAccepted** | This event is triggered when the initiated call is accepted by the receiver. | +| **ccCallRejected** | This event is triggered when the initiated call is rejected by the receiver. | +| **ccCallEnded** | This event is triggered when the initiated call successfully ends. | ### UI events -UI events, refer to actions or interactions performed by a user within the CometChat's UI Kit. These events are triggered when a user interacts with various UI elements, such as buttons, menus, checkboxes, input fields, or any other interactive components. - -It consists of the following events: +UI events are triggered when a user interacts with UI Kit elements such as buttons, menus, or input fields. | Name | Description | | ------------------- | ---------------------------------------------------------------------------- | -| ccActiveChatChanged | This event is triggered when the user navigates to a particular chat window. | +| **ccActiveChatChanged** | This event is triggered when the user navigates to a particular chat window. | diff --git a/ui-kit/react/extensions.mdx b/ui-kit/react/extensions.mdx index 15f4332d9..6f35680c5 100644 --- a/ui-kit/react/extensions.mdx +++ b/ui-kit/react/extensions.mdx @@ -1,87 +1,197 @@ --- title: "Extensions" +description: "Overview of CometChat's extensions grouped by Dashboard categories (User Experience, User Engagement, Collaboration, Security, Customer Support, Smart Chat Features) and how they auto-integrate into React UI Kit components." --- -## Overview + + +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` + Extensions enabled in [CometChat Dashboard](/fundamentals/extensions-overview) | +| Extension categories | User Experience, User Engagement, Collaboration, Security, Customer Support, Smart Chat Features | +| Key components | `CometChatMessageComposer` → [Message Composer](/ui-kit/react/message-composer) (Stickers, Polls, Whiteboard, Document), `CometChatMessageList` → [Message List](/ui-kit/react/message-list) (Translation, Link Preview, Thumbnails) | +| Activation | Enable each extension from the CometChat Dashboard — UI Kit auto-integrates them, no additional code required | -CometChat's UI Kit offers built-in support for various extensions, enriching the chatting experience with enhanced functionality. These extensions augment your chat application, making it more interactive, secure, and efficient. + -Activating extensions within CometChat is a straightforward process through your application's dashboard. For detailed instructions, refer to our guide on [Extensions](/fundamentals/extensions-overview). +## Overview -Once you've enabled your desired extension in the dashboard, it seamlessly integrates into your CometChat application upon initialization and successful login. It's important to note that extension features will only be available if they are supported by the CometChat UI Kit. +CometChat UI Kit includes built-in support for extensions that add interactive, secure, and efficient features to chat. Extensions are activated from the [CometChat Dashboard](/fundamentals/extensions-overview) and auto-integrate into UI Kit components on init and login. -CometChat's UI Kit provides native support for 12 powerful extensions. This effortless integration enables you to enhance your chat application with engaging features without any additional coding. Simply enable the desired extensions from the CometChat Dashboard, and they will automatically enhance the relevant components of your application, providing a richer and more engaging experience for your users. + +Ensure `CometChatUIKit.init(UIKitSettings)` has completed and the user is logged in via `CometChatUIKit.login("UID")`. Extensions must be activated from the [CometChat Dashboard](/fundamentals/extensions-overview). + ## Built-in Extensions -Here's a guide on how you can enable and integrate these extensions: +The grouping below mirrors the CometChat Dashboard. + +### User Experience -### Stickers +#### Bitly -The Stickers extension allows users to express their emotions more creatively. It adds a much-needed fun element to the chat by allowing users to send various pre-designed stickers. For a comprehensive understanding and guide on implementing and using the Sticker Extension, refer to our specific guide on the [Sticker Extension](/fundamentals/stickers). +Shortens long URLs in text messages using Bitly. See [Bitly Extension](/fundamentals/bitly). -Once you have successfully activated the [Sticker Extension](/fundamentals/stickers) from your CometChat Dashboard, the feature will automatically be incorporated into the [Message Composer](/ui-kit/react/message-composer) component of UI Kits. +#### Link Preview + +Displays a summary (title, description, thumbnail) for URLs shared in chat. See [Link Preview Extension](/fundamentals/link-preview). + +Auto-integrates into the Message Bubble of [MessageList](/ui-kit/react/message-list) when activated. - + -### Polls +#### Message Shortcuts + +Sends predefined messages using short codes (e.g., `!hb` expands to `Happy birthday!`). See [Message Shortcuts Extension](/fundamentals/message-shortcuts). + +#### Pin Message + +Pins important messages in a conversation for easy access. See [Pin Message Extension](/fundamentals/pin-message). + +#### Rich Media Preview + +Generates rich preview panels for URLs using iFramely. See [Rich Media Preview Extension](/fundamentals/rich-media-preview). + +#### Save Message + +Bookmarks messages for later reference. Saved messages are private to the user. See [Save Message Extension](/fundamentals/save-message). -The Polls extension enhances group discussions by allowing users to create polls. Users can ask questions with a predefined list of answers, enabling a quick, organized way to gather group opinions. For a comprehensive understanding and guide on implementing and using the Polls Extension, refer to our specific guide on the [Polls Extension](/fundamentals/polls). +#### Thumbnail Generation -Once you have successfully activated the [Polls Extension](/fundamentals/polls) from your CometChat Dashboard, the feature will automatically be incorporated into the Action Sheet of the [Message Composer](/ui-kit/react/message-composer) component of UI Kits. +Creates smaller preview images for shared images, reducing bandwidth. See [Thumbnail Generation Extension](/fundamentals/thumbnail-generation). + +Auto-integrates into the Message Bubble of [MessageList](/ui-kit/react/message-list) when activated. - + -### Collaborative Whiteboard +#### TinyURL + +URL shortening using TinyURL. See [TinyURL Extension](/fundamentals/tinyurl). + +#### Voice Transcription + +Converts audio messages to text. See [Voice Transcription Extension](/fundamentals/voice-transcription). + +### User Engagement + +#### Giphy -The Collaborative Whiteboard extension facilitates real-time collaboration. Users can draw, brainstorm, and share ideas on a shared digital whiteboard. For a comprehensive understanding and guide on implementing and using the Collaborative Whiteboard Extension, refer to our specific guide on the [Collaborative Whiteboard Extension](/fundamentals/collaborative-whiteboard). +Search and share GIFs from Giphy. See [Giphy Extension](/fundamentals/giphy). -Once you have successfully activated the [Collaborative Whiteboard Extension](/fundamentals/collaborative-whiteboard) from your CometChat Dashboard, the feature will automatically be incorporated into the Action Sheet of the [Message Composer](/ui-kit/react/message-composer) component of UI Kits. +#### Message Translation + +Translates messages into the local locale. See [Message Translation Extension](/fundamentals/message-translation). + +Auto-integrates into the Action Sheet of [MessageList](/ui-kit/react/message-list) when activated. - + -### Collaborative Document +#### Polls -With the Collaborative Document extension, users can work together on a shared document. This feature is essential for remote teams where document collaboration is a recurring requirement. For a comprehensive understanding and guide on implementing and using the Collaborative Document Extension, refer to our specific guide on the [Collaborative Document Extension](/fundamentals/collaborative-document). +Creates polls in group discussions with predefined answer options. See [Polls Extension](/fundamentals/polls). -Once you have successfully activated the [Collaborative Document Extension](/fundamentals/collaborative-document) from your CometChat Dashboard, the feature will automatically be incorporated into the Action Sheet of the [Message Composer](/ui-kit/react/message-composer) component of UI Kits. +Auto-integrates into the Action Sheet of [Message Composer](/ui-kit/react/message-composer) when activated. - + -### Message Translation +#### Reminders + +Sets reminders for messages or creates personal reminders. A bot sends a notification when due. See [Reminders Extension](/fundamentals/reminders). -The Message Translation extension in CometChat is designed to translate any message into your local locale. It eliminates language barriers, making the chat more inclusive. For a comprehensive understanding and guide on implementing and using the Message Translation Extension, refer to our specific guide on the [Message Translation Extension](/fundamentals/message-translation). +#### Stickers -Once you have successfully activated the [Message Translation Extension](/fundamentals/message-translation) from your CometChat Dashboard, the feature will automatically be incorporated into the Action Sheet of [MessageList Component](/ui-kit/react/message-list) component of UI Kits. +Sends pre-designed stickers in chat. See [Sticker Extension](/fundamentals/stickers). + +Auto-integrates into [Message Composer](/ui-kit/react/message-composer) when activated. - + -### Link Preview +#### Stipop + +Integrates Stipop's sticker library. See [Stipop Extension](/fundamentals/stickers-stipop). + +#### Tenor + +Search and share GIFs from Tenor. See [Tenor Extension](/fundamentals/tenor). + +### Collaboration + +#### Collaborative Document -The Link Preview extension provides a summary of the URL shared in the chat. It includes the title, a description, and a thumbnail image from the web page. For a comprehensive understanding and guide on implementing and using the Link Preview Extension, refer to our specific guide on the [Link Preview Extension](/fundamentals/link-preview). +Shared document editing for real-time collaboration. See [Collaborative Document Extension](/fundamentals/collaborative-document). -Once you have successfully activated the [Link Preview Extension](/fundamentals/link-preview) from your CometChat Dashboard, the feature will automatically be incorporated into the Message Bubble of [MessageList Component](/ui-kit/react/message-list) component of UI Kits. +Auto-integrates into the Action Sheet of [Message Composer](/ui-kit/react/message-composer) when activated. - + -### Thumbnail Generation +#### Collaborative Whiteboard -The Thumbnail Generation extension automatically creates a smaller preview image whenever a larger image is shared, helping to reduce the upload/download time and bandwidth usage. For a comprehensive understanding and guide on implementing and using the Thumbnail Generation Extension, refer to our specific guide on the [Thumbnail Generation Extension](/fundamentals/thumbnail-generation). +Real-time shared whiteboard for drawing and brainstorming. See [Collaborative Whiteboard Extension](/fundamentals/collaborative-whiteboard). -Once you have successfully activated the [Thumbnail Generation Extension](/fundamentals/thumbnail-generation) from your CometChat Dashboard, the feature will automatically be incorporated into the Message Bubble of [MessageList Component](/ui-kit/react/message-list) component of UI Kits. +Auto-integrates into the Action Sheet of [Message Composer](/ui-kit/react/message-composer) when activated. - + + +### Security + +#### Disappearing Messages + +Messages auto-delete after a specified interval. Works for 1:1 and group messages. See [Disappearing Messages Extension](/fundamentals/disappearing-messages). + +### Customer Support + +#### Chatwoot + +Routes user messages to Chatwoot for customer support. See [Chatwoot Extension](/fundamentals/chatwoot). + +#### Intercom + +Integrates Intercom for in-app customer support. See [Intercom Extension](/fundamentals/intercom). + +### Smart Chat Features + +#### Conversation Starter + +AI-generated opening messages for new chats. See [Conversation Starter](/fundamentals/ai-user-copilot/conversation-starter) and [AI Features](/ui-kit/react/ai-features). + +#### Smart Replies + +AI-generated response suggestions based on conversation context. See [Smart Replies](/fundamentals/ai-user-copilot/smart-replies) and [AI Features](/ui-kit/react/ai-features). + +#### Conversation Summary + +AI-generated recap of long conversations. See [Conversation Summary](/fundamentals/ai-user-copilot/conversation-summary) and [AI Features](/ui-kit/react/ai-features). + +--- + +## Next Steps + + + + Customize the composer where most extensions appear + + + Customize the message list for extension-rendered content + + + Core chat features like messaging and reactions + + + AI-powered chat capabilities + + diff --git a/ui-kit/react/group-members.mdx b/ui-kit/react/group-members.mdx index ce7ec270f..3546a6372 100644 --- a/ui-kit/react/group-members.mdx +++ b/ui-kit/react/group-members.mdx @@ -1,1463 +1,1197 @@ --- title: "Group Members" +description: "Scrollable, searchable list of members in a specific group with roles, scopes, online status, and member management actions." --- + +```json +{ + "component": "CometChatGroupMembers", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatGroupMembers } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Scrollable, searchable list of members in a specific group with roles, scopes, online status, and member management actions.", + "cssRootClass": ".cometchat-group-members", + "primaryOutput": { + "prop": "onItemClick", + "type": "(groupMember: CometChat.GroupMember) => void" + }, + "props": { + "data": { + "group": { + "type": "CometChat.Group", + "required": true, + "note": "The group whose members are displayed" + }, + "groupMemberRequestBuilder": { + "type": "CometChat.GroupMembersRequestBuilder", + "default": "SDK default (30 per page)", + "note": "Pass the builder, not the result of .build()" + }, + "searchRequestBuilder": { + "type": "CometChat.GroupMembersRequestBuilder", + "default": "undefined" + }, + "searchKeyword": { + "type": "string", + "default": "\"\"" + } + }, + "callbacks": { + "onItemClick": "(groupMember: CometChat.GroupMember) => void", + "onSelect": "(groupMember: CometChat.GroupMember, selected: boolean) => void", + "onEmpty": "() => void", + "onError": "((error: CometChat.CometChatException) => void) | null" + }, + "visibility": { + "hideSearch": { "type": "boolean", "default": false }, + "hideError": { "type": "boolean", "default": false }, + "hideKickMemberOption": { "type": "boolean", "default": false }, + "hideBanMemberOption": { "type": "boolean", "default": false }, + "hideScopeChangeOption": { "type": "boolean", "default": false }, + "hideUserStatus": { "type": "boolean", "default": false }, + "disableLoadingState": { "type": "boolean", "default": false }, + "showScrollbar": { "type": "boolean", "default": false } + }, + "selection": { + "selectionMode": { + "type": "SelectionMode", + "values": ["SelectionMode.single (0)", "SelectionMode.multiple (1)", "SelectionMode.none (2)"], + "default": "SelectionMode.none" + } + }, + "viewSlots": { + "itemView": "(groupMember: CometChat.GroupMember) => JSX.Element", + "leadingView": "(groupMember: CometChat.GroupMember) => JSX.Element", + "titleView": "(groupMember: CometChat.GroupMember) => JSX.Element", + "subtitleView": "(groupMember: CometChat.GroupMember) => JSX.Element", + "trailingView": "(groupMember: CometChat.GroupMember) => JSX.Element", + "headerView": "JSX.Element", + "loadingView": "JSX.Element", + "emptyView": "JSX.Element", + "errorView": "JSX.Element", + "options": "(group: CometChat.Group, groupMember: CometChat.GroupMember) => CometChatOption[]" + } + }, + "events": [ + { + "name": "CometChatGroupEvents.ccGroupMemberKicked", + "payload": "IGroupMemberKickedBanned", + "description": "Member kicked" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberBanned", + "payload": "IGroupMemberKickedBanned", + "description": "Member banned" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberScopeChanged", + "payload": "IGroupMemberScopeChanged", + "description": "Member scope changed" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberAdded", + "payload": "IGroupMemberAdded", + "description": "Members added" + } + ], + "sdkListeners": [ + "onGroupMemberScopeChanged", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onMemberAddedToGroup", + "onGroupMemberLeft", + "onGroupMemberJoined", + "onUserOnline", + "onUserOffline" + ], + "types": { + "CometChatOption": { + "id": "string | undefined", + "title": "string | undefined", + "iconURL": "string | undefined", + "onClick": "(() => void) | undefined" + }, + "SelectionMode": { + "single": 0, + "multiple": 1, + "none": 2 + } + } +} +``` + + +## Where It Fits + +`CometChatGroupMembers` is a panel component that renders the member list for a specific group. It requires a `group` prop and provides built-in member management actions (kick, ban, scope change) based on the logged-in user's role. Typically rendered alongside the message view in a group chat layout. + +```tsx lines +import { useEffect, useState } from "react"; +import { + CometChatGroupMembers, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function GroupChatWithMembers() { + const [group, setGroup] = useState(); + + useEffect(() => { + CometChat.getGroup("GROUP_GUID").then(setGroup); + }, []); -## Overview + if (!group) return null; -`CometChatGroupMembers` is a Component that displays all users added or invited to a group, granting them access to group discussions, shared content, and collaborative features. Group members can communicate in real-time via messaging, voice and video calls, and other activities. They can interact, share files, and join calls based on group permissions set by the administrator or owner. + return ( +
+
+ +
+
+ + + +
+
+ ); +} +``` -*** - -## Usage - -### Integration +--- -The following code snippet illustrates how you can directly incorporate the Group Members component into your Application. +## Minimal Render - - -```tsx -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines +import { useEffect, useState } from "react"; import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import "@cometchat/chat-uikit-react/css-variables.css"; -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); +function GroupMembersDemo() { + const [group, setGroup] = useState(); - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + useEffect(() => { + CometChat.getGroup("GROUP_GUID").then(setGroup); }, []); - return <>{chatGroup && }; -}; + return group ? ( +
+ +
+ ) : null; +} export default GroupMembersDemo; ``` -
+Root CSS class: `.cometchat-group-members` + +--- + +## Filtering Group Members + +Pass a `CometChat.GroupMembersRequestBuilder` to `groupMemberRequestBuilder`. Pass the builder instance — not the result of `.build()`. - -```tsx -import { GroupMembersDemo } from "./GroupMembersDemo"; +```tsx lines +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export default function App() { +function FilteredGroupMembers({ group }: { group: CometChat.Group }) { return ( -
- -
+ ); } ``` -
- -
+### Filter Recipes -*** +| Recipe | Code | +| --- | --- | +| Limit to 10 per page | `new CometChat.GroupMembersRequestBuilder("GUID").setLimit(10)` | +| Search by keyword | `new CometChat.GroupMembersRequestBuilder("GUID").setSearchKeyword("john")` | +| Admins and moderators only | `new CometChat.GroupMembersRequestBuilder("GUID").setScopes(["admin", "moderator"])` | -### Actions +Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom. -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +The `searchRequestBuilder` prop accepts a separate `GroupMembersRequestBuilder` for filtering when the search bar is active. -##### 1. onSelect +Refer to [GroupMembersRequestBuilder](/sdk/javascript/retrieve-group-members) for the full builder API. -The `onSelect` action is activated when you select the done icon while in selection mode. This returns a list of all the group members that you have selected. +--- -This action does not come with any predefined behavior. However, you have the flexibility to override this event and tailor it to suit your needs using the following code snippet. +## Actions and Events - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatGroupMembers, - SelectionMode, -} from "@cometchat/chat-uikit-react"; -import React from "react"; +### Callback Props -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); +#### onItemClick - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +Fires when a member row is tapped. - function handleOnSelect( - groupMembers: CometChat.GroupMember, - selected: boolean - ): void { - console.log(groupMembers, selected); - /** Your custom onSelect actions */ - } +```tsx lines +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +function GroupMembersWithClick({ group }: { group: CometChat.Group }) { return ( - <> - {chatGroup && ( - - )} - + { + console.log("Selected member:", member.getName()); + }} + /> ); -}; - -export default GroupMembersDemo; +} ``` - +#### onSelect - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; +Fires when a member is checked/unchecked in multi-select mode. Requires `selectionMode` to be set. + +```tsx lines +import { useState } from "react"; import { - CometChatGroupMembers, - SelectionMode, + CometChatGroupMembers, + SelectionMode, } from "@cometchat/chat-uikit-react"; -import React, { useEffect, useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +function BatchSelectMembers({ group }: { group: CometChat.Group }) { + const [selected, setSelected] = useState>(new Set()); - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); + return ( + { + setSelected((prev) => { + const next = new Set(prev); + const uid = member.getUid(); + isSelected ? next.add(uid) : next.delete(uid); + return next; }); - }, []); - - function handleOnSelect(groupMembers, selected) { - console.log(groupMembers); - /** Your custom onSelect actions - } - - return ( - <> - {chatGroup && ( - - )} - - ); -}; - -export default GroupMembersDemo; + }} + /> + ); +} ``` - - - - -##### 2. onItemClick +#### onEmpty -The `onItemClick` event is activated when you click on the Group Members List item. This action does not come with any predefined behavior. However, you have the flexibility to override this event and tailor it to suit your needs using the following code snippet. +Fires when the member list has no data to display. - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); - - function handleOnItemClick(groupMembers: CometChat.GroupMember): void { - console.log(groupMembers, "your custom on item click action"); - } +import { CometChat } from "@cometchat/chat-sdk-javascript"; +function GroupMembersWithEmpty({ group }: { group: CometChat.Group }) { return ( - <> - {chatGroup && ( - - )} - + console.log("No members found")} + /> ); -}; - -export default GroupMembersDemo; +} ``` - - - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import { useEffect, useState } from "react"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +#### onError - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +Fires on internal errors (network failure, auth issue, SDK exception). - function handleOnItemClick(groupMembers) { - console.log(groupMembers, "your custom on item click action"); - } +```tsx lines +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +function GroupMembersWithError({ group }: { group: CometChat.Group }) { return ( - <> - {chatGroup && ( - - )} - + { + console.error("CometChatGroupMembers error:", error); + }} + /> ); -}; - -export default GroupMembersDemo; +} ``` - +### Global UI Events - +`CometChatGroupEvents` emits events subscribable from anywhere in the application. The component both emits and subscribes to these events. -##### 3. onEmpty +Events emitted by this component: -This action allows you to specify a callback function to be executed when a certain condition, typically the absence of data or content, is met within the component or element. +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccGroupMemberKicked` | A member is kicked | `IGroupMemberKickedBanned` | +| `ccGroupMemberBanned` | A member is banned | `IGroupMemberKickedBanned` | +| `ccGroupMemberScopeChanged` | A member's scope changes | `IGroupMemberScopeChanged` | - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; +Events subscribed internally: + +| Event | Internal behavior | +| --- | --- | +| `ccGroupMemberKicked` | Removes the kicked member from the list | +| `ccGroupMemberBanned` | Removes the banned member from the list | +| `ccGroupMemberScopeChanged` | Updates the member's scope in the list | +| `ccGroupMemberAdded` | Appends newly added members to the list | -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); +```tsx lines +import { useEffect } from "react"; +import { CometChatGroupEvents } from "@cometchat/chat-uikit-react"; + +function useGroupMemberEvents() { + useEffect(() => { + const kickedSub = CometChatGroupEvents.ccGroupMemberKicked.subscribe( + (item) => { + console.log("Member kicked:", item.kickedUser.getName()); + } + ); + const scopeSub = CometChatGroupEvents.ccGroupMemberScopeChanged.subscribe( + (item) => { + console.log("Scope changed:", item.updatedUser.getName(), "to", item.scopeChangedTo); + } + ); - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + return () => { + kickedSub?.unsubscribe(); + scopeSub?.unsubscribe(); + }; }, []); +} +``` - function handleOnEmpty(): void { - console.log("your custom on empty actions"); - } +### SDK Events (Real-Time, Automatic) - return ( - <> - {chatGroup && ( - - )} - - ); -}; +The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required. -export default GroupMembersDemo; -``` +| SDK Listener | Internal behavior | +| --- | --- | +| `onGroupMemberScopeChanged` | Updates the member's scope in the list | +| `onGroupMemberKicked` | Removes the kicked member from the list | +| `onGroupMemberBanned` | Removes the banned member from the list | +| `onMemberAddedToGroup` | Appends the new member to the list | +| `onGroupMemberLeft` | Removes the member who left from the list | +| `onGroupMemberJoined` | Appends the joined member to the list | +| `onUserOnline` / `onUserOffline` | Updates the member's online/offline status (disabled when `hideUserStatus={true}`) | - + +In React 18 StrictMode, `useEffect` runs twice on mount in development. The component handles listener cleanup internally, but any additional listeners added alongside the component need cleanup in the `useEffect` return function to avoid duplicate event handling. + - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import { useEffect, useState } from "react"; +--- -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +## Custom View Slots - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +Each slot replaces a section of the default UI. Slots that accept a member parameter receive the `CometChat.GroupMember` object for that row. - function handleOnEmpty() { - console.log("your custom on empty actions"); - } +| Slot | Signature | Replaces | +| --- | --- | --- | +| `itemView` | `(groupMember: CometChat.GroupMember) => JSX.Element` | Entire list item row | +| `leadingView` | `(groupMember: CometChat.GroupMember) => JSX.Element` | Avatar / left section | +| `titleView` | `(groupMember: CometChat.GroupMember) => JSX.Element` | Name / title text | +| `subtitleView` | `(groupMember: CometChat.GroupMember) => JSX.Element` | Subtitle text | +| `trailingView` | `(groupMember: CometChat.GroupMember) => JSX.Element` | Right section (scope badge / actions) | +| `headerView` | `JSX.Element` | Entire header bar | +| `loadingView` | `JSX.Element` | Loading spinner | +| `emptyView` | `JSX.Element` | Empty state | +| `errorView` | `JSX.Element` | Error state | +| `options` | `(group: CometChat.Group, groupMember: CometChat.GroupMember) => CometChatOption[]` | Context menu / hover actions | - return ( - <> - {chatGroup && ( - - )} - - ); -}; +### itemView -export default GroupMembersDemo; -``` +Replace the entire list item row. - +Default: - + + + -##### 4. onError +Customized: -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Group Members component. + + + -```ts +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); - - function handleOnError(error: CometChat.CometChatException): void { - /** Your Custom on error actions */ - } +import { + CometChatAvatar, + CometChatGroupMembers, +} from "@cometchat/chat-uikit-react"; - return ( - <> - {chatGroup && ( - - )} - - ); -}; +function CustomItemViewMembers({ group }: { group: CometChat.Group }) { + const getItemView = (member: CometChat.GroupMember) => { + const scope = member.getScope(); + return ( +
+
+ +
+
+
{member.getName()}
+
+ {scope} +
+
+
+ ); + }; -export default GroupMembersDemo; + return ; +} ``` -
+ +```css lines +.group-member-list-item { + display: flex; + min-width: 240px; + padding: 8px 16px; + align-items: center; + gap: 12px; + background: #fff; +} - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import { useEffect, useState } from "react"; +.group-member-list-item__content { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} + +.group-member-list-item__avatar { + width: 40px; + height: 40px; +} -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +.group-member-list-item__content-name { + overflow: hidden; + color: #141414; + text-overflow: ellipsis; + font: 500 16px Roboto; +} - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +.group-member-list-item__content-tag { + display: flex; + padding: 4px 12px; + border-radius: 1000px; + background: #edeafa; + color: #6852d6; + font: 400 12px Roboto; +} - function handleOnError(error) { - /** Your Custom on error actions */ - } +.group-member-list-item__content-tag-owner { + background: #6852d6; + color: #fff; +} - return ( - <> - {chatGroup && ( - - )} - - ); -}; +.group-member-list-item__content-tag-admin { + border: 1px solid #6852d6; +} -export default GroupMembersDemo; +.group-member-list-item__content-tag-participant { + display: none; +} ``` - -
-*** - -### Filters +### subtitleView -**Filters** allow you to customize the data displayed in a list within a Component. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using RequestBuilders of Chat SDK. +Replace the subtitle text. Joined date example. -##### 1. GroupMembersRequestBuilder +Default: -The [GroupMembersRequestBuilder](/sdk/javascript/retrieve-group-members) enables you to filter and customize the group members list based on available parameters in GroupMembersRequestBuilder. This feature allows you to create more specific and targeted queries when fetching groups. The following are the parameters available in [GroupMembersRequestBuilder](/sdk/javascript/retrieve-group-members) - -| Methods | Type | Description | -| -------------------- | -------------- | ------------------------------------------------------------------------------------------------- | -| **setLimit** | number | sets the number of group members that can be fetched in a single request, suitable for pagination | -| **setSearchKeyword** | String | used for fetching group members matching the passed string | -| **setScopes** | Array\ | used for fetching group members based on multiple scopes | + + + -**Example** +Customized: -In the example below, we are applying a filter to the Group Members by setting the limit to two and setting the scope to show only admin and moderator. + + + -```ts +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); - return ( - <> - {chatGroup && ( - - )} - - ); -}; +function SubtitleMembers({ group }: { group: CometChat.Group }) { + const getSubtitleView = (member: CometChat.GroupMember) => { + const date = new Date(member.getJoinedAt() * 1000).toLocaleDateString(); + return
Joined: {date}
; + }; -export default GroupMembersDemo; + return ; +} +``` +
+ +```css lines +.group-member-subtitle { + overflow: hidden; + color: #727272; + text-overflow: ellipsis; + white-space: nowrap; + font: 400 14px Roboto; +} ``` - +
- -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import { useEffect, useState } from "react"; +### trailingView -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +Replace the right section. Scope tag example. - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +Default: - return ( - <> - {chatGroup && ( - - )} - - ); -}; + + + -export default GroupMembersDemo; -``` +Customized: - + + + + + + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; + +function TrailingViewMembers({ group }: { group: CometChat.Group }) { + const getTrailingView = (member: CometChat.GroupMember) => { + return ( +
+ {member.getScope()} +
+ ); + }; + return ; +} +``` +
+ +```css lines +.group-member-scope-tag { + display: flex; + padding: 4px 12px; + border-radius: 1000px; + background: #edeafa; + color: #6852d6; + font: 400 12px Roboto; +} +``` +
-##### 2. SearchRequestBuilder +### headerView -The SearchRequestBuilder uses [GroupMembersRequestBuilder](/sdk/javascript/retrieve-group-members) enables you to filter and customize the search list based on available parameters in GroupMembersRequestBuilder. This feature allows you to keep uniformity between the displayed Group Members List and searched Group Members List. +Replace the entire header bar. -**Example** + + + -```ts +```tsx lines +import { + CometChatGroupMembers, + CometChatButton, + getLocalizedString, +} from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +function CustomHeaderMembers({ group }: { group: CometChat.Group }) { return ( - <> - {chatGroup && ( - - )} - + +
+ {getLocalizedString("GROUP_MEMBERS")} +
+ { /* handle click */ }} /> +
+ } + /> ); -}; - -export default GroupMembersDemo; +} ``` +
+ +```css lines +.group-members__header { + display: flex; + width: 100%; + padding: 8px 16px; + align-items: center; + justify-content: space-between; + gap: 12px; + border-radius: 10px; + border: 1px solid #e8e8e8; + background: #edeafa; +} +.group-members__header__title { + overflow: hidden; + color: #141414; + text-overflow: ellipsis; + font: 700 24px Roboto; +} +``` +
- -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import { useEffect, useState } from "react"; +### options -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +Replace the context menu / hover actions on each member item. The `options` callback receives both the group and the member. - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); + + + + + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatGroupMembers, + CometChatOption, +} from "@cometchat/chat-uikit-react"; + +function CustomOptionsMembers({ group }: { group: CometChat.Group }) { return ( - <> - {chatGroup && ( - - )} - + [ + new CometChatOption({ + id: "kick", + title: "Kick User", + onClick: () => { /* kick logic */ }, + }), + ]} + /> ); -}; - -export default GroupMembersDemo; +} ``` - + +```css lines +.cometchat-group-members .cometchat-menu-list__main-menu-item-icon { + background: #f44649; +} +.cometchat-group-members .cometchat-menu-list__menu { + background: transparent; + box-shadow: none; +} +``` + -*** - -### Events - -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +--- -Events emitted by the Group Members component is as follows. +## Common Patterns -| Event | Description | -| ----------------------------- | ----------------------------------------------------------------- | -| **ccGroupMemberBanned** | Triggers when the group member banned from the group successfully | -| **ccGroupMemberKicked** | Triggers when the group member kicked from the group successfully | -| **ccGroupMemberScopeChanged** | Triggers when the group member scope is changed in the group | +### Hide member management actions - - -```tsx -const ccGroupMemberBanned = CometChatGroupEvents.ccGroupMemberBanned.subscribe( - (item: IGroupMemberKickedBanned) => { - /** Your Code */ - } -); - -const ccGroupMemberKicked = CometChatGroupEvents.ccGroupMemberKicked.subscribe( - (item: IGroupMemberKickedBanned) => { - /** Your Code */ - } -); +```tsx lines +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const ccGroupMemberScopeChanged = - CometChatGroupEvents.ccGroupMemberScopeChanged.subscribe( - (item: IGroupMemberScopeChanged) => { - /** Your Code */ - } +function ReadOnlyMembers({ group }: { group: CometChat.Group }) { + return ( + ); +} ``` - +### Admins and moderators only - +```tsx lines +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -*** +function AdminMembers({ group }: { group: CometChat.Group }) { + return ( + + ); +} +``` - - -```tsx -ccGroupMemberBanned?.unsubscribe(); +### Minimal chrome -ccGroupMemberKicked?.unsubscribe(); +```tsx lines +import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -ccGroupMemberScopeChanged?.unsubscribe(); +function MinimalMembers({ group }: { group: CometChat.Group }) { + return ( + + ); +} ``` - +--- - +## CSS Architecture -*** +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: -## Customization +1. Global tokens (e.g., `--cometchat-primary-color`, `--cometchat-background-color-01`) are set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-group-members`) consumes these tokens via `var()` with fallback values. +3. Overrides target `.cometchat-group-members` descendant selectors in a global stylesheet. -To fit your app's design requirements, you can customize the appearance of the Group Members component. +### Key Selectors -### Style +| Target | Selector | +| --- | --- | +| Root | `.cometchat-group-members` | +| Header title | `.cometchat-group-members .cometchat-list__header-title` | +| List item | `.cometchat-group-members .cometchat-list-item` | +| Body title | `.cometchat-group-members .cometchat-list-item__body-title` | +| Trailing view | `.cometchat-group-members .cometchat-list-item__trailing-view` | +| Scope badge | `.cometchat-group-members__trailing-view-options` | +| Admin scope badge | `.cometchat-group-members__trailing-view-options-admin` | +| Owner scope badge | `.cometchat-group-members__trailing-view-options-owner` | +| Participant scope badge | `.cometchat-group-members__trailing-view-options-participant` | +| Online status | `.cometchat-group-members__list-item-online .cometchat-list-item__status` | +| Scope change dropdown | `.cometchat-group-members .cometchat-menu-list__sub-menu` | +| Empty state | `.cometchat-group-members__empty-state-view` | +| Error state | `.cometchat-group-members__error-state-view` | +| Shimmer loading | `.cometchat-group-members__shimmer` | +| Backdrop (modal) | `.cometchat-group-members__backdrop` | -Using CSS you can customize the look and feel of the component in your app like the color, size, shape, and fonts. +### Example: Brand-themed group members - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; -import "./GroupMembersStyle.css"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); - - return <>{chatGroup && }; -}; - -export default GroupMembersDemo; -``` - - - - -```css +```css lines .cometchat-group-members .cometchat-list__header-title { background: #feede1; color: #f76808; font-family: "Times New Roman"; } -.cometchat-group-members .cometchat-list-item__body-title, -.cometchat-group-members .cometchat-search-bar__input::placeholder { +.cometchat-group-members .cometchat-list-item__body-title { font-family: "Times New Roman"; } .cometchat-group-members .cometchat-group-members__trailing-view-options { - background: #feede1; - color: #f76808; font-family: "Times New Roman"; } - -.cometchat-group-members .cometchat-group-members__trailing-view-options-admin { - border: 1px solid #f76808; -} - -.cometchat-group-members .cometchat-group-members__trailing-view-options-owner { - background: #f76808; - color: #fff; - font-family: "Times New Roman"; -} - -.cometchat-group-members .cometchat-list-item__leading-view, -.cometchat-group-members .cometchat-avatar { - height: 40px; - width: 40px; -} ``` - +### Customization Matrix - +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Component props | `on` callbacks | `onItemClick={(m) => openProfile(m)}` | +| Filter which members appear | Component props | `groupMemberRequestBuilder` | `groupMemberRequestBuilder={new CometChat.GroupMembersRequestBuilder("GUID").setScopes(["admin"])}` | +| Toggle visibility of UI elements | Component props | `hide` boolean props | `hideKickMemberOption={true}` | +| Replace a section of the list item | Component props | `View` render props | `subtitleView={(m) =>
{m.getScope()}
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-group-members` class | `.cometchat-group-members .cometchat-avatar { border-radius: 8px; }` | -*** +--- -### Functionality +## Accessibility -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. +The component renders a scrollable list of interactive items. Each member row is keyboard-focusable and activates on Enter/Space. The scope change dropdown and context menu (options) are accessible via keyboard. Online status indicators use CSS — add `aria-label` attributes via `itemView` if screen reader descriptions are needed. - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +--- - return ( - <> - {chatGroup && ( - - )} - - ); -}; +--- -export default GroupMembersDemo; -``` +## Props - +All props are optional unless noted otherwise. - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import { useEffect, useState } from "react"; +--- -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = useState(null); +### disableLoadingState - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +Skips the loading spinner when re-fetching. - return ( - <> - {chatGroup && ( - - )} - - ); -}; +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -export default GroupMembersDemo; -``` +--- - +### emptyView - +Custom component displayed when there are no members. -Below is a list of customizations along with corresponding code snippets, +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in empty state | -| Property | Description | Code | -| ---------------------------- | ------------------------------------------------------------------------- | ---------------------------------------- | -| **Hide Search** | Hides the default search bar. | `hideSearch={true}` | -| **Hide Error** | Hides the default and custom error view passed in `errorView` prop. | `hideError={true}` | -| **Hide Kick Member Option** | Hides the option to kick a member from the group. | `hideKickMemberOption={true}` | -| **Hide Ban Member Option** | Hides the option to ban a member from the group. | `hideBanMemberOption={true}` | -| **Hide Scope Change Option** | Hides the option to change the scope of a group member. | `hideScopeChangeOption={true}` | -| **Hide User Status** | Hides the user's online/offline status indicator. | `hideUserStatus={true}` | -| **Group** | The group for which members are being fetched. | `group={chatGroup}` | -| **Search Keyword** | The keyword used to filter the group members list. | `searchKeyword="admin"` | -| **Selection Mode** | Selection mode to use for the default list item view. | `selectionMode={SelectionMode.multiple}` | -| **Show Scrollbar** | Controls the visibility of the scrollbar in the list. | `showScrollbar={true}` | -| **Loading View** | A custom view to display during the loading state. | `loadingView={}` | -| **Error View** | Custom view for the error state of the component. | `errorView={}` | -| **Empty View** | A custom view to display when no group members are available in the list. | | +--- -*** +### errorView -### Advanced +Custom component displayed when an error occurs. -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in error state | -*** +Hidden when `hideError={true}`. -#### ItemView +--- -With this property, you can assign a custom ListItem to the Group Members Component. +### group -Shown below is the default chat interface. +The group whose members are fetched and displayed. **Required.** - - - +| | | +| --- | --- | +| Type | `CometChat.Group` | +| Default | — | -The customized chat interface is displayed below. +--- - - - +### groupMemberRequestBuilder -Use the following code to achieve the customization shown above. +Controls which members load and in what order. - - -```ts -import { CometChat, GroupMember } from "@cometchat/chat-sdk-javascript"; -import React from "react"; -import { - CometChatAvatar, - CometChatGroupMembers, - CometChatOption, - CometChatUIKitLoginListener, - GroupMemberUtils, - localize, -} from "@cometchat/chat-uikit-react"; -import "./GroupMembersStyle.css"; +| | | +| --- | --- | +| Type | `CometChat.GroupMembersRequestBuilder` | +| Default | SDK default (30 per page) | -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); +Pass the builder instance, not the result of `.build()`. - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +--- - const getCustomItemView = (groupMember: GroupMember) => { - const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - let scope: string | CometChatOption[] = - GroupMemberUtils.getViewMemberOptions( - groupMember, - chatGroup!, - loggedInUser?.getUid() - ); - if (typeof scope !== "string") { - scope = groupMember.getScope(); - } +### headerView - return ( -
-
- - {groupMember.getStatus() === "online" && ( -
- )} -
-
-
- {groupMember.getName()} -
-
- {localize(scope.toUpperCase())} -
-
-
- ); - }; +Custom component rendered as the entire header bar. - return ( - <> - {chatGroup && ( - - )} - - ); -}; +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in header with title | -export default GroupMembersDemo; -``` +--- - +### hideBanMemberOption - -```css -.group-member-list-item { - display: flex; - min-width: 240px; - max-width: 1440px; - padding: 8px 16px; - align-items: center; - gap: 12px; - flex: 1 0 0; - border-right: 1px solid #f5f5f5; - background: #fff; -} +Hides the option to ban a member from the group. -.group-member-list-item__content { - display: flex; - justify-content: space-between; - align-items: center; - align-self: stretch; - width: 100%; -} +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -.group-member-list-item__avatar { - display: flex; - width: 40px; - height: 40px; -} - -.group-member-list-item__avatar .cometchat-avatar, -.group-member-list-item__avatar .cometchat-avatar__image { - height: 40px; - width: 40px; - border-radius: 12px; -} - -.group-member-list-item__avatar-status { - width: 10px; - padding: 5px; - height: 10px; - border-radius: 1000px; - border: 1px solid #fff; - position: relative; - background: #09c26f; - left: -12px; - top: 30px; -} +--- -.group-member-list-item__content-name { - overflow: hidden; - color: #141414; - text-overflow: ellipsis; - font: 500 16px Roboto; -} +### hideError -.group-member-list-item__content-tag { - display: flex; - padding: 4px 12px; - justify-content: center; - align-items: center; - gap: 20px; - border-radius: 1000px; - background: #edeafa; - overflow: hidden; - color: #6852d6; - text-overflow: ellipsis; - font: 400 12px Roboto; -} +Hides the default and custom error views. -.group-member-list-item__content-tag-owner { - background: #6852d6; - color: #fff; -} +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -.group-member-list-item__content-tag-admin { - border: 1px solid #6852d6; -} +--- -.group-member-list-item__content-tag-participant { - display: none; -} -``` +### hideKickMemberOption - +Hides the option to kick a member from the group. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -*** +--- -#### TitleView +### hideScopeChangeOption -The customized chat interface is displayed below. +Hides the option to change the scope of a group member. - - - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Use the following code to achieve the customization shown above. +--- - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; - -// Custom title view component -const customTitleView = (member: CometChat.GroupMember) => { - return
- {member.getName()} - {member.getRole()} -
; -} +### hideSearch -; -``` +Hides the default search bar. -
+| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - -```css -.group-members__title-view{ - display: flex; - align-items: center; - gap: 4px; - align-self: stretch; - } - .group-members__title-view-name{ - overflow: hidden; - color: #141414; - text-overflow: ellipsis; - font:500 16px Roboto - } - .group-members__title-view-type{ - color: #FFF; - font: 600 8px Roboto; - display: flex; - height: 15px; - padding: 1px 3px; - justify-content: center; - align-items: center; - gap: 3px; - border-radius: 7px; - background: #09C26F; - } - .group-members__title-view-public .group-members__title-view-role{ - //add css based on roles - background: #0B7BEA; - } -``` +--- - +### hideUserStatus -
+Hides the user's online/offline status indicator. -*** +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -#### SubtitleView +--- -You can customize the subtitle view for each group members to meet your requirements. +### itemView -Shown below is the default chat interface. +Custom renderer for the entire list item row. - - - +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember) => JSX.Element` | +| Default | Built-in list item | -The customized chat interface is displayed below. +--- - - - +### leadingView -Use the following code to achieve the customization shown above. +Custom renderer for the avatar / left section. - - -```ts -import { CometChat, GroupMember } from "@cometchat/chat-sdk-javascript"; -import React from "react"; -import { CometChatGroupMembers } from "@cometchat/chat-uikit-react"; -import "./GroupMembersStyle.css"; +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember) => JSX.Element` | +| Default | Built-in avatar | -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +--- - const getCustomSubtitleView = (groupMember: GroupMember) => { - const formatTime = (timestamp: number) => { - const date = new Date(timestamp * 1000); - return date.toLocaleDateString(); - }; - return ( -
- {"Joined at: " + formatTime(groupMember.getJoinedAt())} -
- ); - }; +### loadingView - return ( - <> - {chatGroup && ( - - )} - - ); -}; +Custom component displayed during the loading state. -export default GroupMembersDemo; -``` +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in shimmer | -
+--- - -```css -.group-member-subtitle { - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - white-space: nowrap; - font: 400 14px Roboto; -} -``` +### onEmpty - +Callback fired when the member list is empty. -
+| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | -*** +--- -#### LeadingView +### onError -The customized chat interface is displayed below. +Callback fired when the component encounters an error. - - - +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | -Use the following code to achieve the customization shown above. +--- - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers,CometChatAvatar } from "@cometchat/chat-uikit-react"; +### onItemClick -// Custom leading view component -const customLeadingView = (member: CometChat.GroupMember): JSX.Element => { - // Determine the member's scope or owner status - const scope = member.getUid() === group.getOwner() ? "owner" : member.getScope(); +Callback fired when a member row is clicked. - return ( -
- - - {scope} -
- ); -}; -; -``` +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember) => void` | +| Default | `undefined` | -
+--- - -```css -.cometchat-group-members .cometchat-list-item .group-member__leading-view .cometchat-avatar__image, .cometchat-group-members .cometchat-list-item .group-member__leading-view .cometchat-avatar{ -border-radius: 8px; -height: 48px ; -width: 48px ; -} -.group-member__leading-view-scope{ -display: flex; -width: 48px; -height: 15px; -padding: 1px 3px; -justify-content: center; -align-items: center; -color:#FFF; -font:600 8px/9.6px Roboto; -background:#FFAB00; -position:absolute; -bottom:-2px; -} -.group-member__leading-view{ -position: relative; -} +### onSelect -.group-member__leading-view-participant .group-member__leading-view-scope{ -display: none; -} -.group-member__leading-view-owner .group-member__leading-view-scope{ -background: #0B7BEA; -} -.group-member__leading-view-admin .group-member__leading-view-scope{ -background: #FFAB00; -} -.group-member__leading-view-moderator .group-member__leading-view-scope{ -background: #09C26F; -} -``` +Callback fired when a member is selected/deselected. Requires `selectionMode` to be set. - +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember, selected: boolean) => void` | +| Default | `undefined` | -
+--- -*** +### options -#### TrailingView +Custom context menu / hover actions for each member item. -You can customize the trailing view for each group members to meet your requirements. +| | | +| --- | --- | +| Type | `(group: CometChat.Group, groupMember: CometChat.GroupMember) => CometChatOption[]` | +| Default | `undefined` | -Shown below is the default chat interface. +--- - - - +### searchKeyword -The customized chat interface is displayed below. +Pre-fills the search and filters the member list. - - - +| | | +| --- | --- | +| Type | `string` | +| Default | `""` | -Use the following code to achieve the customization shown above. +--- - - -```ts -import { CometChat, GroupMember } from "@cometchat/chat-sdk-javascript"; -import React from "react"; -import { - CometChatGroupMembers, - CometChatOption, - CometChatUIKitLoginListener, - GroupMemberUtils, - localize, -} from "@cometchat/chat-uikit-react"; -import "./GroupMembersStyle.css"; +### searchRequestBuilder -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); +Controls filtering when the search bar is active. - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +| | | +| --- | --- | +| Type | `CometChat.GroupMembersRequestBuilder` | +| Default | `undefined` | - const getCustomTrailingView = (groupMember: GroupMember) => { - const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - let scope: string | CometChatOption[] = - GroupMemberUtils.getViewMemberOptions( - groupMember, - chatGroup!, - loggedInUser?.getUid() - ); - if (typeof scope !== "string") { - scope = groupMember.getScope(); - } - return ( -
- {localize((scope as string).toUpperCase())} -
- ); - }; +--- - return ( - <> - {chatGroup && ( - - )} - - ); -}; +### selectionMode -export default GroupMembersDemo; -``` +Enables single or multi-select checkboxes on list items. -
+| | | +| --- | --- | +| Type | `SelectionMode` | +| Default | `SelectionMode.none` | - -```css -.group-member-scope-tag { - display: flex; - padding: 4px 12px; - justify-content: center; - align-items: center; - gap: 20px; - border-radius: 1000px; - background: #edeafa; - overflow: hidden; - color: #6852d6; - text-overflow: ellipsis; - font: 400 12px Roboto; +```ts lines +enum SelectionMode { + single, // 0 + multiple, // 1 + none, // 2 } ``` - - -
- -*** - -#### HeaderView - -You can set the Custom headerView to add more options to the Group Members component. - -The customized chat interface is displayed below. - - - - - -Use the following code to achieve the customization shown above. - - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroupMembers,localize } from "@cometchat/chat-uikit-react"; -import React from "react"; +--- -const getHeaderView = () => { - return ( -
-
- {localize("GROUP_MEMBERS")} -
- { - // logic here - }} - iconURL={ICON_URL} - /> -
- ); -}; +### showScrollbar - -``` +Shows the scrollbar in the member list. -
+| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - -```css -.cometchat-group-members__header { - display: flex; - width: 100%; - padding: 8px 16px; - align-items: center; - justify-content: space-between; - gap: 12px; - flex: 1 0 0; - align-self: stretch; - border-radius: 10px; - border: 1px solid #E8E8E8; - background: #EDEAFA; -} -.cometchat-group-members__header__title { - overflow: hidden; - color: #141414; - text-overflow: ellipsis; - font: 700 24px Roboto; -} -.cometchat-group-members__header .cometchat-button .cometchat-button__icon { - background: #6852D6; -} -.cometchat-group-members__header .cometchat-button{ - width: 24px; - border: none; - background: transparent; - border-radius: 0; - display: block; -} -``` - - - -
+--- -*** +### subtitleView -#### Options +Custom renderer for the subtitle text. -You can set the Custom options to the Group Members component. +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember) => JSX.Element` | +| Default | Built-in subtitle | -The customized chat interface is displayed below. +--- - - - +### titleView -Use the following code to achieve the customization shown above. +Custom renderer for the name / title text. - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatGroupMembers, - CometChatOption, -} from "@cometchat/chat-uikit-react"; -import React from "react"; -import "./GroupMembersStyle.css"; +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember) => JSX.Element` | +| Default | Built-in title | -const GroupMembersDemo = () => { - const [chatGroup, setChatGroup] = React.useState(); +--- - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +### trailingView - return ( - <> - {chatGroup && ( - { - const customOptions = [ - new CometChatOption({ - id: "1", - title: "Kick User", - onClick: () => { - /** Your logic for handling click of custom option. */ - }, - }), - ]; - return customOptions; - }} - /> - )} - - ); -}; +Custom renderer for the right section (scope badge / actions). -export default GroupMembersDemo; -``` +| | | +| --- | --- | +| Type | `(groupMember: CometChat.GroupMember) => JSX.Element` | +| Default | Built-in trailing view | - +--- - -```css -.cometchat-group-members .cometchat-menu-list__main-menu-item-icon { - height: 24px; - width: 24px; - -webkit-mask: url("./assets/delete.svg") center center no-repeat; - background: #f44649; -} +## Events -.cometchat-group-members .cometchat-menu-list__menu, -.cometchat-group-members .cometchat-menu-list__main-menu-item { - background: transparent; - box-shadow: none; -} -``` +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatGroupEvents.ccGroupMemberKicked` | `IGroupMemberKickedBanned` | Member kicked | +| `CometChatGroupEvents.ccGroupMemberBanned` | `IGroupMemberKickedBanned` | Member banned | +| `CometChatGroupEvents.ccGroupMemberScopeChanged` | `IGroupMemberScopeChanged` | Member scope changed | +| `CometChatGroupEvents.ccGroupMemberAdded` | `IGroupMemberAdded` | Members added | - +All events are RxJS `Subject` instances. Subscribe with `.subscribe()`, unsubscribe with the returned subscription's `.unsubscribe()`. - +--- -*** +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-group-members` | +| Header title | `.cometchat-group-members .cometchat-list__header-title` | +| List item | `.cometchat-group-members .cometchat-list-item` | +| Body title | `.cometchat-group-members .cometchat-list-item__body-title` | +| Trailing view | `.cometchat-group-members .cometchat-list-item__trailing-view` | +| Scope badge | `.cometchat-group-members__trailing-view-options` | +| Admin scope badge | `.cometchat-group-members__trailing-view-options-admin` | +| Owner scope badge | `.cometchat-group-members__trailing-view-options-owner` | +| Participant scope badge | `.cometchat-group-members__trailing-view-options-participant` | +| Online status | `.cometchat-group-members__list-item-online .cometchat-list-item__status` | +| Scope change dropdown | `.cometchat-group-members .cometchat-menu-list__sub-menu` | +| Scope change list | `.cometchat-group-members .cometchat-menu-list__sub-menu-list` | +| Empty state | `.cometchat-group-members__empty-state-view` | +| Empty state title | `.cometchat-group-members__empty-state-view-body-title` | +| Error state | `.cometchat-group-members__error-state-view` | +| Error state title | `.cometchat-group-members__error-state-view-body-title` | +| Shimmer loading | `.cometchat-group-members__shimmer` | +| Backdrop | `.cometchat-group-members__backdrop` | diff --git a/ui-kit/react/groups.mdx b/ui-kit/react/groups.mdx index 27bd1cd69..e05d40352 100644 --- a/ui-kit/react/groups.mdx +++ b/ui-kit/react/groups.mdx @@ -1,1129 +1,1345 @@ --- title: "Groups" +description: "Searchable, scrollable list of all available groups with icon, name, member count, and group type indicator." --- + +```json +{ + "component": "CometChatGroups", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatGroups } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Searchable, scrollable list of all available groups with icon, name, member count, and group type indicator.", + "cssRootClass": ".cometchat-groups", + "primaryOutput": { + "prop": "onItemClick", + "type": "(group: CometChat.Group) => void" + }, + "props": { + "data": { + "groupsRequestBuilder": { + "type": "CometChat.GroupsRequestBuilder", + "default": "SDK default (30 per page)", + "note": "Pass the builder, not the result of .build()" + }, + "searchRequestBuilder": { + "type": "CometChat.GroupsRequestBuilder", + "default": "undefined" + }, + "activeGroup": { + "type": "CometChat.Group", + "default": "undefined" + } + }, + "callbacks": { + "onItemClick": "(group: CometChat.Group) => void", + "onSelect": "(group: CometChat.Group, selected: boolean) => void", + "onError": "((error: CometChat.CometChatException) => void) | null" + }, + "visibility": { + "hideSearch": { "type": "boolean", "default": false }, + "hideError": { "type": "boolean", "default": false }, + "hideGroupType": { "type": "boolean", "default": false }, + "showScrollbar": { "type": "boolean", "default": false } + }, + "selection": { + "selectionMode": { + "type": "SelectionMode", + "values": ["SelectionMode.single (0)", "SelectionMode.multiple (1)", "SelectionMode.none (2)"], + "default": "SelectionMode.none" + } + }, + "viewSlots": { + "itemView": "(group: CometChat.Group) => JSX.Element", + "leadingView": "(group: CometChat.Group) => JSX.Element", + "titleView": "(group: CometChat.Group) => JSX.Element", + "subtitleView": "(group: CometChat.Group) => JSX.Element", + "trailingView": "(group: CometChat.Group) => JSX.Element", + "headerView": "JSX.Element", + "loadingView": "JSX.Element", + "emptyView": "JSX.Element", + "errorView": "JSX.Element", + "options": "(group: CometChat.Group) => CometChatOption[]" + } + }, + "events": [ + { + "name": "CometChatGroupEvents.ccGroupCreated", + "payload": "CometChat.Group", + "description": "New group created" + }, + { + "name": "CometChatGroupEvents.ccGroupDeleted", + "payload": "CometChat.Group", + "description": "Group deleted" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberJoined", + "payload": "IGroupMemberJoined", + "description": "User joins a group" + }, + { + "name": "CometChatGroupEvents.ccGroupLeft", + "payload": "IGroupLeft", + "description": "User leaves a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberAdded", + "payload": "IGroupMemberAdded", + "description": "Members added to a group" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberScopeChanged", + "payload": "IGroupMemberScopeChanged", + "description": "Member scope changed" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberKicked", + "payload": "IGroupMemberKickedBanned", + "description": "Member kicked" + }, + { + "name": "CometChatGroupEvents.ccGroupMemberBanned", + "payload": "IGroupMemberKickedBanned", + "description": "Member banned" + }, + { + "name": "CometChatGroupEvents.ccOwnershipChanged", + "payload": "IOwnershipChanged", + "description": "Ownership transferred" + } + ], + "sdkListeners": [ + "onGroupMemberJoined", + "onGroupMemberLeft", + "onMemberAddedToGroup", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onGroupMemberScopeChanged" + ], + "compositionExample": { + "description": "Group directory wired to message view", + "components": [ + "CometChatGroups", + "CometChatMessageHeader", + "CometChatMessageList", + "CometChatMessageComposer" + ], + "flow": "onItemClick emits CometChat.Group -> pass to MessageHeader, MessageList, MessageComposer" + }, + "types": { + "CometChatOption": { + "id": "string | undefined", + "title": "string | undefined", + "iconURL": "string | undefined", + "onClick": "(() => void) | undefined" + }, + "SelectionMode": { + "single": 0, + "multiple": 1, + "none": 2 + } + } +} +``` + -## Overview - -The Groups is a Component, showcasing an accessible list of all available groups. It provides an integral search functionality, allowing you to locate any specific groups swiftly and easily. For each group listed, the group name is displayed by default, in conjunction with the group icon when available. Additionally, it provides a useful feature by displaying the number of members in each group as a subtitle, offering valuable context about group size and activity level. +## Where It Fits - - - +`CometChatGroups` is a directory list component. It renders available groups and emits the selected `CometChat.Group` via `onItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a group chat layout. -The Groups component is composed of the following BaseComponents: +```tsx lines +import { useState } from "react"; +import { + CometChatGroups, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import "@cometchat/chat-uikit-react/css-variables.css"; -| Components | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------- | -| CometChatList | A reusable container component having title, search box, customisable background and a list view. | -| CometChatListItem | A component that renders data obtained from a Group object on a Tile having a title, subtitle, leading and trailing view. | +function GroupChatApp() { + const [selectedGroup, setSelectedGroup] = useState(); -*** + return ( +
+
+ setSelectedGroup(group)} + /> +
+ {selectedGroup ? ( +
+ + + +
+ ) : ( +
+ Select a group +
+ )} +
+ ); +} +``` -## Usage + + + -### Integration +--- -The following code snippet illustrates how you can directly incorporate the Groups component into your Application. +## Minimal Render - - -```tsx +```tsx lines import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - return ; -}; - -export default GroupsDemo; -``` - - - - -```tsx -import { GroupsDemo } from "./GroupsDemo"; +import "@cometchat/chat-uikit-react/css-variables.css"; -export default function App() { +function GroupsDemo() { return ( -
- +
+
); } -``` - - - - - -*** -### Actions +export default GroupsDemo; +``` -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +Root CSS class: `.cometchat-groups` -##### 1. onSelect +--- -The `onSelect` action is activated when you select the done icon while in selection mode. This returns the `group` object along with the boolean flag `selected` to indicate if the group was selected or unselected. +## Filtering Groups -This action does not come with any predefined behavior. However, you have the flexibility to override this event and tailor it to suit your needs using the following code snippet. +Pass a `CometChat.GroupsRequestBuilder` to `groupsRequestBuilder`. Pass the builder instance — not the result of `.build()`. - - -```ts +```tsx lines +import { CometChatGroups } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups, SelectionMode } from "@cometchat/chat-uikit-react"; -import React from "react"; -const GroupsDemo = () => { - function handleOnSelect(group: CometChat.Group, selected: boolean): void { - console.log(group); - //your custom onSelect actions - } +function FilteredGroups() { return ( ); -}; - -export default GroupsDemo; +} ``` - +### Filter Recipes - -```js -import { CometChatGroups, SelectionMode } from "@cometchat/chat-uikit-react"; -import React from "react"; +| Recipe | Code | +| --- | --- | +| Joined groups only | `new CometChat.GroupsRequestBuilder().joinedOnly(true)` | +| Limit to 10 per page | `new CometChat.GroupsRequestBuilder().setLimit(10)` | +| Search by keyword | `new CometChat.GroupsRequestBuilder().setSearchKeyword("design")` | +| Filter by tags | `new CometChat.GroupsRequestBuilder().setTags(["vip"])` | +| With tags data | `new CometChat.GroupsRequestBuilder().withTags(true)` | -const GroupsDemo = () => { - function handleOnSelect(group, selected) { - console.log(group); - //your custom onSelect actions - } +Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom. + +The `searchRequestBuilder` prop accepts a separate `GroupsRequestBuilder` for filtering when the search bar is active. + +```tsx lines +import { CometChatGroups } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function SearchFilteredGroups() { return ( ); -}; - -export default GroupsDemo; +} ``` - - - - -##### 2. onItemClick +Refer to [GroupsRequestBuilder](/sdk/javascript/retrieve-groups) for the full builder API. -The `onItemClick` event is activated when you click on the Group List item. This action does not come with any predefined behavior. However, you have the flexibility to override this event and tailor it to suit your needs using the following code snippet. +--- - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; +## Actions and Events -const GroupsDemo = () => { - function handleOnItemClick(group: CometChat.Group): void { - console.log(group, "your custom on item click action"); - } - return ; -}; +### Callback Props -export default GroupsDemo; -``` +#### onItemClick - +Fires when a group row is tapped. Primary navigation hook — set the active group and render the message view. - -```js +```tsx lines import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - function handleOnItemClick(group) { - console.log(group, "your custom on item click action"); - } - return ; -}; - -export default GroupsDemo; -``` - - - - - -##### 3. onError - -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Groups component. - - - -```ts import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - const handleOnError = (error: CometChat.CometChatException) => { - console.log("Your custom on error actions"); - }; - return ; -}; - -export default GroupsDemo; -``` - - - - -```js -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; -const GroupsDemo = () => { - const handleOnError = (error) => { - console.log("Your custom on error actions"); +function GroupsWithClick() { + const handleItemClick = (group: CometChat.Group) => { + console.log("Selected:", group.getGuid()); }; - return ; -}; -export default GroupsDemo; + return ; +} ``` - - - - -### Filters - -**Filters** allow you to customize the data displayed in a list within a Component. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using RequestBuilders of Chat SDK. - -##### 1. GroupsRequestBuilder - -The [GroupsRequestBuilder](/sdk/javascript/retrieve-groups) enables you to filter and customize the group list based on available parameters in [GroupsRequestBuilder](/sdk/javascript/retrieve-groups). This feature allows you to create more specific and targeted queries when fetching groups. The following are the parameters available in [GroupsRequestBuilder](/sdk/javascript/retrieve-groups) +#### onSelect -| Methods | Type | Description | -| -------------------- | -------------- | --------------------------------------------------------------------------------------- | -| **setLimit** | number | sets the number groups that can be fetched in a single request, suitable for pagination | -| **setSearchKeyword** | String | used for fetching groups matching the passed string | -| **joinedOnly** | boolean | to fetch only joined groups. | -| **setTags** | Array\ | used for fetching groups containing the passed tags | -| **withTags** | boolean | used to fetch tags data along with the list of groups | +Fires when a group is checked/unchecked in multi-select mode. Requires `selectionMode` to be set. -**Example** - -In the example below, we are applying a filter to the Group List based on only joined groups and setting the limit to two. - - - -```ts +```tsx lines +import { useState } from "react"; +import { + CometChatGroups, + SelectionMode, +} from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - return ( - - ); -}; - -export default GroupsDemo; -``` - +function BatchSelectGroups() { + const [selected, setSelected] = useState>(new Set()); - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; + const handleSelect = (group: CometChat.Group, isSelected: boolean) => { + setSelected((prev) => { + const next = new Set(prev); + const id = group.getGuid(); + isSelected ? next.add(id) : next.delete(id); + return next; + }); + }; -const GroupsDemo = () => { return ( ); -}; - -export default GroupsDemo; +} ``` - - - - -##### 2. SearchRequestBuilder +#### onError -The SearchRequestBuilder uses [GroupsRequestBuilder](/sdk/javascript/retrieve-groups) enables you to filter and customize the search list based on available parameters in GroupsRequestBuilder. This feature allows you to keep uniformity between the displayed Groups List and searched Group List. +Fires on internal errors (network failure, auth issue, SDK exception). -**Example** - - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const GroupsDemo = () => { +function GroupsWithErrorHandler() { return ( { + console.error("CometChatGroups error:", error); + }} /> ); -}; - -export default GroupsDemo; +} ``` - - - -```js +### Global UI Events + +`CometChatGroupEvents` emits events subscribable from anywhere in the application. Subscribe in a `useEffect` and unsubscribe on cleanup. + +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccGroupCreated` | A new group is created | `CometChat.Group` | +| `ccGroupDeleted` | A group is deleted | `CometChat.Group` | +| `ccGroupMemberJoined` | A user joins a group | `IGroupMemberJoined` | +| `ccGroupLeft` | A user leaves a group | `IGroupLeft` | +| `ccGroupMemberAdded` | Members are added to a group | `IGroupMemberAdded` | +| `ccGroupMemberScopeChanged` | A member's scope changes | `IGroupMemberScopeChanged` | +| `ccGroupMemberKicked` | A member is kicked | `IGroupMemberKickedBanned` | +| `ccGroupMemberBanned` | A member is banned | `IGroupMemberKickedBanned` | +| `ccGroupMemberUnbanned` | A member is unbanned | `IGroupMemberUnBanned` | +| `ccOwnershipChanged` | Group ownership is transferred | `IOwnershipChanged` | + +```tsx lines +import { useEffect } from "react"; +import { CometChatGroupEvents } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; -const GroupsDemo = () => { - return ( - - ); -}; +function useGroupEvents() { + useEffect(() => { + const createdSub = CometChatGroupEvents.ccGroupCreated.subscribe( + (group: CometChat.Group) => { + console.log("Group created:", group.getName()); + } + ); + const deletedSub = CometChatGroupEvents.ccGroupDeleted.subscribe( + (group: CometChat.Group) => { + console.log("Group deleted:", group.getName()); + } + ); + const memberAddedSub = CometChatGroupEvents.ccGroupMemberAdded.subscribe( + (item) => { + console.log("Members added to:", item.userAddedIn.getName()); + } + ); + const leftSub = CometChatGroupEvents.ccGroupLeft.subscribe( + (item) => { + console.log("User left group:", item.leftGroup.getName()); + } + ); -export default GroupsDemo; + return () => { + createdSub?.unsubscribe(); + deletedSub?.unsubscribe(); + memberAddedSub?.unsubscribe(); + leftSub?.unsubscribe(); + }; + }, []); +} ``` - +### SDK Events (Real-Time, Automatic) - +The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required. -*** +| SDK Listener | Internal behavior | +| --- | --- | +| `onGroupMemberJoined` | Updates member count, sets `hasJoined` if current user joined | +| `onGroupMemberLeft` | Updates member count, sets `hasJoined(false)` if current user left | +| `onMemberAddedToGroup` | Updates member count, adds group to list if current user was added | +| `onGroupMemberKicked` | Updates member count, sets `hasJoined(false)` if current user was kicked | +| `onGroupMemberBanned` | Removes group if current user was banned, otherwise updates member count | +| `onGroupMemberScopeChanged` | Updates scope if current user's scope changed, updates member count | -### Events + +In React 18 StrictMode, `useEffect` runs twice on mount in development. The component handles listener cleanup internally, but any additional listeners added alongside the component need cleanup in the `useEffect` return function to avoid duplicate event handling. + -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +--- -To handle events supported by Groups you have to add corresponding listeners by using `CometChatGroupEvents` +## Custom View Slots -The `Groups` component does not produce any events directly. +Each slot replaces a section of the default UI. Slots that accept a group parameter receive the `CometChat.Group` object for that row. -*** +| Slot | Signature | Replaces | +| --- | --- | --- | +| `itemView` | `(group: CometChat.Group) => JSX.Element` | Entire list item row | +| `leadingView` | `(group: CometChat.Group) => JSX.Element` | Avatar / left section | +| `titleView` | `(group: CometChat.Group) => JSX.Element` | Name / title text | +| `subtitleView` | `(group: CometChat.Group) => JSX.Element` | Member count subtitle | +| `trailingView` | `(group: CometChat.Group) => JSX.Element` | Right section | +| `headerView` | `JSX.Element` | Entire header bar | +| `loadingView` | `JSX.Element` | Loading spinner | +| `emptyView` | `JSX.Element` | Empty state | +| `errorView` | `JSX.Element` | Error state | +| `options` | `(group: CometChat.Group) => CometChatOption[]` | Context menu / hover actions | -## Customization +### itemView -To fit your app's design requirements, you can customize the appearance of the Groups component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. +Replace the entire list item row. -### Style +Default: -Using CSS you can customize the look and feel of the component in your app like the color, size, shape, and fonts. + + + -**Example** +Customized: - + -```ts -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - return ; -}; - -export default GroupsDemo; -``` - - - - -```js +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; -const GroupsDemo = () => { - return ; -}; +function CustomItemViewGroups() { + const getItemView = (group: CometChat.Group) => { + return ( +
+
+
{group.getName()}
+
JOIN
+
+
+ {group.getMembersCount()} Members • {group.getDescription()} +
+
+ ); + }; -export default GroupsDemo; + return ; +} ``` -
- - -```css -.cometchat .cometchat-groups .cometchat-list__header-title { - background-color: #edeafa; - color: #6852d6; - border-width: 0px 1px 1px 0px; - border-style: solid; - border-color: #6852d6; - overflow: hidden; - text-overflow: ellipsis; - font-family: "Times New Roman"; - font-size: 24px; - font-style: normal; - font-weight: 700; - line-height: 28.8px; + +```css lines +.group-list-item { + display: flex; + flex-direction: column; + text-align: left; + min-width: 240px; + padding: 8px 16px; + gap: 4px; + flex: 1 0 0; + border-right: 1px solid #f5f5f5; + background: #fff; } -.cometchat .cometchat-groups .cometchat-search-bar__input::placeholder { - font-family: "Times New Roman"; - font-size: 16px; - font-style: normal; - font-weight: 400; - line-height: 19.2px; +.group-list-item:hover { + background-color: #f5f5f5; } -.cometchat .cometchat-groups .cometchat-list-item { - background: #fff; - border-right: 1px solid #f5f5f5; +.group-list-item__title-wrapper { + display: flex; + justify-content: space-between; + align-items: center; + align-self: stretch; } -.cometchat .cometchat-groups__list-item .cometchat-avatar { - background-color: #aa9ee8; - border-radius: 6.67px; +.group-list-item__title { + overflow: hidden; + color: #141414; + text-overflow: ellipsis; + font: 500 16px Roboto; } -.cometchat .cometchat-groups .cometchat-list-item__body-title { +.group-list-item__tail { + display: flex; + padding: 4px 12px; + justify-content: center; + align-items: center; + border-radius: 1000px; + background: #edeafa; overflow: hidden; - color: #141414; + color: #6852d6; text-overflow: ellipsis; - font-family: "Times New Roman"; - font-size: 16px; - font-style: normal; - font-weight: 400; - line-height: 19.2px; + font: 700 12px Roboto; } -.cometchat .cometchat-groups .cometchat-groups__subtitle { +.group-list-item__subtitle { overflow: hidden; color: #727272; text-overflow: ellipsis; white-space: nowrap; - font-family: "Times New Roman"; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 16.8px; + font: 400 14px Roboto; } ``` - -
-*** +### titleView -### Functionality +Replace the name / title text. Group type badge inline example. -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. + + + -```ts -import { CometChatGroups, TitleAlignment } from "@cometchat/chat-uikit-react"; -import React from "react"; +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatGroups } from "@cometchat/chat-uikit-react"; -const GroupsDemo = () => { - return ( - - ); -}; +function GroupTypeTitleGroups() { + const getTitleView = (group: CometChat.Group) => { + return ( +
+ {group.getName()} + {group.getType()} +
+ ); + }; -export default GroupsDemo; + return ; +} ``` -
+ +```css lines +.groups__title-view { + display: flex; + align-items: center; + gap: 4px; + align-self: stretch; +} - -```js -import { CometChatGroups, TitleAlignment } from "@cometchat/chat-uikit-react"; -import React from "react"; +.groups__title-view-name { + overflow: hidden; + color: #141414; + text-overflow: ellipsis; + font: 500 16px Roboto; +} -const GroupsDemo = () => { - return ( - - ); -}; +.groups__title-view-type { + color: #fff; + font: 600 8px Roboto; + display: flex; + height: 15px; + padding: 1px 3px; + justify-content: center; + align-items: center; + gap: 4px; + border-radius: 7px; + background: #09c26f; +} -export default GroupsDemo; +.groups__title-view-public .groups__title-view-type { + background: #0b7bea; +} ``` - -
-Below is a list of customizations along with corresponding code snippets: - -| Property | Description | Code | -| ------------------- | ------------------------------------------------------------------- | ---------------------------------------- | -| **Hide Search** | Hides the default search bar. | `hideSearch={true}` | -| **Hide Error** | Hides the default and custom error view passed in `errorView` prop. | `hideError={true}` | -| **Hide Group Type** | Hides the group type icon. | `hideGroupType={true}` | -| **Active Group** | The group to highlight in the list. | `activeGroup={chatGroup}` | -| **Selection Mode** | Selection mode to use for the default trailing view. | `selectionMode={SelectionMode.multiple}` | -| **Show Scrollbar** | Controls the visibility of the scrollbar in the list. | `showScrollbar={true}` | -| **Loading View** | A custom view to display during the loading state. | `loadingView={<>Custom Loading View}` | -| **Empty View** | Custom view for the empty state of the component. | `emptyView={<>Custom Empty View}` | -| **Error View** | A custom view to display when an error occurs. | `errorView={<>Custom Error View}` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. +### subtitleView -*** +Replace the member count subtitle text. -#### ItemView - -A custom view to render for each group in the fetched list. - -Shown below is the default chat interface. +Default: - + -The customized chat interface is displayed below. +Customized: - + -Use the following code to achieve the customization shown above. - -```ts +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; -const GroupsDemo = () => { - const getItemView = (group: CometChat.Group) => { +function SubtitleGroups() { + const getSubtitleView = (group: CometChat.Group) => { return ( -
-
-
{group.getName()}
-
JOIN
-
-
- {group.getMembersCount()} Members • {group.getDescription()} -
+
+ {group.getMembersCount()} Members • {group.getDescription()}
); }; - return ; -}; - -export default GroupsDemo; + return ; +} ``` - + +```css lines +.cometchat .cometchat-groups .group-subtitle { + overflow: hidden; + color: #727272; + text-overflow: ellipsis; + white-space: nowrap; + font: 400 14px Roboto; +} +``` + + - -```js -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; +### leadingView -const GroupsDemo = () => { - const getItemView = (group: CometChat.Group) => { +Replace the avatar / left section. Joined status badge example. + + + + + + + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatGroups, CometChatAvatar } from "@cometchat/chat-uikit-react"; + +function LeadingViewGroups() { + const getLeadingView = (group: CometChat.Group) => { return ( -
-
-
{group.getName()}
-
JOIN
-
-
- {group.getMembersCount()} Members • {group.getDescription()} -
-
+ <> + {group.getHasJoined() ? ( +
+ + Joined +
+ ) : ( +
+ + Join +
+ )} + ); }; - return ; -}; - -export default GroupsDemo; + return ; +} ``` -
+ +```css lines +.cometchat-groups .cometchat-list-item .groups__leading-view .cometchat-avatar__image, +.cometchat-groups .cometchat-list-item .groups__leading-view .cometchat-avatar { + border-radius: 8px; + height: 48px; + width: 48px; +} - -```css -.group-list-item { - display: flex; - flex-direction: column; - text-align: left; +.groups__leading-view-info { display: flex; - min-width: 240px; - padding: 8px 16px; - gap: 4px; - flex: 1 0 0; - border-right: 1px solid #f5f5f5; - background: #fff; + width: 48px; + height: 15px; + padding: 1px 3px; + justify-content: center; + align-items: center; + color: #fff; + font: 600 8px/9.6px Roboto; + background: #ffab00; + position: absolute; + bottom: -2px; } -.group-list-item:hover { - background-color: #f5f5f5; +.groups__leading-view-joined .groups__leading-view-info { + background: #09c26f; } -.group-list-item__title-wrapper { - display: flex; - justify-content: space-between; - align-items: center; - align-self: stretch; +.groups__leading-view { + position: relative; } +``` + +
-.group-list-item__title { - overflow: hidden; - color: #141414; - text-overflow: ellipsis; - font-family: Roboto; - font-size: var(--Size-H4, 16px); - font-style: normal; - font-weight: 500; - line-height: 19.2px; -} +### trailingView -.group-list-item__tail { +Replace the right section. Join status button example. + + + + + + + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatGroups } from "@cometchat/chat-uikit-react"; + +function TrailingViewGroups() { + const getTrailingView = (group: CometChat.Group) => { + return ( +
+ {group.getHasJoined() ? "JOINED" : "+ JOIN"} +
+ ); + }; + + return ; +} +``` +
+ +```css lines +.groups__trailing-view { display: flex; padding: 4px 12px; justify-content: center; align-items: center; - gap: 20px; border-radius: 1000px; background: #edeafa; overflow: hidden; color: #6852d6; text-overflow: ellipsis; - font-family: Roboto; - font-size: 12px; - font-style: normal; - font-weight: 700; - line-height: 14.4px; + font: 700 12px Roboto; } -.group-list-item__subtitle { - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - white-space: nowrap; - font-family: Roboto; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 16.8px; +.cometchat-groups .cometchat-list-item__trailing-view { + width: fit-content; + height: fit-content; } ``` - -
-*** +### headerView -#### TitleView - -The customized chat interface is displayed below. +Replace the entire header bar. - + -Use the following code to achieve the customization shown above. - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; +```tsx lines +import { + CometChatButton, + CometChatGroups, + getLocalizedString, +} from "@cometchat/chat-uikit-react"; -// Custom title view component -const customTitleView = (group: CometChat.Group) => { - return
- {group.getName()} - {group.getType()} -
; +function CustomHeaderGroups() { + return ( + +
+ {getLocalizedString("GROUPS")} +
+ { /* handle click */ }} /> +
+ } + /> + ); } - -; ``` -
- - -```css -.groups__title-view{ -display: flex; -align-items: center; -gap: 4px; -align-self: stretch; -} -.groups__title-view-name{ -overflow: hidden; -color: #141414; -text-overflow: ellipsis; -font:500 16px Roboto + +```css lines +.groups__header { + display: flex; + width: 100%; + padding: 8px 16px; + align-items: center; + justify-content: space-between; + gap: 12px; + border-radius: 10px; + border: 1px solid #e8e8e8; + background: #edeafa; } -.groups__title-view-type{ -color: #FFF; -font: 600 8px Roboto; -display: flex; -height: 15px; -padding: 1px 3px; -justify-content: center; -align-items: center; -gap: 4px; -border-radius: 7px; -background: #09C26F; + +.groups__header__title { + overflow: hidden; + color: #141414; + text-overflow: ellipsis; + font: 700 24px Roboto; } -.groups__title-view-public .groups__title-view-type{ -background: #0B7BEA; + +.groups__header .cometchat-button .cometchat-button__icon { + background: #141414; } -.groups__title-view-type img{ -background: #fff; -border-radius: 4px; -height: 12px; -width: 12px; + +.groups__header .cometchat-button { + width: 24px; + border: none; + background: transparent; + border-radius: 0; } ``` - -
-*** - -#### SubtitleView - -Custom subtitle view to be rendered for each group in the fetched list. - -Shown below is the default chat interface. - - - - +### options -The customized chat interface is displayed below. +Replace the context menu / hover actions on each group item. - + -Use the following code to achieve the customization shown above. - -```ts +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - const getSubtitleView = (group: CometChat.Group): JSX.Element => { - if (!(group instanceof CometChat.Group)) { - return <>; - } - - return ( -
- {group.getMembersCount()} Members • {group.getDescription()} -
- ); - }; +import { + CometChatOption, + CometChatGroups, +} from "@cometchat/chat-uikit-react"; - return ; -}; +function CustomOptionsGroups() { + const getOptions = (group: CometChat.Group) => [ + new CometChatOption({ + title: "Delete", + id: "delete", + onClick: () => { /* delete logic */ }, + }), + ]; -export default GroupsDemo; + return ; +} ``` +
+ +```css lines +.cometchat .cometchat-groups .cometchat-menu-list__menu { + background: none; +} +.cometchat .cometchat-groups .cometchat-menu-list__main-menu-item-icon { + background: #f44649; +} +``` +
- -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; +```ts lines +// CometChatOption interface +interface CometChatOption { + id?: string; // Unique identifier + title?: string; // Display text + iconURL?: string; // Icon asset URL + onClick?: () => void; // Click handler +} +``` -const GroupsDemo = () => { - const getSubtitleView = (group) => { - if (!(group instanceof CometChat.Group)) { - return <>; - } +--- - return ( -
- {group.getMembersCount()} Members • {group.getDescription()} -
- ); - }; +## Common Patterns - return ; -}; +### Custom empty state with CTA -export default GroupsDemo; +```tsx lines +import { CometChatGroups } from "@cometchat/chat-uikit-react"; + +function EmptyStateGroups() { + return ( + +

No groups available

+ +
+ } + /> + ); +} ``` -
+### Hide all chrome — minimal list - -```css -.cometchat .cometchat-groups .group-subtitle { - overflow: hidden; - color: #727272; - text-overflow: ellipsis; - white-space: nowrap; - font-size: 14px; - font-style: normal; - font-weight: 400; - line-height: 120%; +```tsx lines +import { CometChatGroups } from "@cometchat/chat-uikit-react"; + +function MinimalGroups() { + return ( + + ); } ``` - +### Joined groups only -
+```tsx lines +import { CometChatGroups } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -*** +function JoinedGroups() { + return ( + + ); +} +``` -#### LeadingView +--- -The customized chat interface is displayed below. +## CSS Architecture - - - +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: -Use the following code to achieve the customization shown above. +1. Global tokens (e.g., `--cometchat-primary-color`, `--cometchat-background-color-01`) are set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-groups`) consumes these tokens via `var()` with fallback values. +3. Overrides target `.cometchat-groups` descendant selectors in a global stylesheet. - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatGroups,CometChatAvatar } from "@cometchat/chat-uikit-react"; - -// Custom leading view component - const customLeadingView = (group: CometChat.Group) => { - return <> - {group.getHasJoined() ?
- - {/* Icon here */} - Joined - - -
:
- - {/* Icon here */} - Join - - -
}; - } +To scope overrides to a single instance when multiple `CometChatGroups` exist on the same page, wrap the component in a container and scope selectors: -; +```css lines +.sidebar-left .cometchat-groups .cometchat-avatar { + border-radius: 8px; +} ``` -
+### Key Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-groups` | +| Header title | `.cometchat-groups .cometchat-list__header-title` | +| Search bar input | `.cometchat-groups .cometchat-search-bar__input` | +| List item | `.cometchat-groups .cometchat-list-item` | +| Body title | `.cometchat-groups .cometchat-list-item__body-title` | +| Avatar | `.cometchat-groups__list-item .cometchat-avatar` | +| Subtitle | `.cometchat-groups__subtitle` | +| Active item | `.cometchat-groups__list-item-active .cometchat-list-item` | +| Password group icon | `.cometchat-groups__list-item-password .cometchat-list-item__status` | +| Private group icon | `.cometchat-groups__list-item-private .cometchat-list-item__status` | +| Empty state | `.cometchat-groups__empty-state-view` | +| Error state | `.cometchat-groups__error-state-view` | +| Shimmer loading | `.cometchat-groups__shimmer` | + +### Example: Brand-themed groups - -```css + + + -.cometchat-groups .cometchat-list-item .groups__leading-view .cometchat-avatar__image, .cometchat-groups .cometchat-list-item .groups__leading-view .cometchat-avatar{ - border-radius: 8px; - height: 48px ; - width: 48px ; +```css lines +.cometchat-groups .cometchat-list__header-title { + background-color: #edeafa; + color: #6852d6; + border-width: 0px 1px 1px 0px; + border-style: solid; + border-color: #6852d6; + font-family: "Times New Roman"; + font-size: 24px; + font-weight: 700; } -.groups__leading-view-info{ - display: flex; - width: 48px; - height: 15px; - padding: 1px 3px; - justify-content: center; - align-items: center; - color:#FFF; - font:600 8px/9.6px Roboto; - background:#FFAB00; - position:absolute; - bottom:-2px; +.cometchat-groups__list-item .cometchat-avatar { + background-color: #aa9ee8; + border-radius: 6.67px; } -.groups__leading-view-joined .groups__leading-view-info{ - background:#09C26F; + +.cometchat-groups .cometchat-list-item__body-title { + font-family: "Times New Roman"; + font-size: 16px; + font-weight: 400; } -.groups__leading-view{ - position: relative; + +.cometchat-groups .cometchat-groups__subtitle { + font-family: "Times New Roman"; + font-size: 14px; + font-weight: 400; } ``` - +### Customization Matrix -
+| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Component props | `on` callbacks | `onItemClick={(g) => setActive(g)}` | +| Filter which groups appear | Component props | `groupsRequestBuilder` | `groupsRequestBuilder={new CometChat.GroupsRequestBuilder().joinedOnly(true)}` | +| Toggle visibility of UI elements | Component props | `hide` boolean props | `hideGroupType={true}` | +| Replace a section of the list item | Component props | `View` render props | `itemView={(group) =>
...
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-groups` class | `.cometchat-groups .cometchat-avatar { border-radius: 8px; }` | -*** +--- -#### TrailingView +## Accessibility -The customized chat interface is displayed below. +The component renders a scrollable list of interactive items. Each group row is keyboard-focusable and activates on Enter/Space. The context menu (options) is accessible via keyboard. Avatar images include the group name as alt text. Group type indicators (public/private/password) use CSS mask images — add `aria-label` attributes via `itemView` if screen reader descriptions are needed for these visual indicators. - - - +--- -Use the following code to achieve the customization shown above. +--- - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatGroups, -} from "@cometchat/chat-uikit-react"; +## Props -// Custom trailing view component -const customTrailingButtonView = (group:CometChat.Group) => { -return
- {group.getHasJoined() ? "JOINED" : "+ JOIN"} -
-} +All props are optional unless noted otherwise. -; -``` +--- -
+### activeGroup - -```css -.groups__trailing-view{ -display: flex; -padding: 4px 12px; -justify-content: center; -align-items: center; -border-radius: 1000px; -background: #EDEAFA; -overflow: hidden; -color: #6852D6; -text-overflow: ellipsis; -font:700 12px Roboto; -} -.cometchat-groups .cometchat-list-item__trailing-view{ -width: fit-content; -height: fit-content; -} -``` +Highlights the specified group in the list. - +| | | +| --- | --- | +| Type | `CometChat.Group` | +| Default | `undefined` | -
+Must be a reference-equal object from the SDK; a manually constructed object will not match. -*** +--- -#### Header View +### emptyView -A custom component to render in the top-right corner of the groups list. +Custom component displayed when there are no groups. -The customized chat interface is displayed below. +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in empty state | - - - +--- -Use the following code to achieve the customization shown above. +### errorView - - -```ts -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; +Custom component displayed when an error occurs. -const GroupsDemo = () => { - const getHeaderView = () => { - return
; - }; +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in error state | - return ; -}; +Hidden when `hideError={true}`. -export default GroupsDemo; -``` +--- - +### groupsRequestBuilder - -```js -import { CometChatGroups } from "@cometchat/chat-uikit-react"; -import React from "react"; +Controls which groups load and in what order. -const GroupsDemo = () => { - const getHeaderView = () => { - return
; - }; +| | | +| --- | --- | +| Type | `CometChat.GroupsRequestBuilder` | +| Default | SDK default (30 per page) | - return ; -}; +Pass the builder instance, not the result of `.build()`. -export default GroupsDemo; -``` +--- - +### headerView - -```css -.group-header-view { - height: 24px; - width: 24px; - display: flex; - align-items: center; - justify-content: center; - border: none; - align-self: center; - background: #6852d6; - flex-shrink: 0; - -webkit-mask: url("../assets/create-group.svg") center center no-repeat; - mask: url("../assets/create-group.svg") center center no-repeat; - -webkit-mask-size: contain; - mask-size: contain; -} -``` +Custom component rendered as the entire header bar. - +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in header with title | - +--- -*** +### hideError -#### Options +Hides the default and custom error views. -You can set the Custom options to the Groups component. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -The customized chat interface is displayed below. +Also suppresses `errorView` if set. - - - +--- -Use the following code to achieve the customization shown above. +### hideGroupType - - -```ts -import { CometChatGroups, CometChatOption } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - const getOptions = (group: CometChat.Group): CometChatOption[] => { - return [ - new CometChatOption({ - id: "delete", - title: "delete", - onClick: () => { - console.log("Custom option clicked for group:", group); - }, - }), - ]; - }; +Hides the group type icon (public/private/password). - return ; -}; +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -export default GroupsDemo; -``` +--- - +### hideSearch - -```js -import { CometChatGroups, CometChatOption } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const GroupsDemo = () => { - const getOptions = (group: CometChat.Group): CometChatOption[] => { - return [ - new CometChatOption({ - id: "delete", - title: "delete", - onClick: () => { - console.log("Custom option clicked for group:", group); - }, - }), - ]; - }; +Hides the default search bar. - return ; -}; +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -export default GroupsDemo; -``` +--- - +### itemView - -```css -.cometchat .cometchat-groups .cometchat-menu-list__menu { - background: none; +Custom renderer for the entire list item row. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => JSX.Element` | +| Default | Built-in list item | + +--- + +### leadingView + +Custom renderer for the avatar / left section. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => JSX.Element` | +| Default | Built-in avatar | + +--- + +### loadingView + +Custom component displayed during the loading state. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in shimmer | + +--- + +### onError + +Callback fired when the component encounters an error. + +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | + +--- + +### onItemClick + +Callback fired when a group row is clicked. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => void` | +| Default | `undefined` | + +--- + +### onSelect + +Callback fired when a group is selected/deselected. Requires `selectionMode` to be set. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group, selected: boolean) => void` | +| Default | `undefined` | + +--- + +### options + +Custom context menu / hover actions for each group item. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => CometChatOption[]` | +| Default | `undefined` | + +```ts lines +class CometChatOption { + id?: string; + title?: string; + iconURL?: string; + onClick?: () => void; } -.cometchat .cometchat-groups .cometchat-menu-list__main-menu-item-icon { - height: 24px; - width: 24px; - display: flex; - align-items: center; - justify-content: center; - border: none; - align-self: center; - background: #f44649; - flex-shrink: 0; - -webkit-mask: url("../assets/delete.svg") center center no-repeat; - mask: url("../assets/delete.svg") center center no-repeat; - -webkit-mask-size: contain; - mask-size: contain; +``` + +--- + +### searchRequestBuilder + +Controls filtering when the search bar is active. + +| | | +| --- | --- | +| Type | `CometChat.GroupsRequestBuilder` | +| Default | `undefined` | + +--- + +### selectionMode + +Enables single or multi-select checkboxes on list items. + +| | | +| --- | --- | +| Type | `SelectionMode` | +| Default | `SelectionMode.none` | + +```ts lines +enum SelectionMode { + single, // 0 + multiple, // 1 + none, // 2 } ``` - +Must pair with `onSelect` to capture selections. - +--- + +### showScrollbar + +Shows the scrollbar in the group list. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### subtitleView + +Custom renderer for the member count subtitle text. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => JSX.Element` | +| Default | Built-in subtitle | + +--- + +### titleView + +Custom renderer for the name / title text. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => JSX.Element` | +| Default | Built-in title | + +--- + +### trailingView + +Custom renderer for the right section. + +| | | +| --- | --- | +| Type | `(group: CometChat.Group) => JSX.Element` | +| Default | Built-in trailing view | + +--- + +## Events + +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatGroupEvents.ccGroupCreated` | `CometChat.Group` | New group created | +| `CometChatGroupEvents.ccGroupDeleted` | `CometChat.Group` | Group deleted | +| `CometChatGroupEvents.ccGroupMemberJoined` | `IGroupMemberJoined` | User joins a group | +| `CometChatGroupEvents.ccGroupLeft` | `IGroupLeft` | User leaves a group | +| `CometChatGroupEvents.ccGroupMemberAdded` | `IGroupMemberAdded` | Members added to a group | +| `CometChatGroupEvents.ccGroupMemberScopeChanged` | `IGroupMemberScopeChanged` | Member scope changed | +| `CometChatGroupEvents.ccGroupMemberKicked` | `IGroupMemberKickedBanned` | Member kicked | +| `CometChatGroupEvents.ccGroupMemberBanned` | `IGroupMemberKickedBanned` | Member banned | +| `CometChatGroupEvents.ccGroupMemberUnbanned` | `IGroupMemberUnBanned` | Member unbanned | +| `CometChatGroupEvents.ccOwnershipChanged` | `IOwnershipChanged` | Ownership transferred | + +All events are RxJS `Subject` instances. Subscribe with `.subscribe()`, unsubscribe with the returned subscription's `.unsubscribe()`. + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-groups` | +| Header title | `.cometchat-groups .cometchat-list__header-title` | +| Search bar input | `.cometchat-groups .cometchat-search-bar__input` | +| List item | `.cometchat-groups .cometchat-list-item` | +| Body title | `.cometchat-groups .cometchat-list-item__body-title` | +| Avatar | `.cometchat-groups__list-item .cometchat-avatar` | +| Leading view | `.cometchat-groups__list-item .cometchat-list-item__leading-view` | +| Subtitle | `.cometchat-groups__subtitle` | +| Active item | `.cometchat-groups__list-item-active .cometchat-list-item` | +| Password group icon | `.cometchat-groups__list-item-password .cometchat-list-item__status` | +| Password group status icon | `.cometchat-groups__list-item-password .cometchat-list-item__status-icon` | +| Private group icon | `.cometchat-groups__list-item-private .cometchat-list-item__status` | +| Private group status icon | `.cometchat-groups__list-item-private .cometchat-list-item__status-icon` | +| Empty state | `.cometchat-groups__empty-state-view` | +| Empty state title | `.cometchat-groups__empty-state-view-body-title` | +| Empty state description | `.cometchat-groups__empty-state-view-body-description` | +| Error state | `.cometchat-groups__error-state-view` | +| Error state title | `.cometchat-groups__error-state-view-body-title` | +| Error state description | `.cometchat-groups__error-state-view-body-description` | +| Shimmer loading | `.cometchat-groups__shimmer` | +| Shimmer item | `.cometchat-groups__shimmer-item` | +| Shimmer avatar | `.cometchat-groups__shimmer-item-avatar` | +| Shimmer title | `.cometchat-groups__shimmer-item-body-title` | +| Shimmer subtitle | `.cometchat-groups__shimmer-item-body-subtitle` | diff --git a/ui-kit/react/guide-block-unblock-user.mdx b/ui-kit/react/guide-block-unblock-user.mdx index f758f45b3..952ee092c 100644 --- a/ui-kit/react/guide-block-unblock-user.mdx +++ b/ui-kit/react/guide-block-unblock-user.mdx @@ -1,51 +1,50 @@ --- title: "Block/Unblock Users" sidebarTitle: "Block/Unblock Users" +description: "Implement block and unblock user functionality in CometChat React UI Kit with composer state management." --- -Implement user blocking functionality to prevent unwanted communication in your React chat app. + -## Overview +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key components | `CometChatMessages` — uses `CometChat.blockUsers()` / `CometChat.unblockUsers()` SDK methods | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Events | `CometChatUserEvents.ccUserBlocked`, `CometChatUserEvents.ccUserUnblocked` | +| UI helpers | `CometChatConfirmDialog`, `CometChatToast` | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -The Block Users feature allows users to prevent specific users from sending them messages, effectively cutting off communication from unwanted contacts. + -- Block Users feature allows users to prevent specific users from sending them messages. -- Provides privacy control, prevents harassment, and allows users to manage their communication preferences. -- Your app will allow users to block/unblock other users, hide message composers for blocked users, and provide appropriate UI feedback for blocked states. +Block/Unblock lets users prevent specific users from sending them messages. When blocked, the message composer is hidden and replaced with an unblock prompt. ---- - -## Prerequisites - -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- Project setup with initialized CometChat credentials (App ID, Auth Key, Region) -- TypeScript support (recommended) -- User authentication and chat functionality already implemented +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework. --- ## Components -| Component / Class | Role | -|:-----------------------------------|:-----| -| **CometChat.blockUsers()** | SDK method to block specific users | -| **CometChat.unblockUsers()** | SDK method to unblock previously blocked users | -| **CometChatUserEvents.ccUserBlocked** | Event listener for when a user is blocked | -| **CometChatUserEvents.ccUserUnblocked** | Event listener for when a user is unblocked | -| **CometChatConfirmDialog** | Confirmation dialog for block/unblock actions | -| **CometChatToast** | Toast notifications for action feedback | +| Component / Class | Role | +|:---|:---| +| `CometChat.blockUsers()` | SDK method to block specific users | +| `CometChat.unblockUsers()` | SDK method to unblock previously blocked users | +| `CometChatUserEvents.ccUserBlocked` | Event fired when a user is blocked | +| `CometChatUserEvents.ccUserUnblocked` | Event fired when a user is unblocked | +| `CometChatConfirmDialog` | Confirmation dialog for block/unblock actions | --- ## Integration Steps -### 1. Block User Function Implementation +### 1. Block User + +Call `CometChat.blockUsers()` with the target UID. On success, update the local user object with `setBlockedByMe(true)` and emit `ccUserBlocked` so all subscribed components (like the composer) react to the change. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const onBlockUserClicked: () => Promise = () => { let UID = user.getUid(); return new Promise(async (resolve, reject) => { @@ -67,11 +66,13 @@ const onBlockUserClicked: () => Promise = () => { --- -### 2. Unblock User Function Implementation +### 2. Unblock User + +Call `CometChat.unblockUsers()` with the target UID. On success, reset the action items back to "Block" (instead of "Unblock"), update the local user object, and emit `ccUserUnblocked` to restore the composer. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const onUnblockUserClicked = () => { let UID = user.getUid(); CometChat.unblockUsers([UID]).then( @@ -96,11 +97,13 @@ const onUnblockUserClicked = () => { --- -### 3. Block User Confirmation Dialog +### 3. Confirmation Dialog + +Show a confirmation dialog before blocking. This prevents accidental blocks. The dialog uses `CometChatConfirmDialog` with localized title, message, and button text. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const getBlockUserConfirmationDialogView = () => { return <>
@@ -119,11 +122,13 @@ const getBlockUserConfirmationDialogView = () => { --- -### 4. Message Composer Blocked State +### 4. Composer Blocked State _File: [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx)_ -```tsx +When a user is blocked, the composer is replaced with an unblock prompt: + +```tsx lines {showComposerState ? (
{ - if (messageUser?.getBlockedByMe()) { - setShowComposer(false); - } - const unsubscribeFromEvents = subscribeToEvents(); - return () => { - unsubscribeFromEvents(); - }; -}, [subscribeToEvents, selectedItem]); -``` - -- **Send Block/Unblock Action Handler** +### 5. Event Listeners _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx -const onUserActionClick = (item: { name: string; icon: string; }) => { - if (item.name == getLocalizedString("user_details_block")) { - setShowBlockUserDialog(true); - } else if (item.name == getLocalizedString("user_details_unblock")) { - onUnblockUserClicked(); - } -} -``` +Subscribe to block/unblock events to update the UI in real time: -- **Live Updates / Observers** - -_File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ - -```tsx +```tsx lines const ccUserBlocked = CometChatUserEvents.ccUserBlocked.subscribe(user => { if (user.getBlockedByMe()) { setShowComposer(false); @@ -214,76 +179,34 @@ const ccUserUnblocked = CometChatUserEvents.ccUserUnblocked.subscribe(user => { --- -## Customization Options - -- Styling overrides for blocked states and confirmation dialogs -- Custom block/unblock confirmation messages -- Toast notification customization -- Custom action items for different user states -- Custom blocked state UI - ---- - -## Filtering / Edge Cases +## Feature Matrix -- Detect when blocking status changes mid-chat -- Prevent duplicate block actions -- Handle blocked users in search results -- Respect group chat rules when blocking -- Keep old messages visible from blocked users +| Feature | Component / Method | File | +|:---|:---|:---| +| Block user | `CometChat.blockUsers([UID])` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Unblock user | `CometChat.unblockUsers([UID])` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Check blocked status | `user.getBlockedByMe()` | [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx) | +| Block confirmation | `CometChatConfirmDialog` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Blocked composer state | `message-composer-blocked` | [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx) | +| Block events | `ccUserBlocked.subscribe()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Unblock events | `ccUserUnblocked.subscribe()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Update user state | `user.setBlockedByMe(boolean)` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | --- -## Error Handling - -```tsx -CometChat.blockUsers([UID]).then( - list => { - user.setBlockedByMe(true); - CometChatUserEvents.ccUserBlocked.next(user); - toastTextRef.current = getLocalizedString("blocked_successfully"); - setShowToast(true); - }, error => { - console.log("Blocking user fails with error", error); - } -) -``` - -- Handle block/unblock network errors -- Provide retry options -- Maintain UI consistency on errors - ---- - -## Context-Specific Notes - -- Blocking applies only to private chats, not groups -- Blocked users may still appear in lists but with indicators -- Existing messages remain visible -- Updates are reflected in real-time - ---- - -## Summary / Feature Matrix - -| Feature | Component / Method | File Reference | -|:-----------------------|:------------------------------------|:---------------| -| Block user | `CometChat.blockUsers([UID])` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Unblock user | `CometChat.unblockUsers([UID])` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Check blocked status | `user.getBlockedByMe()` | [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx) | -| Block confirmation dlg | `CometChatConfirmDialog` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Blocked composer state | `message-composer-blocked` | [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx) | -| Block user events | `ccUserBlocked.subscribe()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Unblock user events | `ccUserUnblocked.subscribe()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Update user state | `user.setBlockedByMe(boolean)` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | - ---- - -## Next Steps & Further Reading - -- [CometChat React UI Kit Documentation](https://www.cometchat.com/docs/ui-kit/react/overview) -- [Sample App Repository](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) -- User Management Features -- Advanced Customization Guide -- Event Handling Documentation - +## Next Steps + + + + Display and manage user lists. + + + Customize the message input component. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + \ No newline at end of file diff --git a/ui-kit/react/guide-call-log-details.mdx b/ui-kit/react/guide-call-log-details.mdx index a029b601e..aa839f150 100644 --- a/ui-kit/react/guide-call-log-details.mdx +++ b/ui-kit/react/guide-call-log-details.mdx @@ -1,54 +1,51 @@ --- title: "Call Log Details" sidebarTitle: "Call Log Details" +description: "Build a detailed call insights screen with metadata, participants, and recordings in CometChat React UI Kit." --- -Display comprehensive call information and history when users select calls from the calls tab in your React chat app. + -## Overview +| Field | Value | +| --- | --- | +| Packages | `@cometchat/chat-uikit-react` + `@cometchat/calls-sdk-javascript` | +| Key components | `CometChatCallDetails`, `CometChatCallDetailsInfo`, `CometChatCallDetailsParticipants`, `CometChatCallDetailsRecording` | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` + Calls SDK installed | +| Purpose | Detailed call insights screen with metadata, participants, and recordings | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -The Calls Log Details feature provides users with detailed information about specific calls, including call status, participants, duration, recordings, and call history. + -- Provides detailed information about specific calls when selected from the calls tab. -- Enables users to review call details, understand outcomes, view participants, and access recordings for reference. -- Users can view call details with tabbed navigation showing participants, recordings, and call history. +Call Log Details shows call metadata, participants, duration, recordings, and history when a user selects a call from the Calls tab. ---- - -## Prerequisites - -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- CometChat Calls SDK JavaScript v4.0.11+ -- Project setup with initialized CometChat credentials (App ID, Auth Key, Region) -- TypeScript support (recommended) -- Call functionality implemented -- Calls tab navigation configured +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework and install `@cometchat/calls-sdk-javascript`. --- ## Components -| Component / Class | Role | -|:--------------------------------|:-----| -| **CometChatCallDetails** | Main container for call details display | -| **CometChatCallDetailsInfo** | Shows call status, duration, and info | -| **CometChatCallDetailsParticipants** | Displays call participants | -| **CometChatCallDetailsRecording** | Shows call recordings if available | -| **CometChatCallDetailsHistory** | Displays call history | -| **CometChatCallLogs** | Calls list component in the calls tab | +| Component / Class | Role | +|:---|:---| +| `CometChatCallDetails` | Main container for call details display | +| `CometChatCallDetailsInfo` | Shows call status, duration, and info | +| `CometChatCallDetailsParticipants` | Displays call participants | +| `CometChatCallDetailsRecording` | Shows call recordings if available | +| `CometChatCallDetailsHistory` | Displays call history | +| `CometChatCallLogs` | Calls list component in the calls tab | --- ## Integration Steps -### 1. Calls Tab Integration Setup +### 1. Calls Tab Integration + +Render `CometChatCallLogs` when the "Calls" tab is active. When a call is clicked, dispatch it to the app state so the details panel can display it. _File: [CometChatSelector.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatSelector/CometChatSelector.tsx)_ -```tsx -{activeTab == "calls" ? ( +```tsx lines +{activeTab === "calls" ? ( { @@ -60,11 +57,13 @@ _File: [CometChatSelector.tsx](https://github.com/cometchat/cometchat-uikit-reac --- -### 2. Call Details Component Integration +### 2. Call Details Component + +Guard-check that the selected item is a `CometChat.Call` instance, then render `CometChatCallDetails`. The `onBack` callback clears the selection and returns to the call list. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const CallDetailsView = () => { if (!selectedItem || !(selectedItem instanceof CometChat.Call)) return null; @@ -82,11 +81,13 @@ const CallDetailsView = () => { --- -### 3. Call Details Main Component Implementation +### 3. Call Details Implementation + +The main details screen. It shows the caller's avatar and name at the top, call info (status, duration) below, and three tabs: Participants, Recording, and History. Tab selection switches the content panel. _File: [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx)_ -```tsx +```tsx lines export const CometChatCallDetails = (props: { selectedItem: any, onBack?: () => void }) => { const { selectedItem, onBack } = props; const callDetailTabItems = [ @@ -136,11 +137,13 @@ export const CometChatCallDetails = (props: { selectedItem: any, onBack?: () => --- -### 4. Call Information Display Component +### 4. Call Information Display + +Renders the call status line (incoming/outgoing) based on who initiated the call. Compares the initiator's UID against the logged-in user to determine direction, then maps the SDK call status to a localized label. _File: [CometChatCallLogInfo.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogInfo.tsx)_ -```tsx +```tsx lines export const CometChatCallDetailsInfo = (props: { call: any }) => { const { call } = props; const [loggedInUser, setLoggedInUser] = useState(null); @@ -160,7 +163,6 @@ export const CometChatCallDetailsInfo = (props: { call: any }) => { case CometChatUIKitConstants.calls.ended: { return isSentByMeFlag ? getLocalizedString("calls_outgoing_call") : getLocalizedString('calls_incoming_call'); } - // ... other status cases } } @@ -179,127 +181,34 @@ export const CometChatCallDetailsInfo = (props: { call: any }) => { --- -## Implementation Flow - -- **Fetch Data / Call Selection** - -```tsx -const onSelectorItemClicked = (e: CometChat.Conversation | CometChat.User | CometChat.Group | CometChat.Call, type: string) => { - if (type === "updateSelectedItemCall") { - setSelectedItem(e as CometChat.Call); - setAppState({ type: "updateSelectedItemCall", payload: e as CometChat.Call }); - } -} -``` - -- **Load Call Data / Associated Information** - -```tsx -useEffect(() => { - const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - const callUser = verifyCallUser(selectedItem, loggedInUser!); - - if (selectedItem.receiverType === CometChatUIKitConstants.MessageReceiverType.user) { - CometChat.getUser(callUser.uid).then((response: CometChat.User) => { - setUser(response); - }); - } -}, [selectedItem]); -``` - -- **Display Call Details / Tab Navigation** - -```tsx -const [activeTab, setActiveTab] = useState("Participants"); - -const renderTabContent = () => { - switch (activeTab) { - case "Participants": - return ; - case "Recording": - return ; - case "History": - return ; - default: - return null; - } -} -``` - -- **Live Updates / User Status Monitoring** - -```tsx -useEffect(() => { - let isBlocked = new MessageUtils().getUserStatusVisible(user); - const userListenerId = "users_custom" + Date.now(); - - if (isBlocked) { - setSubtitleText(""); - return; - } - - setSubtitleText(user?.getStatus()); - - CometChat.addUserListener( - userListenerId, - new CometChat.UserListener({ - onUserOnline: (onlineUser: CometChat.User) => { - if (user?.getUid() === onlineUser.getUid()) { - setSubtitleText(onlineUser?.getStatus()); - } - }, - onUserOffline: (offlineUser: CometChat.User) => { - if (user?.getUid() === offlineUser?.getUid()) { - setSubtitleText(offlineUser?.getStatus()); - } - }, - }) - ); - - return () => { - CometChat.removeUserListener(userListenerId); - }; -}, [user]); -``` - ---- - -## Customization Options - -- Styling overrides via CSS -- Custom tab configurations -- Custom call status labels and icons -- User profile customization -- Duration and date formatting -- Icon replacements - ---- - -## Filtering / Edge Cases - -- Different call types (audio/video/group) -- Call status variations (missed, rejected, busy, etc.) -- Unavailable users -- Missing duration or recording data -- Large call history handling - ---- - -## Error Handling & Data Validation +## Feature Matrix -- Includes try-catch blocks for duration, history, and call list fetching. +| Feature | Component / Method | File | +|:---|:---|:---| +| Calls tab integration | `CometChatCallLogs` | [CometChatSelector.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatSelector/CometChatSelector.tsx) | +| Call details display | `CometChatCallDetails` | [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx) | +| Call information | `CometChatCallDetailsInfo` | [CometChatCallLogInfo.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogInfo.tsx) | +| Call participants | `CometChatCallDetailsParticipants` | [CometChatCallLogParticipants.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogParticipants.tsx) | +| Call recordings | `CometChatCallDetailsRecording` | [CometChatCallLogRecordings.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogRecordings.tsx) | +| Call history | `CometChatCallDetailsHistory` | [CometChatCallLogHistory.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogHistory.tsx) | +| Tab navigation | `activeTab` state | [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx) | +| User status monitoring | `CometChat.addUserListener()` | [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx) | --- -## Summary / Feature Matrix - -| Feature | Component / Method | File Reference | -|:----------------------|:-----------------------------------|:----------------| -| Calls tab integration | `CometChatCallLogs` | [CometChatSelector.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatSelector/CometChatSelector.tsx) | -| Call details display | `CometChatCallDetails` | [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx) | -| Call information | `CometChatCallDetailsInfo` | [CometChatCallLogInfo.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogInfo.tsx) | -| Call participants | `CometChatCallDetailsParticipants`| [CometChatCallLogParticipants.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogParticipants.tsx) | -| Call recordings | `CometChatCallDetailsRecording` | [CometChatCallLogRecordings.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogRecordings.tsx) | -| Call history | `CometChatCallDetailsHistory` | [CometChatCallLogHistory.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogHistory.tsx) | -| Tab navigation | `activeTab` state | [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx) | -| User status monitoring| `CometChat.addUserListener()` | [CometChatCallLogDetails.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCallLog/CometChatCallLogDetails.tsx) | +## Next Steps + + + + The call logs component reference. + + + Overview of calling capabilities. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + \ No newline at end of file diff --git a/ui-kit/react/guide-group-chat.mdx b/ui-kit/react/guide-group-chat.mdx index b62e735ec..eb4bd755a 100644 --- a/ui-kit/react/guide-group-chat.mdx +++ b/ui-kit/react/guide-group-chat.mdx @@ -1,54 +1,50 @@ --- title: "Group Chat" sidebarTitle: "Group Chat" +description: "Implement group management including create, join, members, roles, and ownership transfer in CometChat React UI Kit." --- -Implement comprehensive group management functionality including creation, joining, member management, and administrative controls in your React chat app. + ---- - -## Overview - -Groups Management provides a complete set of features for creating, managing, and participating in group conversations, including member administration, permissions, and group lifecycle management. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key components | `CometChatGroups`, `CometChatGroupMembers`, `CometChatCreateGroup`, `CometChatJoinGroup`, `CometChatAddMembers`, `CometChatBannedMembers`, `CometChatTransferOwnership` | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Features | Create public/private/password-protected groups, manage members, roles, ownership transfer | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -- Provides a full set of features for creating and managing group conversations, including member administration, permissions, and lifecycle management. -- Enables users to create collaborative spaces, manage team communications, control access through different group types, and maintain group organization through administrative tools. -- Your app will support full group lifecycle management from creation to administration, allowing users to create public/private/password-protected groups, manage members, and control group operations. + ---- - -## Prerequisites +This guide covers the full group lifecycle: creating groups, joining them, managing members, changing roles, and transferring ownership. -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- Project setup with initialized CometChat credentials (App ID, Auth Key, Region) -- TypeScript support (recommended) -- Basic chat functionality already implemented -- User authentication already configured +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework. --- ## Components -| Component / Class | Role | -|--------------------------------|------| -| **CometChatCreateGroup** | Creates new groups with different types and settings | -| **CometChatJoinGroup** | Handles joining public and password-protected groups | -| **CometChatGroupMembers** | Displays and manages group member lists | -| **CometChatAddMembers** | Adds new members to existing groups | -| **CometChatBannedMembers** | Manages banned members and unban operations | -| **CometChatTransferOwnership** | Transfers group ownership to other members | +| Component / Class | Role | +|:---|:---| +| `CometChatCreateGroup` | Creates new groups with different types and settings | +| `CometChatJoinGroup` | Handles joining public and password-protected groups | +| `CometChatGroupMembers` | Displays and manages group member lists | +| `CometChatAddMembers` | Adds new members to existing groups | +| `CometChatBannedMembers` | Manages banned members and unban operations | +| `CometChatTransferOwnership` | Transfers group ownership to other members | --- ## Integration Steps -### 1. Create Group Implementation +### 1. Create Group + +Build a form that collects a group name, type (public/private/password), and optional password. On submit, generate a unique GUID, call `CometChat.createGroup()`, and emit `ccGroupCreated` so the rest of the UI updates. _File: [CometChatCreateGroup.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCreateGroup/CometChatCreateGroup.tsx)_ -```tsx +```tsx lines export const CometChatCreateGroup = ({ setShowCreateGroup, onGroupCreated }: CreateGroupProps) => { const [groupType, setGroupType] = useState("public"); const [groupName, setGroupName] = useState(""); @@ -73,12 +69,14 @@ export const CometChatCreateGroup = ({ setShowCreateGroup, onGroupCreated }: Cre --- -### 2. Join Group Implementation +### 2. Join Group + +Handle joining for both public and password-protected groups. Call `CometChat.joinGroup()` with the group's GUID, type, and password (if applicable). On success, emit `ccGroupMemberJoined` to update the member list across the app. _File: [CometChatJoinGroup.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatJoinGroup/CometChatJoinGroup.tsx)_ -```tsx -export const CometChatJoinGroup = ({ group, onHide, onProtectedGroupJoin }) => { +```tsx lines +export const CometChatJoinGroup = ({ group, onProtectedGroupJoin }) => { const [password, setPassword] = useState(""); const [error, setError] = useState(false); const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); @@ -86,7 +84,6 @@ export const CometChatJoinGroup = ({ group, onHide, onProtectedGroupJoin }) => { const joinGroup = () => { CometChat.joinGroup(group.getGuid(), group.getType(), password) .then((res) => { - onHide(); onProtectedGroupJoin(group); CometChatGroupEvents.ccGroupMemberJoined.next({ joinedGroup: res, @@ -100,11 +97,13 @@ export const CometChatJoinGroup = ({ group, onHide, onProtectedGroupJoin }) => { --- -### 3. View Group Members Implementation +### 3. View Group Members + +Render the member list for a group using `CometChatGroupMembers`. Pass `onItemClick` to handle member selection and `options` to add context-menu actions like "View Profile". _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const GroupMembersView = ({ group }: { group: CometChat.Group }) => { return (
@@ -127,13 +126,16 @@ const GroupMembersView = ({ group }: { group: CometChat.Group }) => { }; ``` + --- -### 4. Add Members to Group Implementation +### 4. Add Members + +Let admins select users and add them to the group. Collect selected UIDs, call `CometChat.addMembersToGroup()`, and emit `ccGroupMemberAdded` so the member list refreshes. _File: [CometChatAddMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatAddMembers/CometChatAddMembers.tsx)_ -```tsx +```tsx lines export const CometChatAddMembers = ({ group, onBack }: IAddMembersProps) => { const [selectedUsers, setSelectedUsers] = useState([]); const [isLoading, setIsLoading] = useState(false); @@ -161,11 +163,13 @@ export const CometChatAddMembers = ({ group, onBack }: IAddMembersProps) => { --- -### 5. Ban Member from Group Implementation +### 5. Ban Members + +Fetch the list of banned members using `BannedMembersRequestBuilder`. This component displays banned users and provides unban functionality for group admins. _File: [CometChatBannedMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatBannedMembers/CometChatBannedMembers.tsx)_ -```tsx +```tsx lines export const CometChatBannedMembers = ({ group }: bannedMembersProp) => { const [bannedMembers, setBannedMembers] = useState([]); const [state, setState] = useState(States.loading); @@ -189,13 +193,16 @@ export const CometChatBannedMembers = ({ group }: bannedMembersProp) => { }; ``` + --- -### 6. Change Member Scope Implementation +### 6. Change Member Scope + +Promote or demote a member by calling `CometChat.updateGroupMemberScope()`. Pass the member's UID, the new scope (`admin`, `moderator`, or `participant`), and the group GUID. Emit `ccGroupMemberScopeChanged` so the UI reflects the role change. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const changeMemberScope = async (member: CometChat.GroupMember, newScope: string) => { try { await CometChat.updateGroupMemberScope(member.getUid(), newScope, group.getGuid()); @@ -207,21 +214,21 @@ const changeMemberScope = async (member: CometChat.GroupMember, newScope: string newScope: newScope, oldScope: member.getScope() }); - showSuccessMessage("Member scope updated successfully"); } catch (error) { console.error("Failed to update member scope:", error); - showErrorMessage("Failed to update member scope"); } }; ``` --- -### 7. Transfer Group Ownership Implementation +### 7. Transfer Ownership + +Let the current owner select a member and transfer ownership via `CometChat.transferGroupOwnership()`. The group object is cloned and updated locally, then `ccOwnershipChanged` is emitted to sync the UI. _File: [CometChatTransferOwnership.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatTransferOwnership/CometChatTransferOwnership.tsx)_ -```tsx +```tsx lines export const CometChatTransferOwnership = ({ group, onClose }: ITransferOwnershipProps) => { const [selectedMember, setSelectedMember] = useState(null); const [isLoading, setIsLoading] = useState(false); @@ -252,96 +259,34 @@ export const CometChatTransferOwnership = ({ group, onClose }: ITransferOwnershi --- -## Implementation Flow - -- **Fetch Data / Group Information**: Retrieve group details and member lists. -- **Load Group Data / Member Information**: Fetch members with pagination. -- **Execute Group Operations / Action Handlers**: Handle creation, adding, banning, etc., with proper error handling. -- **Live Updates / Event Handling**: Subscribe to CometChatGroupEvents for member changes and update UI in real time. - ---- - -## Customization Options - -- Styling: Override CSS classes -- Group Types: Customize available types -- Member Permissions: Add custom roles -- UI Components: Modify list/form elements -- Validation Rules: Add extra checks -- Event Handling: Custom responses -- Search & Filtering: Add search for members - ---- - -## Filtering / Edge Cases +## Feature Matrix -- Handle group type restrictions, member limits, and permission checks -- Manage large groups efficiently -- Handle empty groups and network errors gracefully -- Maintain UI consistency with concurrent actions +| Feature | Component / Method | File | +|:---|:---|:---| +| Create group | `CometChatCreateGroup` | [CometChatCreateGroup.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCreateGroup/CometChatCreateGroup.tsx) | +| Join group | `CometChatJoinGroup` | [CometChatJoinGroup.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatJoinGroup/CometChatJoinGroup.tsx) | +| View members | `CometChatGroupMembers` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Add members | `CometChatAddMembers` | [CometChatAddMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatAddMembers/CometChatAddMembers.tsx) | +| Ban members | `CometChatBannedMembers` | [CometChatBannedMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatBannedMembers/CometChatBannedMembers.tsx) | +| Change scope | `updateGroupMemberScope()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Transfer ownership | `CometChatTransferOwnership` | [CometChatTransferOwnership.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatTransferOwnership/CometChatTransferOwnership.tsx) | +| Group events | `CometChatGroupEvents` | Multiple files | --- -## Error Handling & Permission Management - -```tsx -const handleGroupOperation = async (operation: () => Promise) => { - try { - if (!hasPermission(currentUser, currentGroup, 'manage_members')) { - showErrorMessage("You don't have permission to perform this action"); - return; - } - const result = await operation(); - showSuccessMessage("Operation completed successfully"); - return result; - } catch (error) { - if (error.code === "ERR_PERMISSION_DENIED") { - showErrorMessage("Permission denied for this operation"); - } else if (error.code === "ERR_GROUP_NOT_FOUND") { - showErrorMessage("Group not found or no longer exists"); - } else if (error.code === "ERR_MEMBER_NOT_FOUND") { - showErrorMessage("Member not found in this group"); - } else { - showErrorMessage("An error occurred while performing the operation"); - } - console.error("Group operation failed:", error); - } -}; -``` - ---- - -## Context-Specific Notes - -- Different handling for public, private, password-protected groups -- Different permissions for admins, moderators, participants -- Optimize for large groups -- Real-time updates across devices -- Works cross-platform - ---- - -## Summary / Feature Matrix - -| Feature | Component / Method | File Reference | -|--------------------|--------------------------------|----------------| -| Create group | `CometChatCreateGroup` | [CometChatCreateGroup.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatCreateGroup/CometChatCreateGroup.tsx) | -| Join group | `CometChatJoinGroup` | [CometChatJoinGroup.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatJoinGroup/CometChatJoinGroup.tsx) | -| View members | `CometChatGroupMembers` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Add members | `CometChatAddMembers` | [CometChatAddMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatAddMembers/CometChatAddMembers.tsx) | -| Ban members | `CometChatBannedMembers` | [CometChatBannedMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatBannedMembers/CometChatBannedMembers.tsx) | -| Change scope | `updateGroupMemberScope()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Transfer ownership | `CometChatTransferOwnership` | [CometChatTransferOwnership.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatTransferOwnership/CometChatTransferOwnership.tsx) | -| Group events | `CometChatGroupEvents` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx), [CometChatAddMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatAddMembers/CometChatAddMembers.tsx), [CometChatBannedMembers.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatBannedMembers/CometChatBannedMembers.tsx), [CometChatTransferOwnership.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatTransferOwnership/CometChatTransferOwnership.tsx) | -| Member management | `CometChat.GroupMembersRequestBuilder` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx), [CometChatTransferOwnership.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatTransferOwnership/CometChatTransferOwnership.tsx) | - ---- - -## Next Steps & Further Reading - -- [CometChat React UI Kit Documentation](https://www.cometchat.com/docs/ui-kit/react/overview) -- [Sample App Repository](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) -- Group Management Features -- Advanced Customization Guide -- Member Management Documentation - +## Next Steps + + + + Display and manage group lists. + + + Display and manage group member lists. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + \ No newline at end of file diff --git a/ui-kit/react/guide-message-privately.mdx b/ui-kit/react/guide-message-privately.mdx index 1d0add7ad..71d89dde6 100644 --- a/ui-kit/react/guide-message-privately.mdx +++ b/ui-kit/react/guide-message-privately.mdx @@ -1,51 +1,48 @@ --- title: "Message Privately" sidebarTitle: "Message Privately" +description: "Launch a direct 1:1 chat from a group member profile in CometChat React UI Kit." --- -Enable users to initiate private conversations with group members directly from group chat interfaces. + -## Overview +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key components | `CometChatMessages`, `CometChatGroupMembers`, `CometChatMessageComposer`, `CometChatMessageList`, `CometChatMessageHeader` | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Purpose | Launch a direct 1:1 chat from a group member profile | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -The Message Privately (from a Group) feature allows users to start private, one-on-one conversations with specific group members while remaining in the group context. + -- Allows users to start private conversations with specific group members directly from a group. -- Enables confidential discussions, sharing sensitive information, or asking personal questions without disrupting the group conversation. -- Your app will support initiating private messages from group contexts, allowing users to seamlessly switch between group discussions and private conversations. +Message Privately lets users start a direct 1:1 conversation with a group member without leaving the group context. The user can return to the group after the private chat. ---- - -## Prerequisites - -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- Project setup with initialized CometChat credentials (App ID, Auth Key, Region) -- TypeScript support (recommended) -- Group chat functionality already implemented -- User management and conversation handling already implemented +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework. --- ## Components -| Component / Class | Role | -|--------------------------|------| -| **CometChatGroupMembers** | Displays group members with click handlers for private messaging | -| **CometChatUsers** | Alternative user list component for private messaging | -| **CometChatMessageComposer** | Input component for composing private messages | -| **CometChatMessageList** | Displays private conversation messages | -| **CometChatMessageHeader** | Header showing private chat information | +| Component / Class | Role | +|:---|:---| +| `CometChatGroupMembers` | Displays group members with click handlers for private messaging | +| `CometChatMessageComposer` | Input component for composing private messages | +| `CometChatMessageList` | Displays private conversation messages | +| `CometChatMessageHeader` | Header showing private chat information | --- ## Integration Steps -### 1. Group Member Click Handler Setup +### 1. Group Member Click Handler + +When a group member is clicked, cast them to a `User` object and initiate a private chat. The current group is saved so the user can return to it later. `CometChat.getConversation()` fetches or creates the 1:1 conversation. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const handleGroupMemberClick = (groupMember: CometChat.GroupMember) => { const user = groupMember as CometChat.User; startPrivateChatFromGroup(user, currentGroup); @@ -62,18 +59,19 @@ const startPrivateChatFromGroup = (user: CometChat.User, group: CometChat.Group) }) .catch((error) => { console.error("Failed to start private chat:", error); - showErrorMessage("Unable to start private conversation"); }); } ``` --- -### 2. Group Members Component Integration +### 2. Group Members with Private Messaging Option + +Add a "Message Privately" option to the group members list. The `options` prop adds a context-menu action that triggers the private chat flow when clicked. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const GroupMembersWithPrivateMessaging = ({ group }: { group: CometChat.Group }) => { return ( -``` - -- **Load User Data / Conversation State** - -_File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ - -```tsx -const startPrivateChatFromGroup = async (user: CometChat.User, group: CometChat.Group) => { - try { - setAppState({ type: "updatePreviousGroup", payload: group }); - const conversation = await CometChat.getConversation( - user.getUid(), - CometChatUIKitConstants.MessageReceiverType.user - ); - - setSelectedItem(conversation); - setAppState({ type: "updatePrivateChatUser", payload: user }); - setAppState({ type: "updateShowPrivateChat", payload: true }); - - } catch (error) { - console.error("Failed to start private chat:", error); - showErrorMessage("Unable to start private conversation"); - } -} -``` - -- **Send Private Message / Action Handler** - -_File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ - -```tsx -const sendPrivateMessageFromGroup = async (messageText: string, receiverId: string) => { - const textMessage = new CometChat.TextMessage( - receiverId, - messageText, - CometChatUIKitConstants.MessageReceiverType.user - ); - - try { - const sentMessage = await CometChat.sendMessage(textMessage); - console.log("Private message sent from group context:", sentMessage); - showSuccessMessage("Private message sent"); - } catch (error) { - console.error("Failed to send private message:", error); - showErrorMessage("Failed to send private message"); - } -} -``` - -- **Live Updates / Context Switching** - -_Files: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx), [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts)_ - -```tsx -useEffect(() => { - const messageListener = CometChat.addMessageListener( - "privateMessageFromGroupListener", - new CometChat.MessageListener({ - onTextMessageReceived: (textMessage: CometChat.TextMessage) => { - if (textMessage.getReceiverType() === CometChatUIKitConstants.MessageReceiverType.user) { - updatePrivateConversation(textMessage); - if (!showPrivateChat) { - showNotification(`Private message from ${textMessage.getSender().getName()}`); - } - } - } - }) - ); - - return () => CometChat.removeMessageListener("privateMessageFromGroupListener"); -}, [showPrivateChat]); -``` - ---- - -## Customization Options - -- Styling: Override CSS classes for private chat from group interface -- Member Options: Customize available actions for group members -- Navigation: Customize return-to-group behavior and transitions -- Message Types: Support various message types in private conversations -- Context Display: Customize how group context is shown in private chat -- Member Filtering: Control which group members can receive private messages - ---- - -## Filtering / Edge Cases - -- Handle permissions -- Preserve group context -- Manage blocked users -- Scale for large groups - ---- - -## Error Handling & Context Management - -```tsx -const startPrivateChatFromGroup = async (user: CometChat.User, group: CometChat.Group) => { - try { - if (user.getBlockedByMe()) { - showErrorMessage("Cannot send private message to blocked user"); - return; - } - if (!group.getMembers().some(member => member.getUid() === user.getUid())) { - showErrorMessage("User is no longer a member of this group"); - return; - } - - setAppState({ type: "updatePreviousGroup", payload: group }); - const conversation = await CometChat.getConversation( - user.getUid(), - CometChatUIKitConstants.MessageReceiverType.user - ); - - setSelectedItem(conversation); - setAppState({ type: "updateShowPrivateChat", payload: true }); - - } catch (error) { - if (error.code === "ERR_USER_NOT_FOUND") { - showErrorMessage("User not found or unavailable"); - } else if (error.code === "ERR_CONVERSATION_CREATE_FAILED") { - showErrorMessage("Unable to create private conversation"); - } else { - showErrorMessage("An error occurred while starting private chat"); - } - } -} -``` - ---- - -## Summary / Feature Matrix +## Feature Matrix -| Feature | Component / Method | File Reference | -|-------------------------|--------------------------------|----------------| -| Group member selection | `CometChatGroupMembers` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Private chat initiation | `startPrivateChatFromGroup()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Private chat interface | `PrivateChatFromGroupView` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Context preservation | `updatePreviousGroup` | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | -| Private message sending | `sendPrivateMessageFromGroup()`| [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Return to group | `returnToGroup()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Member options | `options` in CometChatGroupMembers | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| State management | `updateShowPrivateChat` | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | +| Feature | Component / Method | File | +|:---|:---|:---| +| Group member selection | `CometChatGroupMembers` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Private chat initiation | `startPrivateChatFromGroup()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Private chat interface | `PrivateChatFromGroupView` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Context preservation | `updatePreviousGroup` | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | +| Return to group | `returnToGroup()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Member options | `options` in CometChatGroupMembers | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| State management | `updateShowPrivateChat` | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | --- -## Next Steps & Further Reading - -- [CometChat React UI Kit Documentation](https://www.cometchat.com/docs/ui-kit/react/overview) -- [Sample App Repository](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) -- Group Management Features -- User Management Features -- Message Types & Features +## Next Steps + + + + Display and manage group member lists. + + + Render real-time message threads. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + diff --git a/ui-kit/react/guide-new-chat.mdx b/ui-kit/react/guide-new-chat.mdx index 54ee2e6b2..8c4fe34ef 100644 --- a/ui-kit/react/guide-new-chat.mdx +++ b/ui-kit/react/guide-new-chat.mdx @@ -1,51 +1,49 @@ --- title: "New Chat" sidebarTitle: "New Chat" +description: "Build a unified new chat entry point for starting 1:1 or group conversations in CometChat React UI Kit." --- -Enable users to create new conversations with individual users or join existing groups in your React chat app. + -## Overview +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key components | `CometChatUsers`, `CometChatGroups`, `CometChatJoinGroup`, `CometChatSelector` | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Purpose | Unified new chat entry point for starting 1:1 or group conversations | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -The New Chat feature allows users to initiate conversations with other users or join group conversations, providing a seamless way to start new communications. + -- Allows users to initiate conversations with other users or join group conversations. -- Enables users to expand their network, join group discussions, and create new chat threads without navigating through complex menus. -- Your app will provide an intuitive interface for users to discover and connect with other users, join groups, and start new conversations with proper navigation and state management. +The New Chat feature lets users start conversations with other users or join group conversations from a single interface. ---- - -## Prerequisites - -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- Project setup with initialized CometChat credentials (App ID, Auth Key, Region) -- TypeScript support (recommended) -- User authentication and basic chat functionality implemented -- User and group management components available +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework. --- ## Components -| Component / Class | Role | -|--------------------------|------| -| **CometChatNewChatView** | Main container for new chat creation interface | -| **CometChatUsers** | Displays list of available users for chat creation | -| **CometChatGroups** | Shows available groups for joining | -| **CometChatJoinGroup** | Handles protected group joining process | -| **CometChatSelector** | Navigation component with new chat button | +| Component / Class | Role | +|:---|:---| +| `CometChatNewChatView` | Main container for new chat creation interface | +| `CometChatUsers` | Displays list of available users for chat creation | +| `CometChatGroups` | Shows available groups for joining | +| `CometChatJoinGroup` | Handles protected group joining process | +| `CometChatSelector` | Navigation component with new chat button | --- ## Integration Steps -### 1. New Chat State Management Setup +### 1. New Chat State Management + +Track whether the new chat view is visible and which user/group was selected. When the "New Chat" button is clicked, show the view and hide any open side panels. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const [showNewChat, setShowNewChat] = useState(false); const [newChat, setNewChat] = useState<{ user?: CometChat.User, @@ -58,15 +56,15 @@ const onNewChatClicked = () => { } ``` -Manages the new chat view visibility and resets side components when opening new chat. - --- -### 2. New Chat View Component Integration +### 2. Conditional Rendering + +Switch between the new chat view, the messages view, or an empty state depending on the current app state. `useCallback` prevents unnecessary re-renders. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const InformationComponent = useCallback(() => { return ( <> @@ -81,15 +79,15 @@ const InformationComponent = useCallback(() => { }, [activeTab, showNewChat, selectedItem, newChat, appState.goToMessageId]); ``` -Conditionally renders the new chat view or message view based on application state. - --- -### 3. New Chat View Implementation +### 3. New Chat View + +The main new chat interface with a header, back button, and tabbed navigation between Users and Groups. Selecting a tab switches the list below. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const CometChatNewChatView: React.FC = () => { const [selectedTab, setSelectedTab] = useState('user'); const [group, setGroup] = useState(); @@ -101,7 +99,6 @@ const CometChatNewChatView: React.FC = () => { return (
- {/* Header */}
{ setShowNewChat(false); @@ -109,13 +106,11 @@ const CometChatNewChatView: React.FC = () => {
New Chat
- {/* Tabs */}
-
handleTabClick('user')}> {getLocalizedString("user_title")}
-
handleTabClick('group')}> {getLocalizedString("group_title")}
+
handleTabClick('user')}> {getLocalizedString("user_title")}
+
handleTabClick('group')}> {getLocalizedString("group_title")}
- {/* Content */}
@@ -128,9 +123,11 @@ const CometChatNewChatView: React.FC = () => { ### 4. User Selection and Chat Creation +The tab content renders either `CometChatUsers` or `CometChatGroups`. Clicking a user creates a 1:1 chat and closes the new chat view. Clicking a group triggers the join flow. + _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const TabContent: React.FC = ({ selectedTab }) => { return selectedTab === 'user' ? { @@ -153,69 +150,13 @@ const TabContent: React.FC = ({ selectedTab }) => { --- -## Implementation Flow +### 5. Group Joining Logic -- **Fetch Data / Available Users and Groups** +Handle the join flow based on group type. Public groups are joined directly via `CometChat.joinGroup()`. Password-protected groups show a password prompt first. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx - { /* handle */ }} /> - { /* handle */ }} /> -``` - -- **Load User/Group Data / Associated Information** - -_File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ - -```tsx -const joinGroup = (e) => { /* join group logic */ } -``` - -- **Create Conversation / Action Handler** - -_File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ - -```tsx -onItemClick={(user) => { setNewChat({ user }); }} -onItemClick={(group) => { joinGroup(group); }} -``` - -- **Live Updates / State Management** - -_Files: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx), [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts)_ - -```tsx -useEffect(() => { /* update message target */ }, [activeTab, selectedItem]); -``` - ---- - -## Customization Options - -- Override CSS styles -- Configure tabs -- Customize list UI -- Add search -- Handle group types -- Adjust navigation - ---- - -## Filtering / Edge Cases - -- User availability -- Group permissions -- Duplicate chats prevention -- Blocking logic -- Membership checks -- Empty states - ---- - -## Error Handling & State Management - -```tsx +```tsx lines const joinGroup = (e) => { if (!e.getHasJoined()) { if (e.getType() === CometChatUIKitConstants.GroupTypes.public) { @@ -232,34 +173,34 @@ const joinGroup = (e) => { --- -## Context-Specific Notes +## Feature Matrix -- Public vs private groups -- Different state logic for user/group chats -- Mobile responsiveness -- Navigation flow control -- Group type handling +| Feature | Component / Method | File | +|:---|:---|:---| +| Open new chat view | `onNewChatClicked()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| New chat interface | `CometChatNewChatView` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| User selection | `CometChatUsers` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Group selection | `CometChatGroups` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Group joining | `joinGroup()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| State management | `showNewChat` state | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | +| Chat creation | `setNewChat()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Navigation handling | `setShowNewChat(false)` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | --- -## Summary / Feature Matrix - -| Feature | Component / Method | File Reference | -|---------------------|-----------------------------|----------------| -| Open new chat view | `onNewChatClicked()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| New chat interface | `CometChatNewChatView` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| User selection | `CometChatUsers` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Group selection | `CometChatGroups` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Group joining | `joinGroup()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| State management | `showNewChat` state | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | -| Chat creation | `setNewChat()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Navigation handling | `setShowNewChat(false)` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | - ---- - -## Next Steps & Further Reading - -- [CometChat React UI Kit Documentation](https://www.cometchat.com/docs/ui-kit/react/overview) -- [Sample App Repository](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) -- User Management Features -- Group Management Features +## Next Steps + + + + Display and manage conversation lists. + + + Display and manage group lists. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + diff --git a/ui-kit/react/guide-overview.mdx b/ui-kit/react/guide-overview.mdx index 10ab044fd..8a77dfc49 100644 --- a/ui-kit/react/guide-overview.mdx +++ b/ui-kit/react/guide-overview.mdx @@ -1,7 +1,21 @@ --- title: "Overview" sidebarTitle: "Overview" +description: "Index of task-oriented feature guides for the CometChat React UI Kit." --- + + + +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Purpose | Index of task-oriented feature guides for the React UI Kit | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Components | [Components Overview](/ui-kit/react/components-overview) | +| Guides | [Block/Unblock](/ui-kit/react/guide-block-unblock-user) · [Call Log Details](/ui-kit/react/guide-call-log-details) · [Group Chat](/ui-kit/react/guide-group-chat) · [Message Privately](/ui-kit/react/guide-message-privately) · [New Chat](/ui-kit/react/guide-new-chat) · [Search Messages](/ui-kit/react/guide-search-messages) · [Threaded Messages](/ui-kit/react/guide-threaded-messages) | + + + > This page indexes focused, task‑oriented feature guides for the React UI Kit. Each guide shows how to implement a specific capability end‑to‑end using UI components. ## When to Use These Guides @@ -24,5 +38,23 @@ Use these guides after completing the base [Getting Started](/ui-kit/react/react | [URL Formatter](/ui-kit/react/url-formatter-guide) | Detect and style plain URLs; render them as clickable links with optional tracking logic. | | [Shortcut Formatter](/ui-kit/react/shortcut-formatter-guide) | Provide !shortcut style expansions invoking extension APIs or dialogs before inserting content. | -Need another guide? Open a request via our [Developer Community](http://community.cometchat.com/) or Support. +Need another guide? Open a request via our [Support Portal](https://help.cometchat.com/hc/en-us/requests/new). + +--- + +## Next Steps + + + Set up the React UI Kit + + + Explore all UI components + + + Customize themes and styling + + + Handle UI Kit events + + diff --git a/ui-kit/react/guide-search-messages.mdx b/ui-kit/react/guide-search-messages.mdx index 072126f4f..38dfd800f 100644 --- a/ui-kit/react/guide-search-messages.mdx +++ b/ui-kit/react/guide-search-messages.mdx @@ -1,49 +1,48 @@ --- title: "Search Messages" sidebarTitle: "Search Messages" +description: "Add full-text message search across conversations with result routing in CometChat React UI Kit." --- -Enable users to search messages within conversations and group chats using CometChat's React UI Kit. + -## Overview +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key components | `CometChatSearchMessages`, `CometChatMessageList`, `CometChatMessageComposer`, `CometChatMessageHeader` | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Purpose | Full-text message search across conversations with result routing and navigation | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -The Search Messages feature allows users to quickly locate specific messages across conversations and groups. + -- Provides keyword-based search for locating past messages. -- Improves user experience by helping users find information without scrolling through long conversations. -- Users can search messages in real-time across chats and navigate directly to relevant results. +Search Messages lets users locate specific messages across conversations and groups using keyword search, then navigate directly to the result. ---- - -## Prerequisites - -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- Project setup with initialized CometChat credentials (App ID, Auth Key, Region) -- TypeScript support (recommended) -- Basic messaging functionality already implemented +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework. --- ## Components -| Component / Class | Role | -|----------------------------|------| -| **CometChatSearchMessages** | Main container for searching messages | -| **CometChatMessageList** | Displays filtered messages based on search results | -| **CometChatMessageComposer** | Supports navigation after selecting a search result | -| **CometChatMessageHeader** | Displays search context and navigation controls | +| Component / Class | Role | +|:---|:---| +| `CometChatSearchMessages` | Main container for searching messages | +| `CometChatMessageList` | Displays filtered messages based on search results | +| `CometChatMessageComposer` | Supports navigation after selecting a search result | +| `CometChatMessageHeader` | Displays search context and navigation controls | --- ## Integration Steps -### 1. Search State Management Setup +### 1. Search State Management + +Track the current search keyword and the message ID to scroll to. When a new search is triggered, reset `goToMessageId` so the list doesn't jump to a stale result. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const [searchKeyword, setSearchKeyword] = useState(""); const [goToMessageId, setGoToMessageId] = useState(undefined); @@ -55,11 +54,13 @@ const onSearch = (keyword: string) => { --- -### 2. Search Input and Trigger +### 2. Search Input + +Render the search component and wire its `onSearch` callback to update the keyword state. The placeholder text is localized. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines onSearch(keyword)} placeholder={getLocalizedString("search_messages_placeholder")} @@ -70,9 +71,11 @@ _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/bl ### 3. Search Result Integration +Pass `searchKeyword` and `goToMessageId` to `CometChatMessageList`. The list filters messages matching the keyword and highlights them. When `goToMessageId` is set, the list scrolls to that message. + _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines { setGoToMessageId(messageId); }; @@ -97,90 +102,31 @@ Attach `handleResultClick` to your message search result selection logic. --- -## Implementation Flow - -- **Fetch Search Input** - -```tsx - -``` - -- **Execute Search** - -```tsx - -``` - -- **Navigate to Result** - -```tsx -handleResultClick(messageId); -``` - ---- - -## Customization Options +## Feature Matrix -- Style the search input field -- Configure placeholder text -- Limit search scope (e.g., per conversation or global) -- Highlight search keywords in results -- Customize empty search result UI +| Feature | Component / Method | File | +|:---|:---|:---| +| Search input | `CometChatSearchMessages` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Display results | `CometChatMessageList` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Keyword highlighting | `searchKeyword` prop | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Navigate to result | `goToMessageId` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| State management | `onSearch` handler | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | --- -## Filtering / Edge Cases - -- Empty keyword input -- No results found -- Large result sets (pagination) -- Permissions-based filtering -- Search in archived conversations - ---- - -## Error Handling - -```tsx -try { - const messages = await messagesRequest.fetchNext(); - setSearchResults(messages); -} catch (error) { - console.error("Search failed:", error); - showErrorMessage("Unable to fetch search results"); -} -``` - -- Handle network errors gracefully -- Provide retry option -- Maintain UI state on error - ---- - -## Context-Specific Notes - -- Search works across one-on-one and group chats -- Integrates with thread navigation via `goToMessageId` -- Optimized for real-time updates -- Responsive across devices - ---- - -## Summary / Feature Matrix - -| Feature | Component / Method | File Reference | -|---------------------|---------------------------|----------------| -| Search input | `CometChatSearchMessages` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Display results | `CometChatMessageList` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Keyword highlighting| `searchKeyword` prop | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Navigate to result | `goToMessageId` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| State management | `onSearch` handler | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | - ---- - -## Next Steps & Further Reading - -- [CometChat React UI Kit Documentation](https://www.cometchat.com/docs/ui-kit/react/overview) -- [Sample App Repository](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) -- Message Management Features -- Advanced Search Features +## Next Steps + + + + The search component reference. + + + Render real-time message threads. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + \ No newline at end of file diff --git a/ui-kit/react/guide-threaded-messages.mdx b/ui-kit/react/guide-threaded-messages.mdx index 50c06c07f..d22414daa 100644 --- a/ui-kit/react/guide-threaded-messages.mdx +++ b/ui-kit/react/guide-threaded-messages.mdx @@ -1,49 +1,49 @@ --- title: "Threaded Messages" sidebarTitle: "Threaded Messages" +description: "Implement threaded message replies with parent context, reply list, and focused thread composer in CometChat React UI Kit." --- -Enable organized threaded conversations within group chats using CometChat's React UI Kit. + -## Overview +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key components | `CometChatThreadedMessages`, `CometChatThreadHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Init | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Entry point | `CometChatMessages.onThreadRepliesClick` opens thread view from group messages | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [All Guides](/ui-kit/react/guide-overview) | -Threaded messages in group chat allow users to create organized sub-conversations by replying to specific messages. + -- Threaded messages in group chat allow users to create organized sub-conversations by replying to specific messages. -- Improves group conversation organization, reduces chat clutter, and enables focused discussions. -- Group chats display threaded conversations with clear parent-child relationships. +Threaded messages let users create sub-conversations by replying to specific messages in group chats. This reduces clutter and keeps discussions focused. ---- - -## Prerequisites - -- React v18.2.0+ -- CometChat React UI Kit v6.1.0+ -- CometChat Chat SDK JavaScript v4.0.13+ -- CometChat credentials configured (App ID, Auth Key, Region) -- Group chat functionality implemented +Before starting, complete the [Getting Started](/ui-kit/react/react-js-integration) guide for your framework. --- ## Components -| Component / Class | Role | -|:----------------------------------|:------------------------------------------------| -| **CometChatThreadedMessages** | Main container for threaded messages | -| **CometChatThreadHeader** | Displays parent message and controls | -| **CometChatMessageList** | Shows messages filtered by `parentMessageId` | -| **CometChatMessageComposer** | Input for composing threaded replies | -| **CometChatMessages.onThreadRepliesClick** | Opens thread view from group messages | +| Component / Class | Role | +|:---|:---| +| `CometChatThreadedMessages` | Main container for threaded messages | +| `CometChatThreadHeader` | Displays parent message and controls | +| `CometChatMessageList` | Shows messages filtered by `parentMessageId` | +| `CometChatMessageComposer` | Input for composing threaded replies | +| `CometChatMessages.onThreadRepliesClick` | Opens thread view from group messages | --- ## Integration Steps -### 1. Thread State Management Setup +### 1. Thread State Management + +Store the parent message that the user clicked "Reply in Thread" on. When set, update the app state to show the threaded messages side panel. _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines const [threadedMessage, setThreadedMsg] = useState(); const updateThreadedMessage = (message: CometChat.BaseMessage) => { @@ -57,9 +57,11 @@ const updateThreadedMessage = (message: CometChat.BaseMessage) => { ### 2. Thread Trigger in Group Messages +Wire the `onThreadRepliesClick` callback on `CometChatMessages`. When a user clicks the thread reply icon on any message, this fires with the parent message object. + _File: [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx)_ -```tsx +```tsx lines ``` -- **Send Reply** - -```tsx +```tsx lines ``` -- **Live Updates** - -```tsx -useEffect(() => { - if (message.getId() === threadedMessage?.getId()) { - // handle updates - } -}, [message, threadedMessage]); -``` - ---- - -## Customization Options - -- Override CSS for styling -- Search keyword highlighting -- Control composer visibility -- Custom message filtering -- Search integration within threads - ---- +When the composer is blocked (e.g. permissions), show a fallback: -## Filtering / Edge Cases - -- Search within threads -- Go to specific message in thread -- Handle empty or deleted threads -- Respect group permissions - ---- - -## Error Handling - -```tsx +```tsx lines {showComposer ? ( { --- -## Context Notes - -- Works specifically in group chats -- Member roles affect permissions -- Mobile responsive -- Scales well for large groups - ---- - ## Feature Matrix -| Feature | Component / Method | File | -|:--------------------|:------------------------|:---------------------------| -| Show thread option | `onThreadRepliesClick` | [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx) | -| Display thread msgs | `ThreadedMessageList` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | -| Compose reply | `MessageComposer` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | -| Thread header | `ThreadHeader` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | -| Search in threads | `TextHighlightFormatter`| [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | -| Navigate to message | `goToMessageId` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| Thread state | `updateThreadedMessage()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | -| App context | `appReducer.ts` | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | +| Feature | Component / Method | File | +|:---|:---|:---| +| Show thread option | `onThreadRepliesClick` | [CometChatMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatMessages/CometChatMessages.tsx) | +| Display thread msgs | `ThreadedMessageList` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | +| Compose reply | `MessageComposer` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | +| Thread header | `ThreadHeader` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | +| Search in threads | `TextHighlightFormatter` | [CometChatThreadedMessages.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx) | +| Navigate to message | `goToMessageId` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| Thread state | `updateThreadedMessage()` | [CometChatHome.tsx](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/components/CometChatHome/CometChatHome.tsx) | +| App context | `appReducer.ts` | [appReducer.ts](https://github.com/cometchat/cometchat-uikit-react/blob/v6/sample-app/src/context/appReducer.ts) | --- ## Next Steps -- Explore [CometChat React UI Kit Docs](https://www.cometchat.com/docs/ui-kit/react/overview) -- Check the [Sample App Repo](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) + + + Render real-time message threads. + + + Customize the thread header component. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + diff --git a/ui-kit/react/incoming-call.mdx b/ui-kit/react/incoming-call.mdx index e55f9f37f..981661df1 100644 --- a/ui-kit/react/incoming-call.mdx +++ b/ui-kit/react/incoming-call.mdx @@ -1,947 +1,500 @@ --- title: "Incoming Call" +description: "Visual notification for incoming voice/video calls with accept and decline controls." --- + +```json +{ + "component": "CometChatIncomingCall", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatIncomingCall } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Visual notification for incoming voice/video calls with accept and decline controls.", + "cssRootClass": ".cometchat-incoming-call", + "props": { + "data": { + "call": { "type": "any", "default": "auto-detected" }, + "callSettingsBuilder": { "type": "(call: CometChat.Call) => CallSettingsBuilder", "default": "undefined" } + }, + "callbacks": { + "onAccept": "(call: CometChat.Call) => void", + "onDecline": "(call: CometChat.Call) => void", + "onError": "((error: CometChat.CometChatException) => void) | null" + }, + "sound": { + "disableSoundForCalls": { "type": "boolean", "default": false }, + "customSoundForCalls": { "type": "string", "default": "undefined" } + }, + "viewSlots": { + "itemView": "(call: CometChat.Call) => JSX.Element", + "leadingView": "(call: CometChat.Call) => JSX.Element", + "titleView": "(call: CometChat.Call) => JSX.Element", + "subtitleView": "(call: CometChat.Call) => JSX.Element", + "trailingView": "(call: CometChat.Call) => JSX.Element" + } + }, + "events": [ + { "name": "CometChatCallEvents.ccCallRejected", "payload": "CometChat.Call" }, + { "name": "CometChatCallEvents.ccCallAccepted", "payload": "CometChat.Call" }, + { "name": "CometChatCallEvents.ccCallEnded", "payload": "CometChat.Call" } + ] +} +``` + -## Overview - -The `Incoming call` is a Component that serves as a visual representation when the user receives an incoming call, such as a voice call or video call, providing options to answer or decline the call. - - - - - -The `Incoming Call` is comprised of the following base components: - -| Components | Description | -| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| cometchat-list-item | This component’s view consists of avatar, status indicator , title, and subtitle. The fields are then mapped with the SDK’s user, group class. | -| cometchat-button | This component represents a button with optional icon and text. | -| cometchat-avatar | This component component displays an image or user's avatar with fallback to the first two letters of the username. | - -## Usage +## Where It Fits -### Integration +`CometChatIncomingCall` is an overlay component that auto-detects incoming calls and renders a notification with accept/decline buttons. Place it at the app root level so it appears above all other content. - - -```tsx +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - return ; -}; - -export default IncomingCallsDemo; -``` +import "@cometchat/chat-uikit-react/css-variables.css"; - - - -```tsx -import { IncomingCallsDemo } from "./IncomingCallsDemo"; - -export default function App() { +function App() { return ( -
-
- -
+
+ + {/* rest of app */}
); } ``` - - - - -### Actions - -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. - -##### 1. onAccept - -`onAccept` is triggered when you click the accept button of the `Incoming Call` component. You can override this action using the following code snippet. - - - -```ts -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const handleOnAccept = () => { - console.log("custom on accept action"); - }; - - return ; -}; + + + -export default IncomingCallsDemo; -``` +--- - +## Minimal Render - -```js +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const handleOnAccept = () => { - console.log("custom on accept action"); - }; +import "@cometchat/chat-uikit-react/css-variables.css"; - return ; -}; +function IncomingCallDemo() { + return ; +} -export default IncomingCallsDemo; +export default IncomingCallDemo; ``` - - - - -##### 2. onDecline +Root CSS class: `.cometchat-incoming-call` -`onDecline` is triggered when you click the Decline button of the `Incoming Call` component. You can override this action using the following code snippet. +--- - - -```ts -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; +## Actions and Events -const IncomingCallsDemo = () => { - const handleOnDecline = () => { - console.log("your custom on decline action"); - }; +### Callback Props - return ; -}; +#### onAccept -export default IncomingCallsDemo; -``` +Fires when the accept button is clicked. - - - -```js +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const handleOnDecline = () => { - console.log("your custom on decline action"); - }; - - return ; -}; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export default IncomingCallsDemo; +function IncomingCallWithAccept() { + return ( + { + console.log("Call accepted:", call); + }} + /> + ); +} ``` - - - - -##### 3. onError - -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Incoming Call component. - - - -```ts -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const handleOnError = (error: CometChat.CometChatException) => { - console.log("your custom on error action", error); - }; - - return ; -}; +#### onDecline -export default IncomingCallsDemo; -``` +Fires when the decline button is clicked. - - - -```js +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const handleOnError = (error) => { - console.log("your custom on error action", error); - }; - - return ; -}; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export default IncomingCallsDemo; +function IncomingCallWithDecline() { + return ( + { + console.log("Call declined:", call); + }} + /> + ); +} ``` - - - +#### onError -*** +Fires on internal errors. -### Filters - -You can set `CallSettingsBuilder` in the Incoming Call Component to customise the calling experience. To know more about the filters available please refer to [CallSettingsBuilder](/sdk/javascript/direct-call#settings). - - - -```ts +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getCallSettingsBuilder = (call: CometChat.Call) => { - return new CometChatCalls.CallSettingsBuilder() - .setIsAudioOnlyCall( - call?.getType() === CometChatUIKitConstants.MessageTypes.audio - ? true - : false - ) - .build(); - }; - - return ; -}; - -export default IncomingCallsDemo; -``` - - - - -```js -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getCallSettingsBuilder = (call) => { - return new CometChatCalls.CallSettingsBuilder() - .setIsAudioOnlyCall( - call?.getType() === CometChatUIKitConstants.MessageTypes.audio - ? true - : false - ) - .build(); - }; - - return ; -}; - -export default IncomingCallsDemo; -``` - - - - - -### Events - -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. - -The list of events emitted by the Incoming Call component is as follows. - -| Event | Description | -| ------------------ | ---------------------------------------------------------------------------- | -| **ccCallRejected** | This event is triggered when the initiated call is rejected by the receiver. | -| **ccCallAccepted** | This event is triggered when the initiated call is accepted by the receiver. | -| **ccCallEnded** | This event is triggered when the initiated call successfully ends. | - - - -```tsx -const ccCallRejected = CometChatCallEvents.ccCallRejected.subscribe( - (call: CometChat.Call) => { - //Your Code - } -); - -const ccCallAccepted = CometChatCallEvents.ccCallAccepted.subscribe( - (call: CometChat.Call) => { - //Your Code - } -); +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const ccCallEnded = CometChatCallEvents.ccCallEnded.subscribe( - (call: CometChat.Call) => { - //Your Code - } -); +function IncomingCallWithError() { + return ( + { + console.error("IncomingCall error:", error); + }} + /> + ); +} ``` - +### Global UI Events - +`CometChatCallEvents` emits events subscribable from anywhere in the application. -*** +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccCallRejected` | Incoming call is rejected | `CometChat.Call` | +| `ccCallAccepted` | Incoming call is accepted | `CometChat.Call` | +| `ccCallEnded` | Call ends | `CometChat.Call` | - - -```tsx -ccCallRejected?.unsubscribe(); - -ccCallAccepted?.unsubscribe(); +```tsx lines +import { useEffect } from "react"; +import { CometChatCallEvents } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -ccCallEnded?.unsubscribe(); +function useCallEvents() { + useEffect(() => { + const acceptedSub = CometChatCallEvents.ccCallAccepted.subscribe( + (call: CometChat.Call) => console.log("Accepted:", call) + ); + const rejectedSub = CometChatCallEvents.ccCallRejected.subscribe( + (call: CometChat.Call) => console.log("Rejected:", call) + ); + + return () => { + acceptedSub?.unsubscribe(); + rejectedSub?.unsubscribe(); + }; + }, []); +} ``` - - - +### SDK Events (Real-Time, Automatic) -*** +The component listens to SDK call events internally for real-time incoming call detection. No manual attachment needed. -## Customization +--- -To fit your app's design requirements, you can customize the appearance of the Incoming Call component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. +## Custom View Slots -### Style +View slots for `CometChatIncomingCall` are functions that receive the `CometChat.Call` object. -Using CSS you can customize the look and feel of the component in your app like the color, size, shape, and fonts. +| Slot | Signature | Replaces | +| --- | --- | --- | +| `itemView` | `(call: CometChat.Call) => JSX.Element` | Entire list item | +| `leadingView` | `(call: CometChat.Call) => JSX.Element` | Avatar / left section | +| `titleView` | `(call: CometChat.Call) => JSX.Element` | Name / title text | +| `subtitleView` | `(call: CometChat.Call) => JSX.Element` | Subtitle text | +| `trailingView` | `(call: CometChat.Call) => JSX.Element` | Right section | -**Example:** +### leadingView - + - - -```ts -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - return ; -}; - -export default IncomingCallsDemo; -``` - - - - -```js -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - return ; -}; - -export default IncomingCallsDemo; -``` - - - - -```css -.cometchat-incoming-call { - display: flex; - width: 555px; - padding: 30.833px; - flex-direction: column; - align-items: center; - gap: 24.667px; - flex-shrink: 0; - border-radius: 18.5px; - border: 1.542px solid #aa9ee8; - background: #fff; - box-shadow: 0px 18.5px 24.667px -6.167px rgba(16, 24, 40, 0.08), 0px 6.167px - 9.25px -3.083px rgba(16, 24, 40, 0.03); -} - -.cometchat-incoming-call .cometchat-list-item { - width: 100%; -} - -.cometchat-incoming-call .cometchat-incoming-call__button-group { - justify-content: center; -} - -.cometchat-incoming-call__button-decline, -.cometchat-incoming-call__button-accept { - background-color: white; - border-radius: 12px; - border: 1.5px solid #dcdcdc; -} - -.cometchat-incoming-call__button-decline .cometchat-button:hover, -.cometchat-incoming-call__button-decline .cometchat-button { - background-color: white; - background-color: white; - border-radius: 12px; - border: 1.5px solid #dcdcdc; -} - -.cometchat-incoming-call__button-accept .cometchat-button:hover, -.cometchat-incoming-call__button-accept .cometchat-button { - background-color: #6852d6; - color: white; -} - -.cometchat-incoming-call__button-decline .cometchat-button__text { - color: #f44649; - font: 500 21px/120% roboto; - font-style: normal; -} - -.cometchat-incoming-call__button-accept .cometchat-button__text { - color: #fff; - font: 500 21px/120% roboto; - font-style: normal; -} - -.cometchat-incoming-call__button-decline .cometchat .cometchat-button::before, -.cometchat-incoming-call__button-accept .cometchat .cometchat-button::before { - content: url("../assets/call-decline.svg"); - width: 37px; - height: 37px; - flex-shrink: 0; -} - -.cometchat-incoming-call__button-accept .cometchat .cometchat-button::before { - content: url("../assets/call-accept.svg"); -} - -.cometchat-incoming-call__avatar, -.cometchat-incoming-call__avatar .cometchat-avatar { - display: flex; - width: 123.333px; - height: 123.333px; - justify-content: center; - align-items: center; - border-radius: 24.667px; - background: #aa9ee8; -} - -.cometchat-incoming-call__avatar .cometchat-avatar__image { - border-radius: 24.667px; -} - -.cometchat-incoming-call__avatar .cometchat-avatar__text { - color: #fff; - text-align: center; - font: 500 21px/120% roboto; - font-style: normal; -} - -.cometchat-incoming-call .cometchat-list-item__body { - flex-direction: column-reverse; - gap: 20px; - background: #fff; -} - -.cometchat-incoming-call .cometchat-list-item__body-title { - color: #141414; -} - -.cometchat-incoming-call .cometchat-list-item__title-container { - text-align: center; - gap: 6px; -} +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatAvatar, CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -.cometchat-list-item__body-subtitle { - justify-content: center; +function CustomLeadingIncoming() { + return ( + ( + + )} + /> + ); } ``` - - - +### titleView -### Functionality - -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. - -Here is a code snippet demonstrating how you can customize the functionality of the `Incoming Call` component. + + + - - -```ts +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; -const IncomingCallsDemo = () => { +function CustomTitleIncoming() { return ( ( +
{call.getCallInitiator()?.getName()}
+ )} /> ); -}; - -export default IncomingCallsDemo; +} ``` -
+### itemView - -```js -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; + + + + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatAvatar, CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -const IncomingCallsDemo = () => { +function CustomItemViewIncoming() { return ( ( +
+ +
{call.getCallInitiator()?.getName()}
+
{"Incoming " + call.getType() + " call"}
+
+ )} /> ); -}; - -export default IncomingCallsDemo; +} ``` -
- -
- -Below is a list of customizations along with corresponding code snippets - -| Property | Description | Code | -| ----------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------- | -| **Call** | The CometChat call object used to initialize and display the incoming call component. | `call={callObject}` | -| **Disable sound** | Disables the sound for incoming calls. | `disableSoundForCalls={true}` | -| **Custom sound** | Specifies a custom sound to play for incoming calls. | `customSoundForCalls='Your Custom Sound For Calls'` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -*** +--- -#### SubtitleView +## Common Patterns -Property `subtitleView` is a function that renders a JSX element to display the subtitle view. +### Disable ringtone - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; -const IncomingCallsDemo = () => { - const getSubtitleView = (call: CometChat.Call): JSX.Element => { - /** Return custom subtitle view */ - }; - - return ; -}; - -export default IncomingCallsDemo; +function SilentIncoming() { + return ; +} ``` - +### Custom ringtone - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; -const IncomingCallsDemo = () => { - const getSubtitleView = (call) => { - /** Return custom subtitle view */ - }; - - return ; -}; - -export default IncomingCallsDemo; +function CustomSoundIncoming() { + return ; +} ``` - +--- - +## CSS Architecture -#### LeadingView +### Key Selectors -Property `leadingView` is a function that renders a JSX element to display the leading view. +| Target | Selector | +| --- | --- | +| Root | `.cometchat-incoming-call` | +| List item | `.cometchat-incoming-call .cometchat-list-item` | +| Body title | `.cometchat-incoming-call .cometchat-list-item__body-title` | +| Button group | `.cometchat-incoming-call__button-group` | +| Decline button | `.cometchat-incoming-call__button-decline` | +| Accept button | `.cometchat-incoming-call__button-accept` | -The customized call interface is displayed below. +### Example: Brand-themed incoming call - + -Use the following code to achieve the customization shown above. - - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatAvatar, CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getLeadingView = (call: CometChat.Call) => { - return ( -
- -
- ) - }; +```css lines +.cometchat-incoming-call { + border-radius: 18.5px; + border: 1.542px solid #aa9ee8; + background: #fff; +} - return ; -}; +.cometchat-incoming-call__button-decline .cometchat-button__text { + color: #f44649; +} -export default IncomingCallsDemo; +.cometchat-incoming-call__button-accept .cometchat-button { + background-color: #6852d6; +} ``` -
+--- - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatAvatar, CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getLeadingView = (call) => { - return ( -
- -
- ) - }; +## Accessibility - return ; -}; +The accept and decline buttons are keyboard-focusable and activate on Enter/Space. The caller name and call type are exposed as text content. The component renders as an absolutely positioned overlay. -export default IncomingCallsDemo; -``` +--- -
+--- - -```css -.cometchat-incoming-call__avatar { - display: none; -} -``` +## Props - +All props are optional. -
+--- -#### TitleView +### call -Property `titleView` is a function that renders a JSX element to display the title view. +Sets a specific call object for the incoming call display. -The customized call interface is displayed below. +| | | +| --- | --- | +| Type | `any` | +| Default | Auto-detected | - - - +--- -Use the following code to achieve the customization shown above. +### callSettingsBuilder - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getTitleView = (call: CometChat.Call) => { - return ( -
- {call?.getCallInitiator()?.getName()} -
-
- {call.getCallInitiator()?.getRole()} -
-
- ) - }; +Custom call settings builder for the call session. - return ; -}; +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => typeof CometChatUIKitCalls.CallSettingsBuilder` | +| Default | `undefined` | -export default IncomingCallsDemo; -``` +--- - +### customSoundForCalls - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getTitleView = (call) => { - return ( -
- {call?.getCallInitiator()?.getName()} -
-
- {call.getCallInitiator()?.getRole()} -
-
- ) - }; +Custom sound file URL for incoming calls. - return ; -}; +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | -export default IncomingCallsDemo; -``` +--- - - - -```css -.incoming-call__title-wrapper { - display: flex; - width: 370px; - height: 37px; - padding: 2px 10px; - align-items: center; - gap: 10px; - color: #141414; - font: 700 24px Roboto; -} +### disableSoundForCalls -.incoming-call__tag { - display: flex; - height: 30.036px; - padding: 2.002px 6.007px; - justify-content: center; - align-items: center; - gap: 6.007px; - border-radius: 14.017px; - background: #09C26F; - color: #FFF; - font: 600 12px Roboto; -} +Disables the incoming call ringtone. -.incoming-call__tag-icon { - background-image: url(""); - background-size: contain; - height: 20px; - width: 20px; -} -``` +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- - +### itemView -#### TrailingView +Custom renderer for the entire list item. -Property `trailingView` is a function that renders a JSX element to display the trailing view. +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => JSX.Element` | +| Default | `undefined` | -The customized call interface is displayed below. +--- - - - +### leadingView -Use the following code to achieve the customization shown above. +Custom renderer for the avatar / left section. - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getTrailingView = (call: CometChat.Call) => { - return ( -
-
- {call.getCallInitiator()?.getRole()} -
- ) - }; +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => JSX.Element` | +| Default | `undefined` | - return ; -}; +--- -export default IncomingCallsDemo; -``` +### onAccept - +Callback fired when the accept button is clicked. - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getTrailingView = (call) => { - return ( -
-
- {call.getCallInitiator()?.getRole()} -
- ) - }; +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => void` | +| Default | `undefined` | - return ; -}; +--- -export default IncomingCallsDemo; -``` +### onDecline - - - -```css -.incoming-call__avatar { - display: flex; - height: 62px; - padding: 1px 3px; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 3px; - border-radius: 7px; - background: #AA9EE8; - color: #FFF; - font: 600 10px Roboto; -} +Callback fired when the decline button is clicked. -.incoming-call__avatar-icon { - background-image: url(" void` | +| Default | `undefined` | - +--- - +### onError -#### ItemView +Callback fired when the component encounters an error. -Property `itemView` is a function that renders a JSX element to display the item view. +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | -The customized call interface is displayed below. +--- - - - +### subtitleView -Use the following code to achieve the customization shown above. +Custom renderer for the subtitle text. - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatAvatar, CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getItemView = (call: CometChat.Call) => { - return ( -
- -
-
- {call?.getCallInitiator()?.getName()} -
-
- {"Incoming " + call.getType() + " call"} -
-
-
- ) - }; +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => JSX.Element` | +| Default | `undefined` | - return ; -}; +--- -export default IncomingCallsDemo; -``` +### titleView -
+Custom renderer for the name / title text. - -```js -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatAvatar, CometChatIncomingCall } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const IncomingCallsDemo = () => { - const getItemView = (call) => { - return ( -
- -
-
- {call?.getCallInitiator()?.getName()} -
-
- {"Incoming " + call.getType() + " call"} -
-
-
- ) - }; +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => JSX.Element` | +| Default | `undefined` | - return ; -}; +--- -export default IncomingCallsDemo; -``` +### trailingView -
- - -```css -.incoming-call__itemview { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 20px; - align-self: stretch; -} +Custom renderer for the right section. -.incoming-call__itemview .cometchat-avatar, -.incoming-call__itemview .cometchat-avatar__image { - height: 90px; - width: 90px; - border-radius: 24px; -} +| | | +| --- | --- | +| Type | `(call: CometChat.Call) => JSX.Element` | +| Default | `undefined` | -.incoming-call__itemview .cometchat-avatar__text { - color: #FFF; - text-align: center; - font: 700 32px Roboto -} +--- -.incoming-call__itemview-title { - color: #141414; - text-align: center; - font: 700 24px Roboto; -} +## Events -.incoming-call__itemview-subtitle { - color: var(--Color-Text-Color-Text-Secondary, #727272); - font: 400 16px Roboto; -} -``` +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatCallEvents.ccCallRejected` | `CometChat.Call` | Call rejected | +| `CometChatCallEvents.ccCallAccepted` | `CometChat.Call` | Call accepted | +| `CometChatCallEvents.ccCallEnded` | `CometChat.Call` | Call ended | - +--- -
+## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-incoming-call` | +| List item | `.cometchat-incoming-call .cometchat-list-item` | +| Body title | `.cometchat-incoming-call .cometchat-list-item__body-title` | +| Title container | `.cometchat-incoming-call .cometchat-list-item__title-container` | +| Trailing view | `.cometchat-incoming-call .cometchat-list-item__trailing-view` | +| Button group | `.cometchat-incoming-call__button-group` | +| Decline button | `.cometchat-incoming-call__button-decline` | +| Accept button | `.cometchat-incoming-call__button-accept` | diff --git a/ui-kit/react/link/changelog.mdx b/ui-kit/react/link/changelog.mdx index 8c698a26d..e3acadbd7 100644 --- a/ui-kit/react/link/changelog.mdx +++ b/ui-kit/react/link/changelog.mdx @@ -1,4 +1,4 @@ --- title: "Changelog" url: "https://github.com/cometchat/cometchat-uikit-react/releases?q=v6&expanded=true" ---- \ No newline at end of file +--- diff --git a/ui-kit/react/link/figma.mdx b/ui-kit/react/link/figma.mdx index 172dd3788..784cf16e7 100644 --- a/ui-kit/react/link/figma.mdx +++ b/ui-kit/react/link/figma.mdx @@ -1,4 +1,4 @@ --- title: "Figma Design" url: "https://www.figma.com/community/file/1442863561340379957/cometchat-ui-kit-for-web" ---- \ No newline at end of file +--- diff --git a/ui-kit/react/link/sample.mdx b/ui-kit/react/link/sample.mdx index 3f7e45be6..d7748ae0d 100644 --- a/ui-kit/react/link/sample.mdx +++ b/ui-kit/react/link/sample.mdx @@ -1,4 +1,4 @@ --- title: "React Sample App" url: "https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app" ---- \ No newline at end of file +--- diff --git a/ui-kit/react/localize.mdx b/ui-kit/react/localize.mdx index 45f62ad52..5be7aadb6 100644 --- a/ui-kit/react/localize.mdx +++ b/ui-kit/react/localize.mdx @@ -1,87 +1,79 @@ --- title: "Localization" sidebarTitle: "Localize" +description: "Configure multi-language localization, custom translations, and date/time formatting in CometChat React UI Kit." --- -## **Overview** + -React UI Kit provides **multi-language localization** to **adapt** the UI elements based on the user's preferred language settings. The **CometChatLocalize** class allows developers to: +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Import | `import { CometChatLocalize } from "@cometchat/chat-uikit-react";` | +| Set language | `CometChatLocalize.setCurrentLanguage("fr")` | +| Init with config | `CometChatLocalize.init({ language: "es", fallbackLanguage: "en-US", disableAutoDetection: false })` | +| Add translations | `CometChatLocalize.addTranslation({ "en-US": { "welcome_message": "Welcome!" } })` | +| Supported languages | 19: en-US, en-GB, nl, fr, de, hi, it, ja, ko, pt, ru, es, tr, zh, zh-TW, ms, sv, lt, hu | +| Date formatting | Use `CalendarObject` for custom date/time patterns | +| Source | [GitHub](https://github.com/cometchat/cometchat-uikit-react/blob/v6/src/resources/CometChatLocalize/cometchat-localize.ts) | -* **Automatically detect and apply a language** based on browser/device settings. -* **Manually change the UI language**. -* **Format date and time** based on localization settings. + -The v6 React UI Kit expands support for **multiple languages** and allows developers to define **custom translations**.\ -The localization system now includes **language JSON files**, which store translations, and an **improved CometChatLocalize class**, which handles language detection and formatting. +The `CometChatLocalize` class manages multi-language localization for the UI Kit. It handles automatic language detection, manual language switching, custom translations, and date/time formatting. -*** - -### **Supported Languages** +--- -React UI Kit currently supports **19 languages**: +## Supported Languages -| Language | Code | -| ------------------------ | ------- | -| English (United States) | `en-US` | +| Language | Code | +| --- | --- | +| English (United States) | `en-US` | | English (United Kingdom) | `en-GB` | -| Dutch | `nl` | -| French | `fr` | -| German | `de` | -| Hindi | `hi` | -| Italian | `it` | -| Japanese | `ja` | -| Korean | `ko` | -| Portuguese | `pt` | -| Russian | `ru` | -| Spanish | `es` | -| Turkish | `tr` | -| Chinese | `zh` | -| Chinese (Traditional) | `zh-TW` | -| Malay | `ms` | -| Swedish | `sv` | -| Lithuanian | `lt` | -| Hungarian | `hu` | - -🔗 **View JSON files for all supported languages** in the GitHub repository:\ -➡ [Language JSON Files](https://github.com/cometchat/cometchat-uikit-react/tree/v6/src/resources/CometChatLocalize/resources) - -*** - -## **CometChatLocalize** - -The `CometChatLocalize` class provides methods for managing localization in the UI Kit. - -🔗 **View full class file in the GitHub repository:**\ -➡ [CometChatLocalize](https://github.com/cometchat/cometchat-uikit-react/blob/v6/src/resources/CometChatLocalize/cometchat-localize.ts) - -*** - -### **LocalizationSettings** - -The `LocalizationSettings` interface defines various **localization settings** for an application or component. It allows developers to configure the language, translations, time zone, and calendar formatting while providing options for automatic detection and missing key handling. - -| Property | Type | Description | -| ----------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------- | -| `language` | `string` | The language code (e.g., `"en"`, `"fr"`) for the current localization. | -| `translationsForLanguage` | `{ [key: string]: any }` | An object containing key-value pairs for translations in the current language. | -| `disableAutoDetection` | `boolean` | Disables automatic language detection based on the browser or device settings. | -| `fallbackLanguage` | `string` | The **fallback language code** to use if the primary language is not available. | -| `disableDateTimeLocalization` | `boolean` | Disables localization for **date and time values**, forcing the default format. | -| `timezone` | `string` | The **timezone** used for date and time formatting (e.g., `"America/New_York"`, `"Europe/London"`). | -| `calendarObject` | `CalendarObject` | A **custom calendar format** using `CalendarObject` to define localized date and time formatting. | -| `missingKeyHandler` | `(key: string) => string` | A function that **handles missing translation keys**, allowing custom error handling or fallbacks. | - -*** - -**Example** - -```javascript +| Dutch | `nl` | +| French | `fr` | +| German | `de` | +| Hindi | `hi` | +| Italian | `it` | +| Japanese | `ja` | +| Korean | `ko` | +| Portuguese | `pt` | +| Russian | `ru` | +| Spanish | `es` | +| Turkish | `tr` | +| Chinese | `zh` | +| Chinese (Traditional) | `zh-TW` | +| Malay | `ms` | +| Swedish | `sv` | +| Lithuanian | `lt` | +| Hungarian | `hu` | + +[Language JSON files on GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/src/resources/CometChatLocalize/resources) + +--- + +## LocalizationSettings + +Configuration interface for `CometChatLocalize.init()`. + +| Property | Type | Description | +| --- | --- | --- | +| `language` | `string` | Language code (e.g., `"en"`, `"fr"`) for the current localization | +| `translationsForLanguage` | `{ [key: string]: any }` | Key-value pairs for translations in the current language | +| `disableAutoDetection` | `boolean` | Disables automatic language detection based on browser/device settings | +| `fallbackLanguage` | `string` | Fallback language code if the primary language is not available | +| `disableDateTimeLocalization` | `boolean` | Disables localization for date and time values, forcing the default format | +| `timezone` | `string` | Timezone for date and time formatting (e.g., `"America/New_York"`, `"Europe/London"`) | +| `calendarObject` | `CalendarObject` | Custom calendar format for localized date and time formatting | +| `missingKeyHandler` | `(key: string) => void` | Handles missing translation keys with custom error handling or fallbacks | + + +```javascript lines import { CometChatLocalize } from "@cometchat/chat-uikit-react"; -import { CalendarObject } from "./CalendarObject"; +import { CalendarObject } from "@cometchat/chat-uikit-react"; CometChatLocalize.init({ - language: "es", // Default language set to Spanish - fallbackLanguage: "en-US", // Use English if the preferred language is not available + language: "es", + fallbackLanguage: "en-US", translationsForLanguage: { "es": { "welcome_message": "¡Bienvenido a CometChat!", @@ -92,9 +84,9 @@ CometChatLocalize.init({ "logout_message": "Vous vous êtes déconnecté avec succès." } }, - disableAutoDetection: false, // Allow automatic detection of browser/device language - disableDateTimeLocalization: false, // Enable localization for date and time - timezone: "Europe/Madrid", // Set time zone for date and time formatting + disableAutoDetection: false, + disableDateTimeLocalization: false, + timezone: "Europe/Madrid", calendarObject: new CalendarObject({ today: "[Hoy a las] hh:mm A", yesterday: "[Ayer a las] hh:mm A", @@ -107,83 +99,62 @@ CometChatLocalize.init({ hours: "%d horas atrás", } }), - missingKeyHandler: (key) => `🔍 Missing translation for: ${key}`, // Custom handler for missing translations + missingKeyHandler: (key) => `Missing translation for: ${key}`, }); ``` -*** +--- -### **CalendarObject** +## CalendarObject -The `CalendarObject` class defines customizable formatting for date and time representation. It allows you to format dates based on whether they are today, yesterday, last week, or other days. It also supports relative time formatting for minutes and hours. +Defines customizable formatting for date and time representation. Supports relative time formatting for minutes and hours. -Notice - -Changing this format will **globally update** the date and time representation wherever it is used in the component.\ -However, if a **component-specific** `CalendarObject` is provided, it will take **higher precedence** over the global settings. - +Changing this format globally updates the date and time representation wherever it is used. If a component-specific `CalendarObject` is provided, it takes higher precedence over the global settings. -| Property | Type | Description | -| ---------------------- | -------- | ----------------------------------------------------------------------------------------------- | -| `today` | `string` | Custom formatting for dates that fall on the same day. Example: `"Today at hh:mm A"` | -| `yesterday` | `string` | Custom formatting for dates that fall on the previous day. Example: `"Yesterday at hh:mm A"` | -| `lastWeek` | `string` | Custom formatting for dates within the last 7 days. Example: `"Last week on dddd"` | -| `otherDays` | `string` | Custom formatting for dates that do not fit other categories. Example: `"DD MMM YYYY, hh:mm A"` | -| `relativeTime` | `object` | Custom formatting for relative time expressions (e.g., "2 hours ago"). | -| `relativeTime.minute` | `string` | Formatting for a single minute. Example: `"%d minute ago"` | -| `relativeTime.minutes` | `string` | Formatting for multiple minutes. Example: `"%d minutes ago"` | -| `relativeTime.hour` | `string` | Formatting for a single hour. Example: `"%d hour ago"` | -| `relativeTime.hours` | `string` | Formatting for multiple hours. Example: `"%d hours ago"` | - -*** - -**Example** - -```javascript -import { CometChatLocalize } from "@cometchat/chat-uikit-react"; -import { CalendarObject } from "./CalendarObject"; - +| Property | Type | Description | +| --- | --- | --- | +| `today` | `string` | Format for dates on the same day. Example: `"Today at hh:mm A"` | +| `yesterday` | `string` | Format for dates on the previous day. Example: `"Yesterday at hh:mm A"` | +| `lastWeek` | `string` | Format for dates within the last 7 days. Example: `"Last week on dddd"` | +| `otherDays` | `string` | Format for dates that do not fit other categories. Example: `"DD MMM YYYY, hh:mm A"` | +| `relativeTime` | `object` | Custom formatting for relative time expressions | +| `relativeTime.minute` | `string` | Single minute format. Example: `"%d minute ago"` | +| `relativeTime.minutes` | `string` | Multiple minutes format. Example: `"%d minutes ago"` | +| `relativeTime.hour` | `string` | Single hour format. Example: `"%d hour ago"` | +| `relativeTime.hours` | `string` | Multiple hours format. Example: `"%d hours ago"` | + +```javascript lines new CalendarObject({ - today: "[Hoy a las] hh:mm A", - yesterday: "[Ayer a las] hh:mm A", - lastWeek: "[Última semana el] dddd", - otherDays: "DD MMM YYYY, hh:mm A", - relativeTime: { - minute: "%d minuto atrás", - minutes: "%d minutos atrás", - hour: "%d hora atrás", - hours: "%d horas atrás", - } - }) + today: "[Hoy a las] hh:mm A", + yesterday: "[Ayer a las] hh:mm A", + lastWeek: "[Última semana el] dddd", + otherDays: "DD MMM YYYY, hh:mm A", + relativeTime: { + minute: "%d minuto atrás", + minutes: "%d minutos atrás", + hour: "%d hora atrás", + hours: "%d horas atrás", + } +}) ``` -*** +--- -### **Component Guide** +## Component Guide -Note - -The translation configurations mentioned in this section are to be defined inside the -ComeChat's init() method callback. +The translation configurations in this section are to be defined inside the [CometChat's init() method callback](/ui-kit/react/react-js-integration#step-3:-initialize-cometchat-ui-kit). -#### Report Message +### Report Message -To add translations for any flag reason, a key in the form of `flag_message_reason_id_{reason_id}` is to be defined with the translated strings to be displayed for that `reason_id` in the UI. The translations for `flag_message_reason_id_spam`, `flag_message_reason_id_sexual`, `flag_message_reason_id_harassment` are present by default. +To add translations for any flag reason, define a key in the form `flag_message_reason_id_{reason_id}` with the translated strings. Translations for `flag_message_reason_id_spam`, `flag_message_reason_id_sexual`, `flag_message_reason_id_harassment` are present by default. The reason name is displayed when the required translation is not found. -**Usage** -* Define translations for custom flag message reasons. -* The reason name would be displayed when the required translation is not found. - -**Example** - -```javascript +```javascript lines import { CometChatLocalize } from "@cometchat/chat-uikit-react"; -// Add translations for flag reason keys for the required languages CometChatLocalize.addTranslation({ "en-GB": { "flag_message_reason_id_dislike": "I just don't like it", @@ -194,20 +165,13 @@ CometChatLocalize.addTranslation({ }); ``` -#### Mention All - -To add translations for a custom `mentionAllLabel`, a key in the form of `message_composer_mention_{label}` is to be defined with the translated strings to be displayed for that label in the UI. The translations for `message_composer_mention_all` is present by default. - -**Usage** -* Define translations for custom mentionAllLabel. -* Helps customize the `@all` label used in the app while mentioning all group members. +### Mention All -**Example** +To add translations for a custom `mentionAllLabel`, define a key in the form `message_composer_mention_{label}`. The translation for `message_composer_mention_all` is present by default. -```javascript +```javascript lines import { CometChatLocalize } from "@cometchat/chat-uikit-react"; -// Add translations for mentionAllLabel for the required languages CometChatLocalize.addTranslation({ "en-GB": { "message_composer_mention_channel": "channel", @@ -218,169 +182,131 @@ CometChatLocalize.addTranslation({ }); ``` -*** - -### **Methods** - -#### Initialize CometChatLocalize - -This method initializes the localization system with default values and optional configurations. +--- -**Usage** +## Methods -* Set the default language, timezone, and fallback settings. -* Define a custom calendar format if required. -* Customize how missing keys are handled. +### init -**Example** +Initializes the localization system with default values and optional configurations. -```javascript +```javascript lines import { CometChatLocalize } from "@cometchat/chat-uikit-react"; -// Initialize localization settings CometChatLocalize.init({ - language: "es", // Default language: Spanish - fallbackLanguage: "en-US", // Fallback if translation is missing - disableAutoDetection: false, // Enable browser language detection + language: "es", + fallbackLanguage: "en-US", + disableAutoDetection: false, timezone: "Europe/Madrid", missingKeyHandler: (key) => `Missing translation: ${key}`, }); ``` -*** - -#### Get Browser Language +### getBrowserLanguage -This method detects the language set in the user's browser or device settings. +Detects the language set in the user's browser or device settings. -**Usage** - -* Automatically set the app’s language based on the user’s browser settings. -* Helps in making the UI multilingual without requiring user input. - -**Example** - -```javascript +```javascript lines const userLang = CometChatLocalize.getBrowserLanguage(); console.log(userLang); ``` -*** - -#### Get Localized String +### getLocalizedString -This method fetches localized text based on the current language. +Fetches localized text based on the current language. -**Usage** - -* Retrieve translations dynamically without hardcoding values in multiple languages. -* Useful for UI elements, buttons, alerts, and system messages. - -**Example** - -```javascript +```javascript lines const translatedText = CometChatLocalize.getLocalizedString("welcome_message"); ``` -*** - -#### Get Current Language - -This method returns the currently set language for the UI Kit. +### getCurrentLanguage -**Usage** +Returns the currently set language for the UI Kit. -* Useful to debug and display the currently active language. -* Helps when dynamically switching between languages. - -**Example** - -```javascript +```javascript lines console.log(CometChatLocalize.getCurrentLanguage()); ``` -*** - -#### Get Default Language - -This method returns the system-preferred language. +### getDefaultLanguage -**Usage** +Returns the system-preferred language. If `disableAutoDetection` is enabled, returns the fallback language. Otherwise returns the browser's preferred language. -* If disableAutoDetection is enabled, the method returns the fallback language. -* If auto-detection is enabled, it returns the browser's preferred language. - -**Example** - -```javascript +```javascript lines console.log(CometChatLocalize.getDefaultLanguage()); ``` -*** - -#### Set Current Language - -This method updates the language at runtime without reloading the application. - -**Usage** +### setCurrentLanguage -* Allow users to change the language via a settings menu. -* Ensure that UI elements are updated instantly after changing the language. +Updates the language at runtime without reloading the application. -**Example** - -```javascript +```javascript lines CometChatLocalize.setCurrentLanguage("fr"); ``` -*** +### addTranslation + +Adds custom translations to the existing ones dynamically. New translations are merged into the existing localization data. -#### Add Custom Translations +```javascript lines +CometChatLocalize.addTranslation({ + "en-US": { "welcome_message": "Welcome to CometChat!" } +}); +``` -This method allows you to add custom translations to the existing ones dynamically. It ensures that new translations are merged into the existing localization data. +### formatDate -**Usage** +Formats a Unix timestamp (seconds) based on a `CalendarObject` configuration. Uses the timezone set via `init()`. -* You can define custom translation keys and override the existing translations. -* You can add new languages to the existing translations. -* Useful when you want to support additional words or phrases not present in the default language files. +| Parameter | Type | Description | +| --- | --- | --- | +| `timestamp` | `number` | Unix timestamp in seconds | +| `calendarObject` | `CalendarObject` | Calendar configuration for formatting | -**Example** +Returns a formatted date `string`. -```javascript -CometChatLocalize.addTranslation({ - "en-US": { "welcome_message": "Welcome to CometChat!" } -}); +```javascript lines +import { CometChatLocalize } from "@cometchat/chat-uikit-react"; +import { CalendarObject } from "@cometchat/chat-uikit-react"; + +const formatted = CometChatLocalize.formatDate(1700000000, new CalendarObject({ + today: "hh:mm A", + yesterday: "[Yesterday]", + lastWeek: "dddd", + otherDays: "DD MMM YYYY, hh:mm A" +})); ``` -*** +### getDateLocaleLanguage + +Returns the language code used for date localization. If `disableDateTimeLocalization` is `true`, returns `"en-US"`. Otherwise returns the current language. -#### **Customisation** +```javascript lines +const dateLang = CometChatLocalize.getDateLocaleLanguage(); +``` -CometChat UI Kit provides **flexible customization options** for date/time format. Users can configure **global settings** using `CometChatLocalize.init()` or pass a `CalendarObject` directly to individual components for **component-specific** customization. +--- -* **Global Configuration:** When settings are provided in `CometChatLocalize.init()`, all UI components will automatically use the configured date/time formats. -* **Component-Specific Configuration:** If a `CalendarObject` is passed to a component, it **overrides** the global settings and applies only to that specific instance. +## Customization -**Global Configuration Example** +### Global Configuration -To apply a **custom date format** globally across the whole UI Kit. +Apply a custom date format globally across the whole UI Kit via `CometChatLocalize.init()`: -```php +```javascript lines CometChatLocalize.init({ - calendarObject:new CalendarObject({ - today: " hh:mm A", - yesterday: "[Yesterday], + calendarObject: new CalendarObject({ + today: "hh:mm A", + yesterday: "[Yesterday]", otherDays: "DD MMM YYYY, hh:mm A" }) }); ``` -**Component-Specific Customization Example** +### Component-Specific Configuration -To apply a **custom date format** only within a specific component. +Apply a custom date format only within a specific component. Component-level `CalendarObject` overrides the global settings. -```csharp +```tsx lines ``` -*** \ No newline at end of file diff --git a/ui-kit/react/mentions-formatter-guide.mdx b/ui-kit/react/mentions-formatter-guide.mdx index f5e8d6860..0a20c3540 100644 --- a/ui-kit/react/mentions-formatter-guide.mdx +++ b/ui-kit/react/mentions-formatter-guide.mdx @@ -1,50 +1,75 @@ --- title: "Mentions Formatter" +description: "Add @mentions with styled tokens, suggestion list, and click handling in CometChat React UI Kit." --- -## Overview + -The `CometChatMentionsFormatter` class is a part of the CometChat UI Kit, a ready-to-use chat UI component library for integrating CometChat into your React applications. This class provides functionality to format mentions within text messages displayed in the chat interface. Mentions allow users to reference other users within a conversation, providing a convenient way to direct messages or involve specific participants. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Key class | `CometChatMentionsFormatter` (extends `CometChatTextFormatter`) | +| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` | +| Purpose | Format @mentions with styled tokens, suggestion list, and click handling for users and group members | +| Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) | +| Related | [Custom Text Formatter](/ui-kit/react/custom-text-formatter-guide) \| [All Guides](/ui-kit/react/guide-overview) | -## Features + -* **Mention Formatting**: Automatically formats mentions within text messages based on provided styles and settings. -* **Customizable Styles**: Allows customization of text styles for mentions, including colors, fonts, and background colors. -* **User and Group Member Mentions**: Supports mentions for both individual users and group members, providing flexibility in communication scenarios. -* **Mention List Generation**: Generates a list of suggested mentions based on user input, facilitating easy selection of recipients during message composition. -* **Mention Click Handling**: Provides a listener interface for handling click events on mentions, enabling custom actions to be performed when a mention is tapped by the user. +`CometChatMentionsFormatter` extends [CometChatTextFormatter](/ui-kit/react/custom-text-formatter-guide) to format @mentions in text messages. It styles mention tokens, generates suggestion lists as users type, and handles click events on rendered mentions. -## Usage +| Capability | Description | +| --- | --- | +| Mention formatting | Auto-formats `<@uid:...>` placeholders into styled tokens | +| Custom styles | Colors, fonts, and backgrounds for mention text | +| User and group mentions | Works with both individual users and group members | +| Suggestion list | Generates mention candidates from user input | +| Click handling | Listener interface for tap/click on rendered mentions | + +--- -To integrate the `CometChatMentionsFormatter` class into your application: +## Usage -1. **Initialization**: Create an instance of the `CometChatMentionsFormatter` class and configure it with desired settings, such as mention text styles and limit settings. +### 1. Initialize the formatter -```javascript +```javascript lines import { CometChatMentionsFormatter } from "path-to-your-file"; -// Initialize the formatter const mentionsFormatter = new CometChatMentions(); mentionsFormatter.setCometChatUserGroupMembers(userList); ``` -2. **Initialize the Formatter**: Initialize an instance of the formatter and configure it with any required settings, such as the list of users or groups to mention. +### 2. Format a message -3. **Process Chat Messages**: Once the formatter is initialized, you can process chat messages to format mentions appropriately: +Provide the raw message string containing mention placeholders, then apply the formatter: - * Provide the Unformatted Message: Provide the unformatted message string, including any mention placeholders. +```javascript lines +const unformattedMessage = "<@uid:aliceuid> just shared a photo!"; +const formattedMessage = mentionsFormatter.getFormattedText(unformattedMessage); +// Render formattedMessage in your message component +``` - ```javascript - const unformattedMessage = "<@uid:aliceuid> just shared a photo!"; - ``` +The output contains HTML with styled mentions ready for rendering. - * Apply the Formatter: Apply the formatter to the unformatted message using the `getFormattedText` method. +### 3. Pass to components - ```javascript - const formattedMessage = mentionsFormatter.getFormattedText(unformattedMessage); - // Render the `formattedMessage` in your message component - ``` +Use the `textFormatters` prop on [CometChatMessageList](/ui-kit/react/message-list), [CometChatMessageComposer](/ui-kit/react/message-composer), or [CometChatConversations](/ui-kit/react/conversations). - The `formattedMessage` now contains HTML with styled mentions, ready to be inserted into your message component for display. +--- -Below is an example demonstrating how to use the `CometChatMentionsFormatter` class in components such as [CometChatConversations](/ui-kit/react/conversations), [CometChatMessageList](/ui-kit/react/message-list), [CometChatMessageComposer](/ui-kit/react/message-composer). +## Next Steps + + + + Build custom inline text patterns. + + + Render real-time message threads. + + + Browse all feature and formatter guides. + + + Full working sample application on GitHub. + + diff --git a/ui-kit/react/message-composer.mdx b/ui-kit/react/message-composer.mdx index 67249e000..ce6661ec5 100644 --- a/ui-kit/react/message-composer.mdx +++ b/ui-kit/react/message-composer.mdx @@ -1,922 +1,940 @@ --- title: "Message Composer" +description: "Rich text input for composing and sending text, media, attachments, mentions, voice notes, and custom messages." --- + +```json +{ + "component": "CometChatMessageComposer", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatMessageComposer } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Rich text input for composing and sending text, media, attachments, mentions, voice notes, and custom messages.", + "cssRootClass": ".cometchat-message-composer", + "primaryOutput": { + "prop": "onSendButtonClick", + "type": "(message: CometChat.BaseMessage, previewMessageMode?: PreviewMessageMode) => void" + }, + "props": { + "data": { + "user": { "type": "CometChat.User", "default": "undefined" }, + "group": { "type": "CometChat.Group", "default": "undefined" }, + "parentMessageId": { "type": "number", "default": "undefined" }, + "initialComposerText": { "type": "string", "default": "\"\"" }, + "placeholderText": { "type": "string", "default": "\"\"" } + }, + "callbacks": { + "onSendButtonClick": "(message: CometChat.BaseMessage, previewMessageMode?: PreviewMessageMode) => void", + "onTextChange": "(text: string) => void", + "onError": "((error: CometChat.CometChatException) => void) | null" + }, + "visibility": { + "hideImageAttachmentOption": { "type": "boolean", "default": false }, + "hideVideoAttachmentOption": { "type": "boolean", "default": false }, + "hideAudioAttachmentOption": { "type": "boolean", "default": false }, + "hideFileAttachmentOption": { "type": "boolean", "default": false }, + "hidePollsOption": { "type": "boolean", "default": false }, + "hideCollaborativeDocumentOption": { "type": "boolean", "default": false }, + "hideCollaborativeWhiteboardOption": { "type": "boolean", "default": false }, + "hideAttachmentButton": { "type": "boolean", "default": false }, + "hideVoiceRecordingButton": { "type": "boolean", "default": false }, + "hideEmojiKeyboardButton": { "type": "boolean", "default": false }, + "hideStickersButton": { "type": "boolean", "default": false }, + "hideSendButton": { "type": "boolean", "default": false }, + "showScrollbar": { "type": "boolean", "default": false } + }, + "behavior": { + "disableTypingEvents": { "type": "boolean", "default": false }, + "disableMentions": { "type": "boolean", "default": false }, + "disableMentionAll": { "type": "boolean", "default": false }, + "mentionAllLabel": { "type": "string", "default": "\"all\"" }, + "enterKeyBehavior": { "type": "EnterKeyBehavior", "default": "EnterKeyBehavior.SendMessage" }, + "disableSoundForMessage": { "type": "boolean", "default": false }, + "customSoundForMessage": { "type": "string", "default": "undefined" } + }, + "mentions": { + "mentionsUsersRequestBuilder": "CometChat.UsersRequestBuilder", + "mentionsGroupMembersRequestBuilder": "CometChat.GroupMembersRequestBuilder" + }, + "viewSlots": { + "attachmentOptions": "CometChatMessageComposerAction[]", + "auxiliaryButtonView": "JSX.Element", + "sendButtonView": "JSX.Element", + "headerView": "JSX.Element" + }, + "formatting": { + "textFormatters": { "type": "CometChatTextFormatter[]", "default": "default formatters" } + } + }, + "events": [ + { "name": "CometChatMessageEvents.ccMessageSent", "payload": "IMessages" }, + { "name": "CometChatMessageEvents.ccMessageEdited", "payload": "IMessages" }, + { "name": "CometChatMessageEvents.ccReplyToMessage", "payload": "IMessages" } + ], + "sdkListeners": [], + "types": { + "EnterKeyBehavior": { "SendMessage": "sendMessage", "NewLine": "newLine", "None": "none" }, + "PreviewMessageMode": { "edit": 0, "none": 1 } + } +} +``` + -## Overview +## Where It Fits -MessageComposer is a Component that enables users to write and send a variety of messages, including text, image, video, and custom messages. +`CometChatMessageComposer` provides a rich text input with attachment, emoji, voice recording, sticker, and send controls. Wire it alongside `CometChatMessageHeader` and `CometChatMessageList` to build a standard chat view. -Features such as **Attachments**, and **Message Editing** are also supported by it. +```tsx lines +import { useState, useEffect } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatView() { + const [chatUser, setChatUser] = useState(); + + useEffect(() => { + CometChat.getUser("uid").then((user) => setChatUser(user)); + }, []); + + return chatUser ? ( +
+ + + +
+ ) : null; +} +``` -## Usage - -### Integration +--- -The following code snippet illustrates how you can directly incorporate the MessageComposer component into your app. +## Minimal Render - - -```tsx -import React from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function MessageComposerDemo() { + const [chatUser, setChatUser] = useState(); -export function MessageComposerDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); + useEffect(() => { + CometChat.getUser("uid").then((user) => setChatUser(user)); }, []); - return chatUser ? ( -
- -
- ) : null; + return chatUser ? : null; } + +export default MessageComposerDemo; ``` -
+Root CSS class: `.cometchat-message-composer` + +--- + +## Actions and Events + +### Callback Props + +#### onSendButtonClick - -```tsx -import { MessageComposerDemo } from "./MessageComposerDemo"; +Fires when the send button is clicked. Overrides the default send behavior. -export default function App() { +```tsx lines +import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function ComposerWithCustomSend() { return ( -
-
- -
-
+ { + console.log("Custom send:", message); + }} + /> ); } ``` -
+#### onTextChange -
+Fires as the user types in the composer input. -### Actions +```tsx lines +import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +function ComposerWithTextTracking() { + return ( + { + console.log("Text changed:", text); + }} + /> + ); +} +``` -##### 1. OnSendButtonClick +#### onError -The `OnSendButtonClick` event gets activated when the send message button is clicked. It has a predefined function of sending messages entered in the composer `EditText`. However, you can overide this action with the following code snippet. +Fires on internal errors. - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export function MessageComposerDemo() { - const [chatUser, setChatUser] = React.useState(); +function ComposerWithError() { + return ( + { + console.error("Composer error:", error); + }} + /> + ); +} +``` - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +### Global UI Events - function handleSendButtonClick(message: CometChat.BaseMessage): void { - console.log("your custom on send buttonclick action"); - } +| Event | Fires when | Payload | +| --- | --- | --- | +| `CometChatMessageEvents.ccMessageSent` | A message is sent | `IMessages` | +| `CometChatMessageEvents.ccMessageEdited` | A message is edited | `IMessages` | +| `CometChatMessageEvents.ccReplyToMessage` | User replies to a message | `IMessages` | - return chatUser ? ( -
- -
- ) : null; +```tsx lines +import { useEffect } from "react"; +import { CometChatMessageEvents } from "@cometchat/chat-uikit-react"; + +function useComposerEvents() { + useEffect(() => { + const sentSub = CometChatMessageEvents.ccMessageSent.subscribe( + (data) => console.log("Sent:", data) + ); + const editedSub = CometChatMessageEvents.ccMessageEdited.subscribe( + (data) => console.log("Edited:", data) + ); + + return () => { + sentSub?.unsubscribe(); + editedSub?.unsubscribe(); + }; + }, []); } ``` -
+### SDK Events (Real-Time, Automatic) -
+The component internally handles typing indicators and message sending. No manual SDK listener attachment needed. -##### 2. onError +--- -This action doesn't change the behavior of the component but rather listens for any errors that occur in the MessageList component. +## Custom View Slots - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +| Slot | Type | Replaces | +| --- | --- | --- | +| `attachmentOptions` | `CometChatMessageComposerAction[]` | Default attachment options list | +| `auxiliaryButtonView` | `JSX.Element` | Sticker and AI button area | +| `sendButtonView` | `JSX.Element` | Send button | +| `headerView` | `JSX.Element` | Area above the composer input | -export function MessageComposerDemo() { - const [chatUser, setChatUser] = React.useState(); +### attachmentOptions - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +Override the default attachment options. - function handleError(error: CometChat.CometChatException) { - throw new Error("your custom error action"); - } + + + - return chatUser ? ( -
- -
- ) : null; +```tsx lines +import { + CometChatMessageComposer, + CometChatMessageComposerAction, +} from "@cometchat/chat-uikit-react"; + +function ComposerCustomAttachments() { + return ( + + ); +} +``` + +### auxiliaryButtonView + +Replace the sticker and AI button area. + + + + + +```tsx lines +import { + CometChatMessageComposer, + CometChatButton, +} from "@cometchat/chat-uikit-react"; + +function ComposerCustomAuxiliary() { + return ( + {}} /> + } + /> + ); } ``` +### sendButtonView + +Replace the send button. + + + + + + + +```tsx lines +import { + CometChatMessageComposer, + CometChatButton, +} from "@cometchat/chat-uikit-react"; + +function ComposerCustomSend() { + return ( + {}} /> + } + /> + ); +} +``` + +```css lines +.cometchat-message-composer div:not([class]) .message-composer__send-button .cometchat-button { + background: #edeafa; +} +.cometchat-message-composer div:not([class]) .message-composer__send-button .cometchat-button__icon { + background: #6852d6; +} +``` + -##### 3. onTextChange +### headerView + +Custom view above the composer input. -This event is triggered as the user starts typing in the Message Composer. + + + - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; + +```tsx lines import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; -export function MessageComposerDemo() { - const [chatUser, setChatUser] = React.useState(); - - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +function ComposerWithHeader() { + return ( + +
+
+ User has paused their notifications +
+
+ } + /> + ); +} +``` +
+ +```css lines +.cometchat-message-composer .message-composer__header-view { + display: flex; + align-items: center; + gap: 8px; + width: 100%; +} - function handleTextChange(text: string) { - console.log("onTextChange", text); - } +.cometchat-message-composer__header { + background: #dcd7f6; + border-radius: var(--cometchat-radius-max, 1000px); + padding: var(--cometchat-padding-2) var(--cometchat-padding-5); +} - return chatUser ? ( -
- -
- ) : null; +.message-composer__header-view-text { + color: var(--cometchat-text-color-primary); + font: var(--cometchat-font-body-regular); } ``` -
-
-##### 4. Custom Mentions Request Builders +--- -You can customize how mentioned users and group members are fetched by providing custom request builders. +## Common Patterns - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +### Thread composer + +```tsx lines import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; -export function MessageComposerDemo() { - const [chatUser, setChatUser] = React.useState(); - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - }, []); +function ThreadComposer() { + return ( + + ); +} +``` - // Custom Users Request Builder for mentions - const mentionsUsersRequestBuilder = new CometChat.UsersRequestBuilder() - .setLimit(10) - .setSearchKeyword("") - .setRoles(["default", "moderator"]); +### Minimal composer — text only - // Custom Group Members Request Builder for group mentions - const mentionsGroupMembersRequestBuilder = new CometChat.GroupMembersRequestBuilder("guid") - .setLimit(15) - .setSearchKeyword("") - .setScopes(["admin", "moderator", "participant"]); +```tsx lines +import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; - return chatUser ? ( -
- {/* For user chat with custom users mentions */} - - - {/* For group chat with custom group members mentions */} - {chatGroup && ( - - )} -
- ) : null; +function MinimalComposer() { + return ( + + ); } ``` -
+### Enter key adds new line -
+```tsx lines +import { CometChatMessageComposer, EnterKeyBehavior } from "@cometchat/chat-uikit-react"; -*** +function NewLineComposer() { + return ( + + ); +} +``` -### Filters +### Pre-filled text -MessageComposer component does not have any available filters. +```tsx lines +import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; -*** +function PrefilledComposer() { + return ( + + ); +} +``` -### Events +--- -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +## CSS Architecture -The list of events emitted by the Messages component is as follows. +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: -| Event | Description | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| **ccMessageEdited** | Triggers whenever a loggedIn user edits any message from the list of messages .it will have three states such as: inProgress, success and error. | -| **ccReplyToMessage** | Triggers whenever a loggedIn user replies to any message from the list of messages .it will have three states such as: inProgress, success and error. | -| **ccMessageSent** | Triggers whenever a loggedIn user sends any message, it will have three states such as: inProgress, success and error. | +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-message-composer`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-message-composer` descendant selectors. -Adding `CometChatMessageEvents` Listener's +### Key Selectors - - -```js -import { CometChatMessageEvents } from "@cometchat/chat-uikit-react"; +| Target | Selector | +| --- | --- | +| Root | `.cometchat-message-composer` | +| Send button | `.cometchat-message-composer__send-button` | +| Send button active | `.cometchat-message-composer__send-button-active` | +| Sticker button popover | `.cometchat-message-composer__auxilary-button-view-sticker-button .cometchat-popover__content` | +| Emoji keyboard popover | `.cometchat-message-composer__emoji-keyboard-button .cometchat-popover__content` | +| Attachment popover | `.cometchat-message-composer__secondary-button-view-attachment-button .cometchat-popover__content` | +| Voice recording popover | `.cometchat-message-composer__voice-recording-button .cometchat-popover__content` | +| Header area | `.cometchat-message-composer__header` | -const ccMessageEdited = CometChatMessageEvents.ccMessageEdited.subscribe(() => { - // Your Code -}); +### Customization Matrix -const ccReplyToMessage = CometChatMessageEvents.ccReplyToMessage.subscribe(() => { - // Your Code -}); +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override send behavior | Component props | `onSendButtonClick` | `onSendButtonClick={(msg) => customSend(msg)}` | +| Track text input | Component props | `onTextChange` | `onTextChange={(text) => track(text)}` | +| Toggle visibility | Component props | `hide` boolean props | `hideAttachmentButton={true}` | +| Custom attachments | Component props | `attachmentOptions` | `attachmentOptions={[new CometChatMessageComposerAction(...)]}` | +| Replace UI sections | Component props | View slot props | `sendButtonView={
...
}` | +| Change Enter key behavior | Component props | `enterKeyBehavior` | `enterKeyBehavior={EnterKeyBehavior.NewLine}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-message-composer` class | `.cometchat-message-composer__send-button { background: blue; }` | -const ccMessageSent = CometChatMessageEvents.ccMessageSent.subscribe(() => { - // Your Code -}); -``` +--- -
+## Accessibility -
+The text input is auto-focused and supports standard keyboard shortcuts. The send button activates on Enter (configurable via `enterKeyBehavior`). Attachment, emoji, sticker, and voice recording buttons are keyboard-focusable and activate on Enter/Space. The mention suggestions list is keyboard-navigable with arrow keys. -*** +--- -Removing `CometChatMessageEvents` Listener's +--- - - -```js -ccMessageEdited?.unsubscribe(); -ccReplyToMessage?.unsubscribe(); -ccMessageSent?.unsubscribe(); -``` +## Props - +All props are optional. Sorted alphabetically. - +### attachmentOptions -*** +Custom attachment options list. -## Customization +| | | +| --- | --- | +| Type | `CometChatMessageComposerAction[]` | +| Default | `undefined` | -To fit your app's design requirements, you can customize the appearance of the MessageComposer component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. +--- -### Style +### auxiliaryButtonView -To modify the styling, you can customise the css of MessageComposer Component. +Custom JSX replacing the sticker and AI button area. -**Example** +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in sticker/AI buttons | - - - +--- - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +### customSoundForMessage -; -``` +URL to a custom audio file for outgoing message notifications. - +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | - -```css -.cometchat-message-composer .cometchat-message-composer__input { - font-family: "SF Pro"; -} +--- -.cometchat-message-composer .cometchat-button .cometchat-button__icon { - background: #f19fa1; -} +### disableMentionAll -.cometchat-message-composer .cometchat-message-composer__send-button { - background: #e5484d; +Controls whether group mentions like @all appear in suggestions. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### disableMentions + +Disables the mentions functionality. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### disableSoundForMessage + +Disables sound for outgoing messages. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### disableTypingEvents + +Disables the typing indicator for this composer. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### enterKeyBehavior + +Determines Enter key behavior. + +| | | +| --- | --- | +| Type | `EnterKeyBehavior` | +| Default | `EnterKeyBehavior.SendMessage` | + +```ts lines +enum EnterKeyBehavior { + SendMessage = "sendMessage", + NewLine = "newLine", + None = "none", } ``` - +--- - +### group -*** +The recipient group for the composer. -### Functionality +| | | +| --- | --- | +| Type | `CometChat.Group` | +| Default | `undefined` | -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. +--- - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +### headerView -; -``` +Custom component displayed above the composer input. - +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | - +--- -Below is a list of customizations along with corresponding code snippets - -| Property | Description | Code | -| --------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------- | -| **Initial Composer Text** | The initial text pre-filled in the message input when the component mounts. | `initialComposerText="Hello"` | -| **Disable Typing Events** | Disables the typing indicator for the current message composer. | `disableTypingEvents={true}` | -| **Disable Mentions** | Disables the mentions functionality in the message composer. | `disableMentions={true}` | -| **Disable Mention All** | Controls whether group mentions like @all appear in suggestions. | `disableMentionAll={true}` | -| **Mention All Label** | Allows setting a custom alias label for group mentions (@channel, @everyone, etc.). | `mentionAllLabel="all"` | -| **Mentions Users Request Builder** | Provides a custom UsersRequestBuilder to control how the mentioned users list is fetched. | `mentionsUsersRequestBuilder={usersRequestBuilder}` | -| **Mentions Group Members Request Builder** | Provides a custom GroupMembersRequestBuilder to customize how mentioned group members are retrieved. | `mentionsGroupMembersRequestBuilder={groupMembersRequestBuilder}` | -| **Hide Image Attachment Option** | Hides the image attachment option in the message composer. | `hideImageAttachmentOption={true}` | -| **Hide Video Attachment Option** | Hides the video attachment option in the message composer. | `hideVideoAttachmentOption={true}` | -| **Hide Audio Attachment Option** | Hides the audio attachment option in the message composer. | `hideAudioAttachmentOption={true}` | -| **Hide File Attachment Option** | Hides the file attachment option in the message composer. | `hideFileAttachmentOption={true}` | -| **Hide Polls Option** | Hides the polls option in the message composer. | `hidePollsOption={true}` | -| **Hide Collaborative Document** | Hides the collaborative document option in the message composer. | `hideCollaborativeDocumentOption={true}` | -| **Hide Collaborative Whiteboard** | Hides the collaborative whiteboard option in the message composer. | `hideCollaborativeWhiteboardOption={true}` | -| **Hide Attachment Button** | Hides the attachment button in the message composer. | `hideAttachmentButton={true}` | -| **Hide Voice Recording Button** | Hides the voice recording button in the message composer. | `hideVoiceRecordingButton={true}` | -| **Hide Emoji Keyboard Button** | Hides the emoji keyboard button in the message composer. | `hideEmojiKeyboardButton={true}` | -| **Hide Stickers Button** | Hides the stickers button in the message composer. | `hideStickersButton={true}` | -| **Hide Send Button** | Hides the send button in the message composer. | `hideSendButton={true}` | -| **Show Scrollbar** | Controls the visibility of the scrollbar in the composer. | `showScrollbar={true}` | -| **User** | Specifies the recipient of the message (user object). | `user={chatUser}` | -| **Group** | Specifies the group to send messages to. Used if the `user` prop is not provided. | `group={chatGroup}` | -| **Parent Message ID** | Specifies the ID of the parent message for threading or replying to a specific message. | `parentMessageId={12345}` | -| **Enter Key Behavior** | Determines the behavior of the Enter key (e.g., send message or add a new line). | `enterKeyBehavior={EnterKeyBehavior.SendMessage}` | -| **Disable Sound for Message** | Disables sound for incoming messages. | `disableSoundForMessage={true}` | -| **Custom Sound for Message** | Specifies a custom audio sound for incoming messages. | `customSoundForMessage="sound.mp3"` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -*** - -#### AttachmentOptions - -By using `attachmentOptions`, you can set a list of custom `MessageComposerActions` for the MessageComposer Component. This will override the existing list of `MessageComposerActions`. - -Shown below is the default chat interface. +### hideAttachmentButton - - - +Hides the entire attachment button. -The customized chat interface is displayed below. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - - - +--- -Use the following code to achieve the customization shown above. +### hideAudioAttachmentOption - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatMessageComposer, - CometChatMessageComposerAction, -} from "@cometchat/chat-uikit-react"; +Hides the audio attachment option. -function getAttachments() { - return [ - new CometChatMessageComposerAction({ - id: "custom1", - title: "Custom Option 1", - iconURL: "Icon URL", - }), - new CometChatMessageComposerAction({ - id: "custom2", - title: "Custom Option 2", - iconURL: "Icon URL", - }), - new CometChatMessageComposerAction({ - id: "custom3", - title: "Custom Option 3", - iconURL: "Icon URL", - }), - new CometChatMessageComposerAction({ - id: "custom4", - title: "Custom Option 4", - iconURL: "Icon URL", - }), - ]; -} +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -; -``` +--- - +### hideCollaborativeDocumentOption - -```css -.cometchat-message-composer__secondary-button-view-attachment-button - .cometchat-action-sheet { - border: none; - border-radius: inherit; - background: transparent; - box-shadow: none; - width: 100%; -} +Hides the collaborative document option. -.cometchat-message-composer__secondary-button-view-attachment-button - .cometchat-popover__content - > .cometchat { - border-radius: inherit; -} +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -.cometchat-message-composer__secondary-button-view-attachment-button - .cometchat-popover__content { - height: 240px; -} +--- -.cometchat-message-composer__secondary-button-view-attachment-button - .cometchat-action-sheet__item-icon { - background: #141414; -} -``` +### hideCollaborativeWhiteboardOption - +Hides the collaborative whiteboard option. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -*** +--- -#### AuxiliaryButtonView +### hideEmojiKeyboardButton -You can insert a custom view into the MessageComposer component to add additional functionality using the following method. +Hides the emoji keyboard button. -Please note that the MessageComposer Component utilizes the AuxiliaryButton to provide sticker and AI functionality. Overriding the AuxiliaryButton will subsequently replace the sticker functionality. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Shown below is the default chat interface. +--- - - - +### hideFileAttachmentOption -The customized chat interface is displayed below. +Hides the file attachment option. - - - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Use the following code to achieve the customization shown above. +--- - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatMessageComposer, - IconStyle, - CometChatButton, -} from "@cometchat/chat-uikit-react"; +### hideImageAttachmentOption -const auxiliaryButtonView = ( - { - // logic here - }} - /> -); - -; -``` +Hides the image attachment option. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- -*** +### hidePollsOption -#### SendButtonView +Hides the polls option. -You can set a custom view in place of the already existing send button view. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Shown below is the default chat interface. +--- - - - +### hideSendButton -The customized chat interface is displayed below. +Hides the send button. - - - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Use the following code to achieve the customization shown above. +--- - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatMessageComposer, - CometChatButton, -} from "@cometchat/chat-uikit-react"; +### hideStickersButton -const sendButtonView = ( - { - // logic here - }} - /> -); +Hides the stickers button. -; -``` +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- - -```css -.cometchat-message-composer - div:not([class]) - .message-composer__send-button - .cometchat-button { - background: #edeafa; -} +### hideVideoAttachmentOption -.cometchat-message-composer - div:not([class]) - .message-composer__send-button - .cometchat-button__icon { - background: #6852d6; -} -``` +Hides the video attachment option. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- -*** +### hideVoiceRecordingButton -#### HeaderView +Hides the voice recording button. -You can set custom headerView to the MessageComposer component using the following method. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Shown below is the default chat interface. +--- - - - +### initialComposerText -The customized chat interface is displayed below. +Pre-fills the text input when the component mounts. - - - +| | | +| --- | --- | +| Type | `string` | +| Default | `""` | -Use the following code to achieve the customization shown above. +--- - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; +### mentionAllLabel -const getHeaderView = () => { - return ( -
-
-
- User has paused their notifications -
-
- ); -}; +Custom alias label for group mentions. -; -``` +| | | +| --- | --- | +| Type | `string` | +| Default | `"all"` | -
+--- - -```css -.cometchat-message-composer .message-composer__header-view { - display: flex; - align-items: center; - align-content: center; - gap: 8px var(--cometchat-padding-2, 8px); - align-self: stretch; - flex-wrap: wrap; - width: 100%; -} +### mentionsGroupMembersRequestBuilder -.cometchat-message-composer__header { - background: #dcd7f6; - border-radius: var(--cometchat-radius-ax, 1000px); - padding: var(--cometchat-padding-2, 8px) var(--cometchat-padding-5, 20px); -} +Custom builder to control how mentioned group members are fetched. -.cometchat-message-composer - .message-composer__header-view - .message-composer__header-view-text { - overflow: hidden; - color: var(--cometchat-text-color-primary, #141414); - text-overflow: ellipsis; - font: var(--cometchat-font-body-regular); -} +| | | +| --- | --- | +| Type | `CometChat.GroupMembersRequestBuilder` | +| Default | `undefined` | -.cometchat-message-composer - .message-composer__header-view - .message-composer__header-view-icon { - display: flex; - width: 24px; - height: 24px; - justify-content: center; - align-items: center; - background: var(--cometchat-primary-color); - -webkit-mask: url("icon url") center center no-repeat; - -webkit-mask-size: contain; - mask: url("icon url") center center no-repeat; - mask-size: contain; -} -``` +--- - +### mentionsUsersRequestBuilder -
+Custom builder to control how mentioned users are fetched. -*** +| | | +| --- | --- | +| Type | `CometChat.UsersRequestBuilder` | +| Default | `undefined` | -#### TextFormatters +--- -Assigns the list of text formatters. If the provided list is not null, it sets the list. Otherwise, it assigns the default text formatters retrieved from the data source. To configure the existing Mentions look and feel check out [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide) +### onError - - -```ts -import { CometChatTextFormatter } from "@cometchat/chat-uikit-react"; -import DialogHelper from "./Dialog"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +Callback fired when the component encounters an error. -class ShortcutFormatter extends CometChatTextFormatter { - private shortcuts: { [key: string]: string } = {}; - private dialogIsOpen: boolean = false; - private dialogHelper = new DialogHelper(); - private currentShortcut: string | null = null; // Track the currently open shortcut - - constructor() { - super(); - this.setTrackingCharacter("!"); - CometChat.callExtension("message-shortcuts", "GET", "v1/fetch", undefined) - .then((data: any) => { - if (data && data.shortcuts) { - this.shortcuts = data.shortcuts; - } - }) - .catch((error) => console.log("error fetching shortcuts", error)); - } +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | - onKeyDown(event: KeyboardEvent) { - const caretPosition = - this.currentCaretPosition instanceof Selection - ? this.currentCaretPosition.anchorOffset - : 0; - const textBeforeCaret = this.getTextBeforeCaret(caretPosition); - - const match = textBeforeCaret.match(/!([a-zA-Z]+)$/); - if (match) { - const shortcut = match[0]; - const replacement = this.shortcuts[shortcut]; - if (replacement) { - // Close the currently open dialog, if any - if (this.dialogIsOpen && this.currentShortcut !== shortcut) { - this.closeDialog(); - } - this.openDialog(replacement, shortcut); - } - } - } +--- - getCaretPosition() { - if (!this.currentCaretPosition?.rangeCount) return { x: 0, y: 0 }; - const range = this.currentCaretPosition?.getRangeAt(0); - const rect = range.getBoundingClientRect(); - return { - x: rect.left, - y: rect.top, - }; - } +### onSendButtonClick - openDialog(buttonText: string, shortcut: string) { - this.dialogHelper.createDialog( - () => this.handleButtonClick(buttonText), - buttonText - ); - this.dialogIsOpen = true; - this.currentShortcut = shortcut; - } +Callback fired when the send button is clicked. Overrides default send behavior. - closeDialog() { - this.dialogHelper.closeDialog(); // Use DialogHelper to close the dialog - this.dialogIsOpen = false; - this.currentShortcut = null; - } +| | | +| --- | --- | +| Type | `(message: CometChat.BaseMessage, previewMessageMode?: PreviewMessageMode) => void` | +| Default | `undefined` | - handleButtonClick = (buttonText: string) => { - if (this.currentCaretPosition && this.currentRange) { - // Inserting the replacement text corresponding to the shortcut - const shortcut = Object.keys(this.shortcuts).find( - (key) => this.shortcuts[key] === buttonText - ); - if (shortcut) { - const replacement = this.shortcuts[shortcut]; - this.addAtCaretPosition( - replacement, - this.currentCaretPosition, - this.currentRange - ); - } - } - if (this.dialogIsOpen) { - this.closeDialog(); - } - }; +--- - getFormattedText(text: string): string { - return text; - } +### onTextChange - private getTextBeforeCaret(caretPosition: number): string { - if ( - this.currentRange && - this.currentRange.startContainer && - typeof this.currentRange.startContainer.textContent === "string" - ) { - const textContent = this.currentRange.startContainer.textContent; - if (textContent.length >= caretPosition) { - return textContent.substring(0, caretPosition); - } - } - return ""; - } -} +Callback fired as the user types. -export default ShortcutFormatter; -``` +| | | +| --- | --- | +| Type | `(text: string) => void` | +| Default | `undefined` | - +--- - -```tsx -import React from "react"; -import ReactDOM from "react-dom"; +### parentMessageId -interface DialogProps { - onClick: () => void; - buttonText: string; -} +Targets a thread; messages sent as replies to this parent. -const Dialog: React.FC = ({ onClick, buttonText }) => { - return ( -
- -
- ); -}; +| | | +| --- | --- | +| Type | `number` | +| Default | `undefined` | -export default class DialogHelper { - private dialogContainer: HTMLDivElement | null = null; +--- - createDialog(onClick: () => void, buttonText: string) { - this.dialogContainer = document.createElement("div"); - document.body.appendChild(this.dialogContainer); - ReactDOM.render( - , - this.dialogContainer - ); - } +### placeholderText - closeDialog() { - if (this.dialogContainer) { - ReactDOM.unmountComponentAtNode(this.dialogContainer); - this.dialogContainer.remove(); - this.dialogContainer = null; - } - } -} -``` +Placeholder text displayed in the message input field when empty. -
+| | | +| --- | --- | +| Type | `string` | +| Default | `""` | - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageComposer } from "@cometchat/chat-uikit-react"; -import ShortcutFormatter from "./ShortCutFormatter"; - -export function MessageComposerDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +--- - return chatUser ? ( -
- -
- ) : null; -} -``` +### sendButtonView -
+Custom JSX replacing the send button. -
+| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in send button | + +--- + +### showScrollbar + +Shows the scrollbar in the composer input. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### textFormatters + +Custom text formatters for the composer input. + +| | | +| --- | --- | +| Type | `CometChatTextFormatter[]` | +| Default | Default formatters from data source | + +See [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide). + +--- + +### user + +The recipient user for the composer. + +| | | +| --- | --- | +| Type | `CometChat.User` | +| Default | `undefined` | + +--- + +## Events + +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatMessageEvents.ccMessageSent` | `IMessages` | Message sent | +| `CometChatMessageEvents.ccMessageEdited` | `IMessages` | Message edited | +| `CometChatMessageEvents.ccReplyToMessage` | `IMessages` | User replies to message | + +--- -*** +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-message-composer` | +| Send button | `.cometchat-message-composer__send-button` | +| Send button active | `.cometchat-message-composer__send-button-active` | +| Sticker popover | `.cometchat-message-composer__auxilary-button-view-sticker-button .cometchat-popover__content` | +| Emoji keyboard popover | `.cometchat-message-composer__emoji-keyboard-button .cometchat-popover__content` | +| Attachment popover | `.cometchat-message-composer__secondary-button-view-attachment-button .cometchat-popover__content` | +| Voice recording popover | `.cometchat-message-composer__voice-recording-button .cometchat-popover__content` | +| Header area | `.cometchat-message-composer__header` | diff --git a/ui-kit/react/message-header.mdx b/ui-kit/react/message-header.mdx index 28d7d0c85..d0009f0cb 100644 --- a/ui-kit/react/message-header.mdx +++ b/ui-kit/react/message-header.mdx @@ -1,490 +1,409 @@ --- title: "Message Header" +description: "Toolbar displaying user/group avatar, name, status, typing indicator, back button, and call controls for a single conversation." --- + +```json +{ + "component": "CometChatMessageHeader", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatMessageHeader } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Toolbar displaying user/group avatar, name, status, typing indicator, back button, and call controls for a single conversation.", + "cssRootClass": ".cometchat-message-header", + "note": "View slots are JSX.Element (not functions) — unlike list components.", + "props": { + "data": { + "user": { "type": "CometChat.User", "default": "undefined" }, + "group": { "type": "CometChat.Group", "default": "undefined" }, + "lastActiveAtDateTimeFormat": { "type": "CalendarObject", "default": "component default" }, + "summaryGenerationMessageCount": { "type": "number", "default": 1000 } + }, + "callbacks": { + "onBack": "() => void", + "onError": "((error: CometChat.CometChatException) => void) | null", + "onItemClick": "() => void", + "onSearchOptionClicked": "() => void" + }, + "visibility": { + "showBackButton": { "type": "boolean", "default": false }, + "hideVideoCallButton": { "type": "boolean", "default": false }, + "hideVoiceCallButton": { "type": "boolean", "default": false }, + "hideUserStatus": { "type": "boolean", "default": false }, + "showConversationSummaryButton": { "type": "boolean", "default": false }, + "showSearchOption": { "type": "boolean", "default": false }, + "enableAutoSummaryGeneration": { "type": "boolean", "default": false } + }, + "viewSlots": { + "itemView": "JSX.Element", + "leadingView": "JSX.Element", + "titleView": "JSX.Element", + "subtitleView": "JSX.Element", + "trailingView": "JSX.Element", + "auxiliaryButtonView": "JSX.Element" + } + }, + "sdkListeners": [ + "onUserOnline", + "onUserOffline", + "onTypingStarted", + "onTypingEnded", + "onGroupMemberJoined", + "onGroupMemberLeft", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onMemberAddedToGroup" + ], + "types": { + "CalendarObject": { + "today": "string | undefined", + "yesterday": "string | undefined", + "lastWeek": "string | undefined", + "otherDays": "string | undefined", + "relativeTime": { + "minute": "string | undefined", + "minutes": "string | undefined", + "hour": "string | undefined", + "hours": "string | undefined" + } + } + } +} +``` + -## Overview - -`MessageHeader` is a Component that showcases the [User](/sdk/javascript/users-overview) or [Group](/sdk/javascript/groups-overview) details in the toolbar. Furthermore, it also presents a typing indicator and a back navigation button for ease of use. - - - - - -The `MessageHeader` is comprised of the following components: - -| Component | Description | -| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| CometChatListItem | This component’s view consists of avatar, status indicator , title, and subtitle. The fields are then mapped with the SDK’s user, group class. | -| Back Button | BackButton that allows users to navigate back from the current activity or screen to the previous one. | - -## Usage +## Where It Fits -### Integration +`CometChatMessageHeader` is a toolbar component that sits above `CometChatMessageList` and `CometChatMessageComposer`. It receives a `user` or `group` prop and displays the conversation's avatar, name, online status, and typing indicator. Call buttons are rendered automatically when the calling extension is enabled. - - -```tsx -import React from "react"; +```tsx lines +import { useEffect, useState } from "react"; +import { + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; - -export function MessageHeaderDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +import "@cometchat/chat-uikit-react/css-variables.css"; - return chatUser ? ( -
{chatUser && }
- ) : null; -} -``` +function ChatView() { + const [user, setUser] = useState(); -
+ useEffect(() => { + CometChat.getUser("UID").then(setUser); + }, []); - -```tsx -import { MessageHeaderDemo } from "./MessageHeaderDemo"; + if (!user) return null; -export default function App() { return ( -
-
- -
+
+ + +
); } ``` - - - - -### Actions - -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. - -#### 1. OnBack - -`OnBack` is triggered when you click on the back button of the Message Header component. You can override this action using the following code snippet. + + + -**Example** +--- -In this example, we are employing the `onBack` action. +## Minimal Render - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines +import { useEffect, useState } from "react"; import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import "@cometchat/chat-uikit-react/css-variables.css"; -export function MessageHeaderDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +function MessageHeaderDemo() { + const [user, setUser] = useState(); - function handleOnBack() { - console.log("your custom on back action"); - } + useEffect(() => { + CometChat.getUser("UID").then(setUser); + }, []); - return chatUser ? ( -
- {chatUser && ( - - )} -
- ) : null; + return user ? : null; } -``` -
+export default MessageHeaderDemo; +``` -
+Root CSS class: `.cometchat-message-header` -*** +--- -#### 2. OnError +## Actions and Events -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Message Header component. +### Callback Props -**Example** +#### onBack -In this example, we are employing the `onError` action. +Fires when the back button is clicked. Requires `showBackButton={true}`. - - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export function MessageHeaderDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); - - function handleError(error: CometChat.CometChatException) { - throw new Error("your custom error action"); - } - return chatUser ? ( -
- {chatUser && ( - - )} -
- ) : null; +function HeaderWithBack({ user }: { user: CometChat.User }) { + return ( + console.log("Navigate back")} + /> + ); } ``` -
+#### onItemClick -
- -*** - -##### 3. onSearchOptionClicked +Fires when the header list item area (avatar + name) is clicked. -The `onSearchOptionClicked` event is triggered when the user clicks the search option. It does not have a default behavior. However, you can override its behavior using the following code snippet. - - - -```tsx +```tsx lines import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -const handleSearchClick = () => { - console.log("Search option clicked"); -}; - -; +function HeaderWithItemClick({ user }: { user: CometChat.User }) { + return ( + console.log("Open user detail")} + /> + ); +} ``` - - - - -*** +#### onSearchOptionClicked -#### 4. OnItemClick - -`OnItemClick` is triggered when you click on a ListItem of the `CometChatMessageHeader` component. The `OnItemClick` action doesn't have a predefined behavior. You can override this action using the following code snippet. - - - -```tsx -import { MessageHeaderDemo } from "@cometchat/chat-uikit-react"; +Fires when the search option is clicked. Requires `showSearchOption={true}`. -const getOnItemClick = () => { - console.log("List item clicked"); -}; +```tsx lines +import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -; +function HeaderWithSearch({ user }: { user: CometChat.User }) { + return ( + console.log("Open search")} + /> + ); +} ``` - - - - -*** - -### Filters - -**Filters** allow you to customize the data displayed in a list within a `Component`. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using `RequestBuilders` of Chat SDK. +#### onError -The `MessageHeader` component does not have any exposed filters. - -### Events - -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. - -The `MessageHeader` component does not produce any events. - -## Customization - -To fit your app's design requirements, you can customize the appearance of the Message Header component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. - -### Style - -To customize the appearance, you can customise css of `CometChatMessageHeader` - -**Example** - - - - +Fires on internal errors. - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -// Assuming groupObj is defined elsewhere in your code -; -``` - - - - -```css -.cometchat-message-header .cometchat-list-item .cometchat-avatar { - background: #f0999b; - border-radius: 8px; -} -.cometchat-message-header .cometchat-avatar__text { - font-family: "SF Pro"; +function HeaderWithError({ user }: { user: CometChat.User }) { + return ( + { + console.error("MessageHeader error:", error); + }} + /> + ); } ``` - - - - -### Functionality - -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. - -Here is a code snippet demonstrating how you can customize the functionality of the Message Header component. - - - -```ts -import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +### SDK Events (Real-Time, Automatic) -; -``` +The component listens to these SDK events internally. No manual attachment needed. - +| SDK Listener | Internal behavior | +| --- | --- | +| `onUserOnline` / `onUserOffline` | Updates the user's online/offline status indicator | +| `onTypingStarted` / `onTypingEnded` | Shows/hides the typing indicator in the subtitle area | +| Group member events | Updates group member count when members join/leave | - + +In React 18 StrictMode, `useEffect` runs twice on mount in development. The component handles listener cleanup internally. + -Following is a list of customizations along with their corresponding code snippets: +--- -| Property | Description | Code | -| ------------------------------------ | --------------------------------------------------------------------------------------------------- | -------------------------------------- | -| **Show Back Button** | Shows the back button. | `showBackButton={true}` | -| **Hide Video Call Button** | Hides the video call button. | `hideVideoCallButton={true}` | -| **Hide Voice Call Button** | Hides the voice call button. | `hideVoiceCallButton={true}` | -| **Show Conversation Summary Button** | Shows the conversation summary button. | `showConversationSummaryButton={true}` | -| **Hide User Status** | Hides the user's online/offline status indicator. | `hideUserStatus={true}` | -| **Show Search Option** | Shows the search option. | `showSearchOption={true}` | -| **User** | A `CometChat.User` object representing the user whose information (e.g., status) is displayed. | `user={chatUser}` | -| **Group** | A `CometChat.Group` object representing the group whose details (e.g., member count) are displayed. | `group={chatGroup}` | -| **Summary Generation Message Count** | Number of messages for which the summary should be shown. | `summaryGenerationMessageCount={1000}` | -| **Disable Auto Summary Generation** | Disables the auto generation of conversation summary. | `disableAutoSummaryGeneration={true}` | +## Custom View Slots -### Advanced +View slots for `CometChatMessageHeader` are `JSX.Element` (not functions) — unlike list components where slots receive a data parameter. -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. +| Slot | Type | Replaces | +| --- | --- | --- | +| `itemView` | `JSX.Element` | Entire list item (avatar + name + subtitle) | +| `leadingView` | `JSX.Element` | Avatar / left section | +| `titleView` | `JSX.Element` | Name / title text | +| `subtitleView` | `JSX.Element` | Subtitle text (status / typing indicator) | +| `trailingView` | `JSX.Element` | Right section (call buttons area) | +| `auxiliaryButtonView` | `JSX.Element` | Auxiliary button area (next to call buttons) | -#### ItemView +### itemView -The customized chat interface is displayed below. +Replace the entire list item (avatar + name + subtitle). -Use the following code to achieve the customization shown above. - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader, CometChatListItem, } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -// Custom list item view definition -const CustomItemView = ( - <> - + } + showBackButton={true} /> - -); - -; + ); +} ``` - - - -```css + +```css lines .cometchat-message-header .cometchat-list-item .cometchat-avatar { border-radius: 8px; } ``` - - -*** - -#### TitleView +### titleView -The customized chat interface is displayed below. +Replace the name / title text. -Use the following code to achieve the customization shown above. - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -// Custom title view component -function CustomTitleView() { +function CustomTitleHeader({ user }: { user: CometChat.User }) { return ( -
- - {userObj.getName() + " • "} - - - {userObj.getStatusMessage()} - -
+ + + {user.getName() + " • "} + + + {user.getStatusMessage()} + +
+ } + /> ); } - -; ``` -
- - -```css + +```css lines .cometchat-message-header .message-header__title-view { display: flex; gap: 4px; width: 100%; } -.cometchat-message-header - .message-header__title-view - .message-header__title-view-name { +.message-header__title-view-name { color: #141414; font: 500 16px/19.2px Roboto; - text-align: left; } -.cometchat-message-header - .message-header__title-view - .message-header__title-view-status { + +.message-header__title-view-status { color: #6852d6; font: 400 16px/19.2px Roboto; - text-align: left; } ``` - -
-*** - -#### SubtitleView +### subtitleView -The customized chat interface is displayed below. +Replace the subtitle text (status / typing indicator area). -Use the following code to achieve the customization shown above. - - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -// Custom subtitle view component -function CustomSubtitleView() { - return <>{group?.getMembersCount() + " • " + group?.getDescription()}; +function CustomSubtitleHeader({ group }: { group: CometChat.Group }) { + return ( + {group.getMembersCount() + " • " + group.getDescription()} + } + /> + ); } - -; ``` - - - - -*** +### leadingView -#### LeadingView - -The customized chat interface is displayed below. +Replace the avatar / left section. -Use the following code to achieve the customization shown above. - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader, CometChatAvatar, } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -// Custom title view component -function CustomLeadingView() { +function CustomLeadingHeader({ user }: { user: CometChat.User }) { return ( -
- - - ⭐ {userObj?.getRole()} - -
+ + + + {user.getRole()} + +
+ } + /> ); } - -; ``` -
- - -```css -.cometchat-message-header - .cometchat-list-item - .message-header__leading-view - .cometchat-avatar__image, -.cometchat-message-header - .cometchat-list-item - .message-header__leading-view - .cometchat-avatar { + +```css lines +.cometchat-message-header .message-header__leading-view .cometchat-avatar { border-radius: 8px; height: 48px; width: 48px; @@ -503,203 +422,488 @@ function CustomLeadingView() { position: absolute; bottom: -2px; } + .message-header__leading-view { position: relative; } ``` - - -*** +### trailingView -#### TrailingView - -The customized chat interface is displayed below. +Replace the right section (call buttons area). -Use the following code to achieve the customization shown above. - - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageHeader, CometChatButton, } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -// Custom trailing view component -function CustomTrailingButtonView() { +function CustomTrailingHeader({ user }: { user: CometChat.User }) { return ( - <> - { - // Your logic here - }} - iconURL={icon} // Ensure `icon` is defined or passed as a prop - /> - + { /* custom action */ }} /> + } + /> ); } - -; ``` - +### auxiliaryButtonView - -```css -.cometchat-message-header - .cometchat-list-item__trailing-view - .cometchat-button { - background: transparent; - height: 24px; - width: 24px; - padding: 0; -} +Replace the auxiliary button area (next to call buttons). + + + + -.cometchat-message-header - .cometchat-list-item__trailing-view - .cometchat-button__icon { - background: black; +```tsx lines +import { + CometChatMessageHeader, + CometChatButton, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function AuxiliaryButtonHeader({ group }: { group: CometChat.Group }) { + return ( + { /* custom action */ }} /> + } + /> + ); } ``` - +### lastActiveAtDateTimeFormat - +Customize the "last seen" timestamp format using a `CalendarObject`. -*** +```tsx lines +import { + CometChatMessageHeader, + CalendarObject, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -#### AuxiliaryButtonView +function CustomDateHeader({ user }: { user: CometChat.User }) { + const dateFormat = new CalendarObject({ + today: "hh:mm A", + yesterday: "[yesterday]", + otherDays: "DD MM YYYY", + }); + + return ( + + ); +} +``` -The customized chat interface is displayed below. + +If no property is passed in the [CalendarObject](/ui-kit/react/localize#calendarobject), the component checks the [global configuration](/ui-kit/react/localize#customisation) first. If also missing there, the component's default formatting applies. + - - - +--- -Use the following code to achieve the customization shown above. +## Common Patterns - - -```ts -import React from "react"; +### Header with back button and search + +```tsx lines +import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatMessageHeader, - CometChatButton, -} from "@cometchat/chat-uikit-react"; -// Custom auxiliary view component -function CustomAuxiliaryButtonView() { +function FullFeaturedHeader({ user }: { user: CometChat.User }) { return ( - <> - { - // Your logic here - }} - iconURL={icon} // Ensure `icon` is defined or passed as a prop - /> - + { /* navigate back */ }} + onSearchOptionClicked={() => { /* open search */ }} + /> ); } - -; ``` - +### Hide call buttons - -```css -.cometchat-message-header - .cometchat-message-header__auxiliary-view - .cometchat-button { - background: transparent; - height: 24px; - width: 24px; - padding: 0; +```tsx lines +import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function NoCalls({ user }: { user: CometChat.User }) { + return ( + + ); } +``` -.cometchat-message-header - .cometchat-message-header__auxiliary-view - .cometchat-button__icon { - background: black; +### Group header with AI summary + +```tsx lines +import { CometChatMessageHeader } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function GroupHeaderWithSummary({ group }: { group: CometChat.Group }) { + return ( + + ); } ``` - +--- - +## CSS Architecture -#### LastActiveAt Date Time Format +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: -The `lastActiveAtDateTimeFormat` property allows you to customize the **last active** timestamp displayed in the message header. +1. Global tokens are set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-message-header`) consumes these tokens via `var()` with fallback values. +3. Overrides target `.cometchat-message-header` descendant selectors in a global stylesheet. -Default Date Time Format: +### Key Selectors -```ruby -new CalendarObject({ - today: `[Last seen DD MMM at] hh:mm A`, // Example: "today at 10:30 AM" - yesterday: `[Last seen DD MMM at] hh:mm A`, // Example: "yesterday at 08:15 PM" - otherDays: `[Last seen DD MMM at] hh:mm A`, // Example: "25, Jan 05:45 PM" - relativeTime: { - hour: `Last seen %d hour ago`, // Example: "1 hour ago" - minute: `Last seen %d minute ago`, // Example: "1 minute ago" - minutes: `Last seen %d minutes ago`, // Example: "5 minutes ago" - }, -}); -``` +| Target | Selector | +| --- | --- | +| Root | `.cometchat-message-header` | +| List item | `.cometchat-message-header .cometchat-list-item` | +| Body title | `.cometchat-message-header .cometchat-list-item__body-title` | +| Avatar | `.cometchat-message-header .cometchat-list-item .cometchat-avatar` | +| Leading view | `.cometchat-message-header .cometchat-list-item__leading-view` | +| Trailing view | `.cometchat-message-header .cometchat-list-item__trailing-view` | +| Subtitle | `.cometchat-message-header__subtitle` | +| Subtitle (typing) | `.cometchat-message-header__subtitle-typing` | +| Back button | `.cometchat-message-header__back-button` | +| Auxiliary button view | `.cometchat-message-header__auxiliary-button-view` | +| List item container | `.cometchat-message-header__listitem` | +| Title container | `.cometchat-message-header .cometchat-list-item__title-container` | -The following example demonstrates how to modify the **last active** timestamp format using a custom [`CalendarObject`](/ui-kit/react/localize#calendarobject). +### Example: Brand-themed header - - -```ts -import { - CometChatMessageHeader, - CalendarObject, -} from "@cometchat/chat-uikit-react"; + + + -// Define a custom date format pattern -function getDateFormat() { - const dateFormat = new CalendarObject({ - today: `hh:mm A`, // Example: "10:30 AM" - yesterday: `[yesterday]`, // Example: "yesterday" - otherDays: `DD MM YYYY`, // Example: "25 01 2025" - }); - return dateFormat; +```css lines +.cometchat-message-header .cometchat-list-item .cometchat-avatar { + background: #f0999b; + border-radius: 8px; } -// Apply the custom format to the CometChatMessageHeader component -; +.cometchat-message-header .cometchat-avatar__text { + font-family: "SF Pro"; +} ``` - +### Customization Matrix - +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior on user interaction | Component props | `on` callbacks | `onBack={() => navigate(-1)}` | +| Toggle visibility of UI elements | Component props | `hide` / `show` boolean props | `hideVideoCallButton={true}` | +| Replace a section of the header | Component props | `View` JSX.Element props | `titleView={
Custom
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-message-header` class | `.cometchat-message-header .cometchat-avatar { border-radius: 8px; }` | - +--- -**Fallback Mechanism** +## Accessibility -* If you **do not** pass any property in the [**CalendarObject**](/ui-kit/react/localize#calendarobject), the component will first check the [**global configuration**](/ui-kit/react/localize#customisation). If the property is **also missing in the global configuration**, it will **fallback to the component's default formatting**. +The component renders a toolbar with interactive elements. The back button, call buttons, and auxiliary buttons are keyboard-focusable and activate on Enter/Space. The avatar includes alt text. The typing indicator updates the subtitle text dynamically — screen readers announce the change via live region behavior. - +--- + +--- + +## Props + +All props are optional unless noted otherwise. + +--- + +### auxiliaryButtonView + +Custom component for the auxiliary button area. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | + +--- + +### enableAutoSummaryGeneration + +Enables automatic conversation summary generation. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### group + +Displays group details in the header. + +| | | +| --- | --- | +| Type | `CometChat.Group` | +| Default | `undefined` | + +Pass either `user` or `group`, not both. + +--- + +### hideBackButton + +Hides the back navigation button. Deprecated — use `showBackButton` instead. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | + +--- + +### hideUserStatus + +Hides the user's online/offline status indicator. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideVideoCallButton + +Hides the video call button. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideVoiceCallButton + +Hides the voice call button. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### itemView + +Custom component for the entire list item. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | + +--- + +### lastActiveAtDateTimeFormat + +Format for displaying the "last seen" timestamp. + +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default | + +--- + +### leadingView + +Custom component for the avatar / left section. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | + +--- + +### onBack + +Callback fired when the back button is clicked. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `() => {}` | + +--- + +### onError + +Callback fired when the component encounters an error. + +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | + +--- + +### onItemClick + +Callback fired when the header list item is clicked. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `() => {}` | + +--- + +### onSearchOptionClicked + +Callback fired when the search option is clicked. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `() => {}` | + +--- + +### showBackButton + +Shows the back navigation button. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showConversationSummaryButton + +Shows the AI conversation summary button. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showSearchOption + +Shows the search option in the header. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### subtitleView + +Custom component for the subtitle text. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | + +--- + +### summaryGenerationMessageCount + +Number of messages used for AI summary generation. + +| | | +| --- | --- | +| Type | `number` | +| Default | `1000` | + +--- + +### titleView + +Custom component for the name / title text. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | + +--- + +### trailingView + +Custom component for the right section. + +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | + +--- + +### user + +Displays user details in the header. + +| | | +| --- | --- | +| Type | `CometChat.User` | +| Default | `undefined` | + +Pass either `user` or `group`, not both. + +--- -*** +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-message-header` | +| List item | `.cometchat-message-header .cometchat-list-item` | +| Body title | `.cometchat-message-header .cometchat-list-item__body-title` | +| Avatar | `.cometchat-message-header .cometchat-list-item .cometchat-avatar` | +| Leading view | `.cometchat-message-header .cometchat-list-item__leading-view` | +| Trailing view | `.cometchat-message-header .cometchat-list-item__trailing-view` | +| Subtitle | `.cometchat-message-header__subtitle` | +| Subtitle (typing) | `.cometchat-message-header__subtitle-typing` | +| Back button | `.cometchat-message-header__back-button` | +| Auxiliary button view | `.cometchat-message-header__auxiliary-button-view` | +| List item container | `.cometchat-message-header__listitem` | +| Title container | `.cometchat-message-header .cometchat-list-item__title-container` | +| Summary button | `.cometchat-message-header__conversation-summary-button` | +| Search button | `.cometchat-message-header__search-button` | +| Menu | `.cometchat-message-header__menu` | diff --git a/ui-kit/react/message-list.mdx b/ui-kit/react/message-list.mdx index e2300b1d1..64b2a13a9 100644 --- a/ui-kit/react/message-list.mdx +++ b/ui-kit/react/message-list.mdx @@ -1,1585 +1,1293 @@ --- title: "Message List" +description: "Scrollable list of sent and received messages with text, media, reactions, read receipts, threaded replies, and AI features." --- + +```json +{ + "component": "CometChatMessageList", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatMessageList } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Scrollable list of sent and received messages with text, media, reactions, read receipts, threaded replies, and AI features.", + "cssRootClass": ".cometchat-message-list", + "primaryOutput": { + "prop": "onThreadRepliesClick", + "type": "(message: CometChat.BaseMessage) => void" + }, + "props": { + "data": { + "user": { "type": "CometChat.User", "default": "undefined" }, + "group": { "type": "CometChat.Group", "default": "undefined" }, + "messagesRequestBuilder": { "type": "CometChat.MessagesRequestBuilder", "default": "SDK default" }, + "reactionsRequestBuilder": { "type": "CometChat.ReactionsRequestBuilder", "default": "undefined" }, + "parentMessageId": { "type": "number", "default": "undefined" }, + "templates": { "type": "CometChatMessageTemplate[]", "default": "SDK defaults" }, + "goToMessageId": { "type": "string", "default": "undefined" } + }, + "callbacks": { + "onThreadRepliesClick": "(message: CometChat.BaseMessage) => void", + "onReactionClick": "(reaction: CometChat.ReactionCount, message: CometChat.BaseMessage) => void", + "onReactionListItemClick": "(reaction: CometChat.Reaction, message: CometChat.BaseMessage) => void", + "onError": "((error: CometChat.CometChatException) => void) | null" + }, + "visibility": { + "hideDateSeparator": { "type": "boolean", "default": false }, + "hideStickyDate": { "type": "boolean", "default": false }, + "hideReceipts": { "type": "boolean", "default": false }, + "hideError": { "type": "boolean", "default": false }, + "hideReplyInThreadOption": { "type": "boolean", "default": false }, + "hideReplyOption": { "type": "boolean", "default": false }, + "hideTranslateMessageOption": { "type": "boolean", "default": false }, + "hideEditMessageOption": { "type": "boolean", "default": false }, + "hideDeleteMessageOption": { "type": "boolean", "default": false }, + "hideReactionOption": { "type": "boolean", "default": false }, + "hideMessagePrivatelyOption": { "type": "boolean", "default": false }, + "hideCopyMessageOption": { "type": "boolean", "default": false }, + "hideMessageInfoOption": { "type": "boolean", "default": false }, + "hideAvatar": { "type": "boolean", "default": false }, + "hideGroupActionMessages": { "type": "boolean", "default": false }, + "hideModerationView": { "type": "boolean", "default": false }, + "hideFlagMessageOption": { "type": "boolean", "default": false }, + "hideFlagRemarkField": { "type": "boolean", "default": false }, + "showConversationStarters": { "type": "boolean", "default": false }, + "showSmartReplies": { "type": "boolean", "default": false }, + "showMarkAsUnreadOption": { "type": "boolean", "default": false }, + "showScrollbar": { "type": "boolean", "default": false } + }, + "behavior": { + "messageAlignment": { "type": "MessageListAlignment", "default": "MessageListAlignment.standard" }, + "scrollToBottomOnNewMessages": { "type": "boolean", "default": false }, + "quickOptionsCount": { "type": "number", "default": 3 }, + "startFromUnreadMessages": { "type": "boolean", "default": false }, + "isAgentChat": { "type": "boolean", "default": false }, + "loadLastAgentConversation": { "type": "boolean", "default": false } + }, + "sound": { + "disableSoundForMessages": { "type": "boolean", "default": true }, + "customSoundForMessages": { "type": "string", "default": "undefined" } + }, + "ai": { + "smartRepliesKeywords": { "type": "string[]", "default": "[\"what\",\"when\",\"why\",\"who\",\"where\",\"how\",\"?\"]" }, + "smartRepliesDelayDuration": { "type": "number", "default": 10000 } + }, + "dateFormatting": { + "separatorDateTimeFormat": "CalendarObject", + "stickyDateTimeFormat": "CalendarObject", + "messageSentAtDateTimeFormat": "CalendarObject", + "messageInfoDateTimeFormat": "CalendarObject" + }, + "viewSlots": { + "headerView": "JSX.Element", + "footerView": "JSX.Element", + "loadingView": "JSX.Element", + "emptyView": "JSX.Element", + "errorView": "JSX.Element" + }, + "formatting": { + "textFormatters": { "type": "CometChatTextFormatter[]", "default": "default formatters" } + } + }, + "events": [ + { "name": "CometChatMessageEvents.ccMessageEdited", "payload": "IMessages" }, + { "name": "CometChatMessageEvents.ccMessageDeleted", "payload": "CometChat.BaseMessage" }, + { "name": "CometChatMessageEvents.ccMessageRead", "payload": "CometChat.BaseMessage" }, + { "name": "CometChatMessageEvents.ccReplyToMessage", "payload": "IMessages" }, + { "name": "CometChatUIEvents.ccOpenChat", "payload": "IOpenChat" }, + { "name": "CometChatUIEvents.ccActiveChatChanged", "payload": "IActiveChatChanged" } + ], + "sdkListeners": [ + "onTextMessageReceived", "onMediaMessageReceived", "onCustomMessageReceived", + "onMessageEdited", "onMessageDeleted", "onMessageModerated", + "onTypingStarted", "onTypingEnded", + "onMessagesDelivered", "onMessagesRead", "onMessagesDeliveredToAll", "onMessagesReadByAll" + ], + "types": { + "MessageListAlignment": { "left": 0, "standard": 1 }, + "CalendarObject": { "today": "string", "yesterday": "string", "lastWeek": "string", "otherDays": "string" } + } +} +``` + -## Overview +## Where It Fits + +`CometChatMessageList` renders a scrollable, real-time message feed for a user or group conversation. Wire it alongside `CometChatMessageHeader` and `CometChatMessageComposer` to build a standard chat view. + +```tsx lines +import { useState, useEffect } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatView() { + const [chatUser, setChatUser] = useState(); + + useEffect(() => { + CometChat.getUser("uid").then((user) => setChatUser(user)); + }, []); -`MessageList` is a composite component that displays a list of messages and effectively manages real-time operations. It includes various types of messages such as Text Messages, Media Messages, Stickers, and more. + return chatUser ? ( +
+ + + +
+ ) : null; +} +``` -*** - -## Usage - -### Integration +--- -The following code snippet illustrates how you can directly incorporate the MessageList component into your Application. +## Minimal Render - - -```tsx -import React from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); +function MessageListDemo() { + const [chatUser, setChatUser] = useState(); + + useEffect(() => { + CometChat.getUser("uid").then((user) => setChatUser(user)); }, []); - return chatUser ? ( -
- -
- ) : null; + return chatUser ? : null; } + +export default MessageListDemo; ``` -
+Root CSS class: `.cometchat-message-list` + +--- - -```tsx -import { MessageListDemo } from "./MessageListDemo"; +## Filtering Messages -export default function App() { +Pass a `CometChat.MessagesRequestBuilder` to `messagesRequestBuilder`. The `UID`/`GUID` parameters are always overridden internally based on the `user`/`group` prop. + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatMessageList } from "@cometchat/chat-uikit-react"; + +function FilteredMessageList() { return ( -
-
- -
-
+ ); } ``` -
- -
+### Reactions Request Builder - +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -To fetch messages for a specific entity, you need to supplement it with `User` or `Group` Object. +function ReactionsFilteredList() { + return ( + + ); +} +``` - +Refer to [MessagesRequestBuilder](/sdk/javascript/additional-message-filtering) for the full builder API. -*** +--- -### Actions +## Actions and Events -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +### Callback Props -##### 1. onThreadRepliesClick +#### onThreadRepliesClick -`onThreadRepliesClick` is triggered when you click on the threaded message bubble. The `onThreadRepliesClick` action doesn't have a predefined behavior. You can override this action using the following code snippet. +Fires when a threaded message reply count is clicked. - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); - - const getOnThreadRepliesClick = () => { - //your custom actions - }; - - return chatUser ? ( -
- -
- ) : null; +function MessageListWithThreads() { + return ( + { + console.log("Thread:", message.getId()); + }} + /> + ); } ``` -
+#### onReactionClick - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +Fires when a reaction on a message bubble is clicked. + +```tsx lines import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +function MessageListWithReactions() { + return ( + { + console.log("Reaction:", reaction, "on message:", message.getId()); + }} + /> + ); +} +``` - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +#### onReactionListItemClick - const getOnThreadRepliesClick = () => { - //your custom actions - }; +Fires when a specific reaction in the reaction detail view is clicked. - return chatUser ? ( -
- -
- ) : null; +```tsx lines +import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function MessageListWithReactionDetail() { + return ( + { + console.log("Reaction detail:", reaction, message.getId()); + }} + /> + ); } ``` -
+#### onError -
+Fires on internal errors. -##### 2. onError +```tsx lines +import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -This action doesn't change the behavior of the component but rather listens for any errors that occur in the MessageList component. +function MessageListWithError() { + return ( + { + console.error("MessageList error:", error); + }} + /> + ); +} +``` - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +### Global UI Events -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +| Event | Fires when | Payload | +| --- | --- | --- | +| `CometChatMessageEvents.ccMessageEdited` | A message is edited | `IMessages` | +| `CometChatMessageEvents.ccMessageDeleted` | A message is deleted | `CometChat.BaseMessage` | +| `CometChatMessageEvents.ccMessageRead` | A message is read | `CometChat.BaseMessage` | +| `CometChatMessageEvents.ccReplyToMessage` | User replies to a message | `IMessages` | +| `CometChatUIEvents.ccOpenChat` | User opens a chat | `IOpenChat` | +| `CometChatUIEvents.ccActiveChatChanged` | Active chat changes | `IActiveChatChanged` | - function handleError(error: CometChat.CometChatException) { - throw new Error("your custom error action"); - } +```tsx lines +import { useEffect } from "react"; +import { CometChatMessageEvents, CometChatUIEvents } from "@cometchat/chat-uikit-react"; - return chatUser ? ( -
- -
- ) : null; +function useMessageListEvents() { + useEffect(() => { + const editedSub = CometChatMessageEvents.ccMessageEdited.subscribe( + (data) => console.log("Edited:", data) + ); + const deletedSub = CometChatMessageEvents.ccMessageDeleted.subscribe( + (msg) => console.log("Deleted:", msg) + ); + + return () => { + editedSub?.unsubscribe(); + deletedSub?.unsubscribe(); + }; + }, []); } ``` -
+### SDK Events (Real-Time, Automatic) - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +The component listens to these SDK events internally: -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +| SDK Listener | Internal behavior | +| --- | --- | +| `onTextMessageReceived` / `onMediaMessageReceived` / `onCustomMessageReceived` | Appends new message to list | +| `onMessageEdited` / `onMessageDeleted` | Updates/removes message in list | +| `onTypingStarted` / `onTypingEnded` | Shows/hides typing indicator | +| `onMessagesDelivered` / `onMessagesRead` / `onMessagesDeliveredToAll` / `onMessagesReadByAll` | Updates receipt ticks | +| `onMessageModerated` | Updates moderated message state | - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); - - const handleError = (error) => { - throw new Error("your custom error action"); - }; +--- - return chatUser ? ( -
- -
- ) : null; -} -``` +## Custom View Slots -
+| Slot | Type | Replaces | +| --- | --- | --- | +| `headerView` | `JSX.Element` | Area above the message list | +| `footerView` | `JSX.Element` | Area below the message list | +| `loadingView` | `JSX.Element` | Loading state | +| `emptyView` | `JSX.Element` | Empty state | +| `errorView` | `JSX.Element` | Error state | +| `templates` | `CometChatMessageTemplate[]` | Message bubble rendering | +| `textFormatters` | `CometChatTextFormatter[]` | Text formatting in messages | -
+### headerView -##### 3. onReactionClick +Custom view above the message list. -`onReactionClick` is triggered when you click on the reaction item of the message bubble. The `onReactionClick` action doesn't have a predefined behavior. You can override this action using the following code snippet. + + + -```ts -import React from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import { CometChatMessageList, CometChatButton } from "@cometchat/chat-uikit-react"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +function MessageListWithHeader() { + const [chatUser, setChatUser] = useState(); - function onReactionClick( - reaction: CometChat.ReactionCount, - message: CometChat.BaseMessage - ) { - //your custom action - } + useEffect(() => { + CometChat.getUser("uid").then((user) => setChatUser(user)); + }, []); return chatUser ? ( -
- -
+ + + + +
+ } + /> ) : null; } ``` -
+ +```css lines +.header-view { + display: flex; + width: 100%; + padding: 3px 16px; + align-items: flex-start; + gap: 5px; + background: #edeafa; +} - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; - -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); - - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); - - const onReactionClick = (reaction, message) => { - //your custom action - }; +.header-view .cometchat .cometchat-button { + width: auto; + height: 32px; + border-radius: 1000px; + border: 1px solid #e8e8e8; + background: #fafafa; +} - return chatUser ? ( -
- -
- ) : null; +.header-view .cometchat .cometchat-button__text { + color: #6852d6; + font: 400 12px/14.4px Roboto; } ``` -
-
-##### 4. onReactionListItemClick +### footerView + +Custom view below the message list. -`onReactionListItemClick` is triggered when you click on the reaction list item of the reaction list. The `onReactionListItemClick` action doesn't have a predefined behavior. You can override this action using the following code snippet. + + + -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +```tsx lines +import { CometChatMessageList, CometChatButton } from "@cometchat/chat-uikit-react"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +function MessageListWithFooter() { + return ( + + + +
+ } + /> + ); +} +``` +
+ +```css lines +.footer-view { + display: flex; + width: 100%; + padding: 3px 16px; + align-items: flex-start; + gap: 5px; + background: #edeafa; +} - function onReactionListItemClick( - reaction: CometChat.Reaction, - message: CometChat.BaseMessage - ) { - //your custom action - } +.footer-view .cometchat .cometchat-button { + width: auto; + height: 32px; + border-radius: 1000px; + border: 1px solid #e8e8e8; + background: #fafafa; +} - return chatUser ? ( -
- -
- ) : null; +.footer-view .cometchat .cometchat-button__text { + color: #6852d6; + font: 400 12px/14.4px Roboto; } ``` -
+ + +### templates + +Custom message bubble templates via [CometChatMessageTemplate](/ui-kit/react/message-template). - -```js -import React from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +import { + CometChatMessageList, + ChatConfigurator, + CometChatActionsIcon, +} from "@cometchat/chat-uikit-react"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +function MessageListCustomTemplates() { + const [chatUser, setChatUser] = useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); + useEffect(() => { + CometChat.getUser("uid").then((user) => setChatUser(user)); }, []); - const onReactionListItemClick = (reaction, message) => { - //your custom action + const getTemplates = () => { + const templates = ChatConfigurator.getDataSource().getAllMessageTemplates(); + templates.map((data) => { + data.options = (loggedInUser, message, group) => { + const defaults = ChatConfigurator.getDataSource().getMessageOptions( + loggedInUser, message, group + ); + defaults.push( + new CometChatActionsIcon({ + id: "custom", + title: "Custom Action", + onClick: () => console.log("custom action"), + }) + ); + return defaults; + }; + }); + return templates; }; return chatUser ? ( -
- -
+ ) : null; } ``` -
+### Date Time Formatting - +Customize timestamps using `CalendarObject`: -### Filters +```tsx lines +import { CometChatMessageList, CalendarObject } from "@cometchat/chat-uikit-react"; -##### 1. Messages Request Builder +function MessageListCustomDates() { + const dateFormat = new CalendarObject({ + today: "hh:mm A", + yesterday: "[yesterday]", + otherDays: "DD/MM/YYYY", + }); -You can adjust the `MessagesRequestBuilder` in the MessageList Component to customize your message list. Numerous options are available to alter the builder to meet your specific needs. For additional details on `MessagesRequestBuilder`, please visit [MessagesRequestBuilder](/sdk/javascript/additional-message-filtering). + return ( + + ); +} +``` -In the example below, we are applying a filter to the messages based on a search substring and for a specific user. This means that only messages that contain the search term and are associated with the specified user will be displayed +--- - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +## Common Patterns -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +### Threaded message list - return chatUser ? ( -
- -
- ) : null; +```tsx lines +import { CometChatMessageList } from "@cometchat/chat-uikit-react"; + +function ThreadedMessageList() { + return ( + + ); } ``` -
+### Hide all chrome — minimal list - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +```tsx lines import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +function MinimalMessageList() { + return ( + + ); +} +``` - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +### Left-aligned messages - return chatUser ? ( -
- -
- ) : null; +```tsx lines +import { CometChatMessageList, MessageListAlignment } from "@cometchat/chat-uikit-react"; + +function LeftAlignedList() { + return ( + + ); } ``` -
+### AI conversation starters and smart replies -
+```tsx lines +import { CometChatMessageList } from "@cometchat/chat-uikit-react"; - +function AIMessageList() { + return ( + + ); +} +``` -The following parameters in messageRequestBuilder will always be altered inside the message list +--- -1. UID -2. GUID +## CSS Architecture - +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: -##### 2. Reactions Request Builder +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-message-list`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-message-list` descendant selectors. -You can adjust the `ReactionsRequestBuilder` in the MessageList Component to customize and fetch the reactions for the messages. Numerous options are available to alter the builder to meet your specific needs. +### Key Selectors - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +| Target | Selector | +| --- | --- | +| Root | `.cometchat-message-list` | +| Error state | `.cometchat-message-list__error-state-view` | +| Footer smart replies | `.cometchat-message-list__footer-smart-replies` | +| Footer conversation starters | `.cometchat-message-list__footer-conversation-starter` | +| Outgoing message bubble | `.cometchat-message-bubble-outgoing` | +| Incoming message bubble | `.cometchat-message-bubble-incoming` | +| Message bubble status info | `.cometchat-message-bubble__status-info-view` | +| Thread view replies | `.cometchat-message-bubble__thread-view-replies` | +| Text bubble | `.cometchat-message-bubble .cometchat-text-bubble` | +| Date separator | `.cometchat-message-bubble__status-info-view .cometchat-date` | -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +### Customization Matrix - return chatUser ? ( -
- -
- ) : null; -} -``` +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Handle thread clicks | Component props | `onThreadRepliesClick` | `onThreadRepliesClick={(msg) => openThread(msg)}` | +| Filter messages | Component props | `messagesRequestBuilder` | `messagesRequestBuilder={builder}` | +| Toggle visibility | Component props | `hide` boolean props | `hideReceipts={true}` | +| Custom message bubbles | Component props | `templates` | `templates={customTemplates}` | +| Add header/footer | Component props | `headerView` / `footerView` | `headerView={
...
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-message-list` class | `.cometchat-message-bubble-outgoing { background: blue; }` | -
+--- - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +## Accessibility -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +Message bubbles are rendered as semantic elements. Date separators provide temporal context. The list supports keyboard scrolling. Thread reply counts are interactive and keyboard-focusable. Reaction buttons activate on Enter/Space. Avatar images include the sender name as alt text. - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +--- - return chatUser ? ( -
- -
- ) : null; -} -``` +--- -
+## Props -
+All props are optional. Sorted alphabetically. -### Events +### customSoundForMessages -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +URL to a custom audio file for incoming message notifications. -The list of events emitted by the Message List component is as follows. +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | -| Event | Description | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| **ccOpenChat** | this event alerts the listeners if the logged-in user has opened a user or a group chat. | -| **ccMessageEdited** | Triggers whenever a loggedIn user edits any message from the list of messages .it will have three states such as: inProgress, success and error. | -| **ccReplyToMessage** | Triggers whenever a loggedIn user replies to any message from the list of messages .it will have three states such as: inProgress, success and error. | -| **ccMessageDeleted** | Triggers whenever a loggedIn user deletes any message from the list of messages. | -| **ccActiveChatChanged** | This event is triggered when the user navigates to a particular chat window. | -| **ccMessageRead** | Triggers whenever a loggedIn user reads any message. | +--- -Adding `CometChatMessageEvents` Listener's +### disableSoundForMessages - - -```ts -import { CometChatMessageEvents, CometChatUIEvents } from "@cometchat/chat-uikit-react"; +Disables the notification sound for incoming messages. -const ccOpenChat = CometChatUIEvents.ccOpenChat.subscribe(() => { - // Your Code -}); +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | -const ccMessageEdited = CometChatMessageEvents.ccMessageEdited.subscribe(() => { - // Your Code -}); +--- -const ccReplyToMessage = CometChatMessageEvents.ccReplyToMessage.subscribe(() => { - // Your Code -}); +### emptyView -const ccMessageDeleted = CometChatMessageEvents.ccMessageDeleted.subscribe(() => { - // Your Code -}); +Custom component displayed when there are no messages. -const ccActiveChatChanged = CometChatUIEvents.ccActiveChatChanged.subscribe(() => { - // Your Code -}); +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in empty state | -const ccMessageRead = CometChatMessageEvents.ccMessageRead.subscribe(() => { - // Your Code -}); -``` +--- - +### errorView - -```js -import { CometChatMessageEvents, CometChatUIEvents } from "@cometchat/chat-uikit-react"; +Custom component displayed when an error occurs. -const ccOpenChat = CometChatUIEvents.ccOpenChat.subscribe(() => { - // Your Code -}); +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in error state | -const ccMessageEdited = CometChatMessageEvents.ccMessageEdited.subscribe(() => { - // Your Code -}); +--- -const ccReplyToMessage = CometChatMessageEvents.ccReplyToMessage.subscribe(() => { - // Your Code -}); +### footerView -const ccMessageDeleted = CometChatMessageEvents.ccMessageDeleted.subscribe(() => { - // Your Code -}); +Custom component displayed below the message list. -const ccActiveChatChanged = CometChatUIEvents.ccActiveChatChanged.subscribe(() => { - // Your Code -}); +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | -const ccMessageRead = CometChatMessageEvents.ccMessageRead.subscribe(() => { - // Your Code -}); -``` +--- - +### goToMessageId - +Scrolls to the specified message on initial load. -*** +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | -Removing `CometChatMessageEvents` Listener's +--- - - -```ts -ccMessageEdited?.unsubscribe(); -ccReplyToMessage?.unsubscribe(); -ccActiveChatChanged?.unsubscribe(); -``` +### group - +The group for group conversation messages. - -```js -ccMessageEdited?.unsubscribe(); -ccReplyToMessage?.unsubscribe(); -ccActiveChatChanged?.unsubscribe(); -``` +| | | +| --- | --- | +| Type | `CometChat.Group` | +| Default | `undefined` | - +--- - +### headerView -*** +Custom component displayed above the message list. -## Customization +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | `undefined` | -To fit your app's design requirements, you can customize the appearance of the Message List component. We provide exposed properties that allow you to modify the experience and behavior according to your specific needs. +--- -### Style +### hideAvatar -You can set the css to the MessageList Component Component to customize the styling. +Hides avatars on messages. -**Example** +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - - - +--- - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +### hideCopyMessageOption -; -``` +Hides the copy message option. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - -```css -.cometchat-message-bubble__body - .cometchat-text-bubble.cometchat-text-bubble-incoming - .cometchat-text-bubble__body-text { - font-family: "SF Pro"; -} -``` +--- - +### hideDateSeparator - +Hides date separators between message groups. -### Functionality +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. +--- - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +### hideDeleteMessageOption -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +Hides the delete message option. - return chatUser ? ( -
- -
- ) : null; -} -``` +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -
+--- - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; +### hideEditMessageOption -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +Hides the edit message option. - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - return chatUser ? ( -
- -
- ) : null; -} -``` +--- -
+### hideError -
+Hides the default and custom error views. -*** - -Below is a list of customizations along with corresponding code snippets - -| Property | Description | Code | -| ------------------------------------ | ------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| **Hide Date Separator** | Hides the visibility of the date separator in the message list. | `hideDateSeparator={true}` | -| **Hide Sticky Date** | Hides the sticky date header in the message list. | `hideStickyDate={true}` | -| **Hide Receipts** | Hides the visibility of receipts in the message list. | `hideReceipts={true}` | -| **Hide Error** | Hides the default & custom error view passed in the `errorView` prop. | `hideError={true}` | -| **Hide Reply In Thread Option** | Hides the option to reply to messages in a thread. | `hideReplyInThreadOption={true}` | -| **Hide Translate Message Option** | Hides the option to translate messages. | `hideTranslateMessageOption={true}` | -| **Hide Edit Message Option** | Hides the option to edit messages. | `hideEditMessageOption={true}` | -| **Hide Delete Message Option** | Hides the option to delete messages. | `hideDeleteMessageOption={true}` | -| **Hide Reaction Option** | Hides the option to react to messages. | `hideReactionOption={true}` | -| **Hide Message Privately Option** | Hides the option to message a user privately. | `hideMessagePrivatelyOption={true}` | -| **Hide Copy Message Option** | Hides the option to copy messages. | `hideCopyMessageOption={true}` | -| **Hide Message Info Option** | Hides the option to view message information. | `hideMessageInfoOption={true}` | -| **Hide Reply Option** | Hides the reply option for a message. | `hideReplyOption={true}` | -| **Hide Avatar** | Hides avatars for messages. | `hideAvatar={true}` | -| **Hide Group Action Messages** | Hides group action messages. | `hideGroupActionMessages={true}` | -| **Hide Conversation Starters** | Hides the visibility of the conversation starters in the message list. | `hideConversationStarters={true}` | -| **Hide Smart Replies** | Hides the visibility of the smart replies in the message list. | `hideSmartReplies={true}` | -| **Hide Moderation View** | Hides the moderation view shown below the message bubble in the bottom view when a message is moderated. | `hideModerationView={true}` | -| **Hide Flag Message Option** | Hides the "Report Message" option from message actions menu. | `hideFlagMessageOption={true}` | -| **Hide Flag Remark Field** | Hides the remark text area in the flag message dialog. | `hideFlagRemarkField={true}` | -| **Parent Message ID** | Unique identifier of the parent message for displaying threaded conversations. | `parentMessageId={1234}` | -| **User** | A `CometChat.User` object representing the participant of the chat. | `user={chatUser}` | -| **Group** | A `CometChat.Group` object representing the group whose chat messages are displayed. | `group={chatGroup}` | -| **Message Alignment** | Specifies the alignment of messages in the list (e.g., left, right). | `messageAlignment={MessageListAlignment.left}` | -| **Scroll To Bottom On New Messages** | Automatically scrolls the message list to the bottom when a new message arrives. | `scrollToBottomOnNewMessages={true}` | -| **Quick Options Count** | Specifies how many message options are visible in the main menu by default. | `quickOptionsCount={3}` | -| **Disable Sound For Messages** | Disables the sound effect when new messages arrive. | `disableSoundForMessages={true}` | -| **Custom Sound For Messages** | Specifies a custom sound file to play when new messages arrive. | `customSoundForMessages="sound.mp3"` | -| **Smart Replies Keywords** | Sets the keywords on which the smart replies should be triggered in the message list. | `smartRepliesKeywords={['why', 'how']}` | -| **Smart Replies Delay Duration** | Sets the delay duration (in milliseconds) before smart replies are shown. | `smartRepliesDelayDuration={5000}` | -| **Start From Unread Messages** | When set to true, the chat will load from the first unread message if unread messages exist, otherwise loads from the latest messages. Default is false. | `startFromUnreadMessages={true}` | -| **Show Mark Unread Option** | When set to true, shows the "Mark Unread" option in the message actions menu. This option will only appear for received messages, not for the user's own messages. Default is false. | `showMarkAsUnreadOption={true}` | -| **Empty View** | Custom empty state view to display when there are no messages. | `emptyView={}` | -| **Error View** | A custom view displayed when there are no messages. | `errorView={}` | -| **Loading View** | A custom view displayed while messages are being fetched. | `loadingView={}` | -| **Go To MessageId** | The ID of the message that the list should automatically scroll to when it is first loaded. | `goToMessageId={1}` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -#### Templates - -[CometChatMessageTemplate](/ui-kit/react/message-template) is a pre-defined structure for creating message views that can be used as a starting point or blueprint for creating message views often known as message bubbles. For more information, you can refer to [CometChatMessageTemplate](/ui-kit/react/message-template). - -You can set message Templates to MessageList by using the following code snippet. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatMessageList, - ChatConfigurator, - CometChatActionsIcon, -} from "@cometchat/chat-uikit-react"; +--- -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +### hideFlagMessageOption - const getCustomOptions = ( - loggedInUser: CometChat.User, - message: CometChat.BaseMessage, - group?: CometChat.Group - ) => { - const defaultOptions: any = - ChatConfigurator.getDataSource().getMessageOptions( - loggedInUser, - message, - group - ); - const myView: any = new CometChatActionsIcon({ - id: "custom id", - title: "your custom title for options", - iconURL: "your custom icon url for options", - onClick: () => console.log("custom action"), - }); - defaultOptions.push(myView); - return defaultOptions; - }; +Hides the "Report Message" option. - const getTemplates = () => { - let templates = ChatConfigurator.getDataSource().getAllMessageTemplates(); - templates.map((data) => { - data.options = ( - loggedInUser: CometChat.User, - message: CometChat.BaseMessage, - group?: CometChat.Group - ) => getCustomOptions(loggedInUser, message, group); - }); - return templates; - }; +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - return chatUser ? ( -
- -
- ) : null; -} -``` +--- -
+### hideFlagRemarkField - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatMessageList, - ChatConfigurator, - CometChatActionsIcon, -} from "@cometchat/chat-uikit-react"; +Hides the remark text area in the flag message dialog. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideGroupActionMessages + +Hides group action messages (join, leave, kick, etc.). + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideMessageInfoOption + +Hides the message info option. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideMessagePrivatelyOption + +Hides the "Message Privately" option. -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +--- - const getCustomOptions = (loggedInUser, message, theme, group) => { - const defaultOptions = ChatConfigurator.getDataSource().getMessageOptions( - loggedInUser, - message, - group - ); - const myView = new CometChatActionsIcon({ - id: "custom id", - title: "your custom title for options", - iconURL: "your custom icon url for options", - onClick: () => console.log("custom action"), - }); - defaultOptions.push(myView); - return defaultOptions; - }; +### hideModerationView - const getTemplates = () => { - let templates = ChatConfigurator.getDataSource().getAllMessageTemplates(); - templates.map((data) => { - data.options = (loggedInUser, message, group) => - getCustomOptions(loggedInUser, message, group); - }); - return templates; - }; +Hides the moderation view below moderated messages. - return chatUser ? ( -
- -
- ) : null; -} -``` +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -
+--- -
+### hideReactionOption -*** +Hides the reaction option. -#### Separator DateTime Format +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -The `separatorDateTimeFormat` property allows you to customize the **Date Separator** timestamp displayed in the Message List. +--- -Default Date Time Format: +### hideReceipts -```javascript -new CalendarObject({ - today: "today" // Example: "today" - yesterday: "yesterday", // Example: "yesterday" - otherDays: `DD MMM, YYYY`, // Example: "25 Jan, 2025" -}); -``` +Hides read/delivery receipt indicators. -The following example demonstrates how to modify the **Date Separator** timestamp format using a custom [`CalendarObject`](/ui-kit/react/localize#calendarobject). +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - - -```ts -import { - CometChatMessageList, - CalendarObject, -} from "@cometchat/chat-uikit-react"; +--- -// Define a custom date format pattern -function getDateFormat() { - const dateFormat = new CalendarObject({ - today: `hh:mm A`, // Example: "10:30 AM" - yesterday: `[yesterday]`, // Example: "yesterday" - otherDays: `DD/MM/YYYY`, // Example: "25/05/2025" - }); - return dateFormat; -} +### hideReplyInThreadOption -// Apply the custom format to the CometChatMessageList component -; -``` +Hides the "Reply in Thread" option. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- - +### hideReplyOption -**Fallback Mechanism** +Hides the reply option. -* If you **do not** pass any property in the [**CalendarObject**](/ui-kit/react/localize#calendarobject), the component will first check the [**global configuration**](/ui-kit/react/localize#customisation). If the property is **also missing in the global configuration**, it will **fallback to the component's default formatting**. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- -*** +### hideStickyDate -#### Sticky DateTime Format +Hides the sticky date header. -The `stickyDateTimeFormat` property allows you to customize the **Sticky Date** timestamp displayed in the Message List. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -!\[]\(Screenshot HERE) +--- -Default Date Time Format: +### hideTranslateMessageOption -```javascript -new CalendarObject({ - today: "today" // Example: "today" - yesterday: "yesterday", // Example: "yesterday" - otherDays: `DD MMM, YYYY`, // Example: "25 Jan, 2025" -}); -``` +Hides the translate message option. -The following example demonstrates how to modify the **Sticky Date** timestamp format using a custom [`CalendarObject`](/ui-kit/react/localize#calendarobject). +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - - -```ts -import { - CometChatMessageList, - CalendarObject, -} from "@cometchat/chat-uikit-react"; +--- -// Define a custom date format pattern -function getDateFormat() { - const dateFormat = new CalendarObject({ - today: `hh:mm A`, // Example: "10:30 AM" - yesterday: `[yesterday]`, // Example: "yesterday" - otherDays: `DD/MM/YYYY`, // Example: "25/05/2025" - }); - return dateFormat; -} +### isAgentChat -// Apply the custom format to the CometChatMessageList component -; -``` +Toggles AI Agent functionality for the message list. - +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - +--- - +### loadingView -**Fallback Mechanism** +Custom component displayed during the loading state. -* If you **do not** pass any property in the [**CalendarObject**](/ui-kit/react/localize#calendarobject), the component will first check the [**global configuration**](/ui-kit/react/localize#customisation). If the property is **also missing in the global configuration**, it will **fallback to the component's default formatting**. +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in shimmer | - +--- -*** +### loadLastAgentConversation -#### Message SentAt DateTime Format +Loads the most recent existing agent conversation on mount. -The `messageSentAtDateTimeFormat` property allows you to customize the **Message SentAt** timestamp displayed in the Message List. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -Default Date Time Format: +--- -```javascript -new CalendarObject({ - today: "hh:mm A" // Example: "12:00 PM" - yesterday: "hh:mm A", // Example: "01:00 AM" - otherDays: `hh:mm A`, // Example: "09:30 PM" -}); -``` +### messageAlignment -The following example demonstrates how to modify the **Message SentAt** timestamp format using a custom [`CalendarObject`](/ui-kit/react/localize#calendarobject). +Controls message alignment. - - -```ts -import { - CometChatMessageList, - CalendarObject, -} from "@cometchat/chat-uikit-react"; +| | | +| --- | --- | +| Type | `MessageListAlignment` | +| Default | `MessageListAlignment.standard` | -// Define a custom date format pattern -function getDateFormat() { - const dateFormat = new CalendarObject({ - today: `hh:mm A`, // Example: "10:30 AM" - yesterday: `[yesterday]`, // Example: "yesterday" - otherDays: `DD/MM/YYYY`, // Example: "25/05/2025" - }); - return dateFormat; +```ts lines +enum MessageListAlignment { + left, // 0 + standard, // 1 } - -// Apply the custom format to the CometChatMessageList component -; ``` - +--- - +### messageInfoDateTimeFormat - +Format for message info timestamps. -**Fallback Mechanism** +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default | -* If you **do not** pass any property in the [**CalendarObject**](/ui-kit/react/localize#calendarobject), the component will first check the [**global configuration**](/ui-kit/react/localize#customisation). If the property is **also missing in the global configuration**, it will **fallback to the component's default formatting**. +--- - +### messageSentAtDateTimeFormat -*** +Format for message sent-at timestamps. -#### Message Info DateTime Format +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default | -The `messageInfoDateTimeFormat` property allows you to customize the **Message Info** timestamp displayed in the Message List. +--- -Default Date Time Format: +### messagesRequestBuilder -```ruby -new CalendarObject({ - today: `DD MMM, hh:mm A`, // Example: "29 Jan, 04:34 AM" - yesterday: `DD MMM, hh:mm A`, // Example: "29 Jan, 04:34 AM" - otherDays: `DD MMM, hh:mm A`, // Example: "29 Jan, 04:34 AM" -}); -``` +Controls which messages load and in what order. -The following example demonstrates how to modify the **Message Info** timestamp format using a custom [`CalendarObject`](/ui-kit/react/localize#calendarobject). +| | | +| --- | --- | +| Type | `CometChat.MessagesRequestBuilder` | +| Default | SDK default | - - -```ts -import { - CometChatMessageList, - CalendarObject, -} from "@cometchat/chat-uikit-react"; +UID/GUID are always overridden internally. -// Define a custom date format pattern -function getDateFormat() { - const dateFormat = new CalendarObject({ - today: `hh:mm A`, // Example: "10:30 AM" - yesterday: `[yesterday]`, // Example: "yesterday" - otherDays: `DD/MM/YYYY`, // Example: "25/05/2025" - }); - return dateFormat; -} +--- -// Apply the custom format to the CometChatMessageList component -; -``` +### onError - +Callback fired when the component encounters an error. - +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | - +--- -**Fallback Mechanism** +### onReactionClick -* If you **do not** pass any property in the [**CalendarObject**](/ui-kit/react/localize#calendarobject), the component will first check the [**global configuration**](/ui-kit/react/localize#customisation). If the property is **also missing in the global configuration**, it will **fallback to the component's default formatting**. +Callback fired when a reaction on a message is clicked. - +| | | +| --- | --- | +| Type | `(reaction: CometChat.ReactionCount, message: CometChat.BaseMessage) => void` | +| Default | `undefined` | -*** +--- -#### Headerview +### onReactionListItemClick -You can set custom headerView to the Message List component using the following method. +Callback fired when a reaction list item is clicked. -The customized chat interface is displayed below. +| | | +| --- | --- | +| Type | `(reaction: CometChat.Reaction, message: CometChat.BaseMessage) => void` | +| Default | `undefined` | - - - +--- -Use the following code to achieve the customization shown above. +### onThreadRepliesClick - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -import notesIcon from "../../assets/notesIcon.svg"; -import pinnedIcon from "../../assets/pinnedIcon.svg"; -import savedIcon from "../../assets/savedIcon.svg"; +Callback fired when a threaded message reply count is clicked. -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); +| | | +| --- | --- | +| Type | `(message: CometChat.BaseMessage) => void` | +| Default | `undefined` | - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +--- - const getHeaderView = () => { - return ( -
- - - -
- ); - }; +### parentMessageId - return chatUser ? ( -
- -
- ) : null; -} -``` +Displays threaded conversation for the specified parent message. -
+| | | +| --- | --- | +| Type | `number` | +| Default | `undefined` | - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -import notesIcon from "../../assets/notesIcon.svg"; -import pinnedIcon from "../../assets/pinnedIcon.svg"; -import savedIcon from "../../assets/savedIcon.svg"; +--- -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +### quickOptionsCount - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +Number of message options visible in the main menu before overflow. - const getHeaderView = () => { - return ( -
- - - -
- ); - }; +| | | +| --- | --- | +| Type | `number` | +| Default | `3` | - return chatUser ? ( -
- -
- ) : null; -} -``` +--- -
+### reactionsRequestBuilder - -```css -.header-view { - display: flex; - width: 100%; - padding: 3px 16px; - align-items: flex-start; - gap: 5px; - background: #edeafa; -} +Controls how reactions are fetched for messages. -.header-view .cometchat .cometchat-button { - width: auto; - height: 32px; - border-radius: 1000px; - border: 1px solid #e8e8e8; - background: #fafafa; - color: #6852d6; - text-align: center; -} +| | | +| --- | --- | +| Type | `CometChat.ReactionsRequestBuilder` | +| Default | `undefined` | -.header-view .cometchat .cometchat-button__text { - color: #6852d6; - text-align: center; - font: 400 12px/14.4px Roboto; - font-style: normal; -} +--- -.header-view .cometchat .cometchat-button__icon { - background-color: #6852d6; - display: flex; - justify-content: center; - align-items: center; -} -``` +### scrollToBottomOnNewMessages - +Auto-scrolls to bottom when new messages arrive. -
+| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -*** +--- -#### FooterView +### separatorDateTimeFormat -You can set custom footerview to the Message List component using the following method. +Format for date separator timestamps. -The customized chat interface is displayed below. +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default | - - - +--- -Use the following code to achieve the customization shown above. +### showConversationStarters - - -```ts -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -import iceBreakersIcon from "../../assets/iceBreakersIcon.svg"; -import callIcon from "../../assets/callIcon.svg"; -import instagramIcon from "../../assets/instagramIcon.svg"; -import snapchatIcon from "../../assets/snapchatIcon.svg"; +Shows AI conversation starters. -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +--- - const getFooterView = () => { - return ( -
- - - - -
- ); - }; +### showMarkAsUnreadOption - return chatUser ? ( -
- -
- ) : null; -} -``` +Shows "Mark Unread" option in message actions. -
+| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - -```js -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -import iceBreakersIcon from "../../assets/iceBreakersIcon.svg"; -import callIcon from "../../assets/callIcon.svg"; -import instagramIcon from "../../assets/instagramIcon.svg"; -import snapchatIcon from "../../assets/snapchatIcon.svg"; +--- -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(null); +### showScrollbar - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +Shows the scrollbar in the message list. - const getFooterView = () => { - return ( -
- - - - -
- ); - }; +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - return chatUser ? ( -
- -
- ) : null; -} -``` +--- -
+### showSmartReplies - -```css -.footer-view { - display: flex; - width: 100%; - padding: 3px 16px; - align-items: flex-start; - gap: 5px; - background: #edeafa; -} +Shows AI smart replies. -.footer-view .cometchat .cometchat-button { - width: auto; - height: 32px; - border-radius: 1000px; - border: 1px solid #e8e8e8; - background: #fafafa; - color: #6852d6; - text-align: center; -} +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | -.footer-view .cometchat .cometchat-button__text { - color: #6852d6; - text-align: center; - font: 400 12px/14.4px Roboto; - font-style: normal; -} +--- -.footer-view .cometchat .cometchat-button__icon { - background-color: #6852d6; - display: flex; - justify-content: center; - align-items: center; -} -``` +### smartRepliesDelayDuration - +Delay in milliseconds before smart replies appear. -
+| | | +| --- | --- | +| Type | `number` | +| Default | `10000` | -*** +--- -#### TextFormatters +### smartRepliesKeywords -Assigns the list of text formatters. If the provided list is not null, it sets the list. Otherwise, it assigns the default text formatters retrieved from the data source. To configure the existing Mentions look and feel check out [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide) +Keywords that trigger smart replies. - - -```ts -import { CometChatTextFormatter } from "@cometchat/chat-uikit-react"; -import DialogHelper from "./Dialog"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; +| | | +| --- | --- | +| Type | `string[]` | +| Default | `["what", "when", "why", "who", "where", "how", "?"]` | -class ShortcutFormatter extends CometChatTextFormatter { - private shortcuts: { [key: string]: string } = {}; - private dialogIsOpen: boolean = false; - private dialogHelper = new DialogHelper(); - private currentShortcut: string | null = null; // Track the currently open shortcut - - constructor() { - super(); - this.setTrackingCharacter("!"); - CometChat.callExtension("message-shortcuts", "GET", "v1/fetch", undefined) - .then((data: any) => { - if (data && data.shortcuts) { - this.shortcuts = data.shortcuts; - } - }) - .catch((error) => console.log("error fetching shortcuts", error)); - } +--- - onKeyDown(event: KeyboardEvent) { - const caretPosition = - this.currentCaretPosition instanceof Selection - ? this.currentCaretPosition.anchorOffset - : 0; - const textBeforeCaret = this.getTextBeforeCaret(caretPosition); - - const match = textBeforeCaret.match(/!([a-zA-Z]+)$/); - if (match) { - const shortcut = match[0]; - const replacement = this.shortcuts[shortcut]; - if (replacement) { - // Close the currently open dialog, if any - if (this.dialogIsOpen && this.currentShortcut !== shortcut) { - this.closeDialog(); - } - this.openDialog(replacement, shortcut); - } - } - } +### startFromUnreadMessages - getCaretPosition() { - if (!this.currentCaretPosition?.rangeCount) return { x: 0, y: 0 }; - const range = this.currentCaretPosition?.getRangeAt(0); - const rect = range.getBoundingClientRect(); - return { - x: rect.left, - y: rect.top, - }; - } +Loads from the first unread message if available. - openDialog(buttonText: string, shortcut: string) { - this.dialogHelper.createDialog( - () => this.handleButtonClick(buttonText), - buttonText - ); - this.dialogIsOpen = true; - this.currentShortcut = shortcut; - } +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - closeDialog() { - this.dialogHelper.closeDialog(); // Use DialogHelper to close the dialog - this.dialogIsOpen = false; - this.currentShortcut = null; - } +--- - handleButtonClick = (buttonText: string) => { - if (this.currentCaretPosition && this.currentRange) { - // Inserting the replacement text corresponding to the shortcut - const shortcut = Object.keys(this.shortcuts).find( - (key) => this.shortcuts[key] === buttonText - ); - if (shortcut) { - const replacement = this.shortcuts[shortcut]; - this.addAtCaretPosition( - replacement, - this.currentCaretPosition, - this.currentRange - ); - } - } - if (this.dialogIsOpen) { - this.closeDialog(); - } - }; +### stickyDateTimeFormat - getFormattedText(text: string): string { - return text; - } +Format for sticky date header timestamps. - private getTextBeforeCaret(caretPosition: number): string { - if ( - this.currentRange && - this.currentRange.startContainer && - typeof this.currentRange.startContainer.textContent === "string" - ) { - const textContent = this.currentRange.startContainer.textContent; - if (textContent.length >= caretPosition) { - return textContent.substring(0, caretPosition); - } - } - return ""; - } -} +| | | +| --- | --- | +| Type | `CalendarObject` | +| Default | Component default | -export default ShortcutFormatter; -``` +--- - +### templates - -```tsx -import React from "react"; -import ReactDOM from "react-dom"; +Custom message bubble templates. -interface DialogProps { - onClick: () => void; - buttonText: string; -} +| | | +| --- | --- | +| Type | `CometChatMessageTemplate[]` | +| Default | SDK defaults | -const Dialog: React.FC = ({ onClick, buttonText }) => { - console.log("buttonText", buttonText); +See [CometChatMessageTemplate](/ui-kit/react/message-template). - return ( -
- -
- ); -}; +--- -export default class DialogHelper { - private dialogContainer: HTMLDivElement | null = null; +### textFormatters - createDialog(onClick: () => void, buttonText: string) { - this.dialogContainer = document.createElement("div"); - document.body.appendChild(this.dialogContainer); +Custom text formatters for message content. - ReactDOM.render( - , - this.dialogContainer - ); - } +| | | +| --- | --- | +| Type | `CometChatTextFormatter[]` | +| Default | Default formatters from data source | - closeDialog() { - if (this.dialogContainer) { - ReactDOM.unmountComponentAtNode(this.dialogContainer); - this.dialogContainer.remove(); - this.dialogContainer = null; - } - } -} -``` +See [CometChatMentionsFormatter](/ui-kit/react/mentions-formatter-guide). -
+--- - -```tsx -import React from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatMessageList } from "@cometchat/chat-uikit-react"; -import ShortcutFormatter from "./ShortCutFormatter"; +### user -export function MessageListDemo() { - const [chatUser, setChatUser] = React.useState(); - React.useEffect(() => { - CometChat.getUser("uid").then((user) => { - setChatUser(user); - }); - }, []); +The user for 1-on-1 conversation messages. - return chatUser ? ( -
- -
- ) : null; -} -``` +| | | +| --- | --- | +| Type | `CometChat.User` | +| Default | `undefined` | -
+--- -
+## Events + +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatMessageEvents.ccMessageEdited` | `IMessages` | Message edited | +| `CometChatMessageEvents.ccMessageDeleted` | `CometChat.BaseMessage` | Message deleted | +| `CometChatMessageEvents.ccMessageRead` | `CometChat.BaseMessage` | Message read | +| `CometChatMessageEvents.ccReplyToMessage` | `IMessages` | User replies to message | +| `CometChatUIEvents.ccOpenChat` | `IOpenChat` | Chat opened | +| `CometChatUIEvents.ccActiveChatChanged` | `IActiveChatChanged` | Active chat changes | + +--- -*** +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-message-list` | +| Error state | `.cometchat-message-list__error-state-view` | +| Footer smart replies | `.cometchat-message-list__footer-smart-replies` | +| Footer conversation starters | `.cometchat-message-list__footer-conversation-starter` | +| Outgoing bubble | `.cometchat-message-bubble-outgoing` | +| Incoming bubble | `.cometchat-message-bubble-incoming` | +| Status info view | `.cometchat-message-bubble__status-info-view` | +| Thread view replies | `.cometchat-message-bubble__thread-view-replies` | +| Text bubble | `.cometchat-message-bubble .cometchat-text-bubble` | +| Delete bubble | `.cometchat-message-bubble .cometchat-delete-bubble` | diff --git a/ui-kit/react/message-template.mdx b/ui-kit/react/message-template.mdx index 7659b7286..d56c04fae 100644 --- a/ui-kit/react/message-template.mdx +++ b/ui-kit/react/message-template.mdx @@ -1,282 +1,166 @@ --- title: "Message Template" +description: "Data structure defining how message bubbles render in CometChatMessageList — controls header, content, footer, bottom, status info, reply, and bubble views per message type and category." --- + +```json +{ + "component": "CometChatMessageTemplate", + "kind": "model-class", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatMessageTemplate } from \"@cometchat/chat-uikit-react\";", + "description": "Data structure defining how message bubbles render in CometChatMessageList. Each template maps a type+category pair to view functions.", + "usage": "Pass an array of CometChatMessageTemplate instances to CometChatMessageList via the templates prop.", + "properties": { + "type": { "type": "string", "required": true, "description": "CometChat message type" }, + "category": { "type": "string", "default": "\"\"", "description": "CometChat message category" }, + "headerView": { "type": "function | null", "default": "null", "description": "Custom header view function" }, + "contentView": { "type": "function | null", "default": "null", "description": "Custom content view function" }, + "footerView": { "type": "function | null", "default": "null", "description": "Custom footer view function" }, + "bottomView": { "type": "function | null", "default": "null", "description": "Custom bottom view function" }, + "bubbleView": { "type": "function | null", "default": "null", "description": "Replaces entire bubble" }, + "statusInfoView": { "type": "function | null", "default": "null", "description": "Custom status info view function" }, + "replyView": { "type": "function | null", "default": "null", "description": "Custom reply preview function" }, + "options": { "type": "function", "description": "Returns action sheet items for long-press" } + }, + "relatedComponents": ["CometChatMessageList"], + "cssRootClass": null, + "events": null +} +``` + -## Overview - -MessageTemplate provides you with the capability to define and customize both the structure and the behavior of the Message Bubble. It acts as a schema or design blueprint for the creation of a variety of Message Bubble components, allowing you to manage the appearance and interactions of Message Bubble within your application effectively and consistently. - -### Structure - - - - - -The Message Bubble structure can typically be broken down into the following views: - -1. **Leading view**: This is where the sender's avatar is displayed. It's typically on the left of the Message Bubble for messages from others and on the right for messages from the current user. - -2. **Header view**: This displays the sender's name and is especially useful in group chats where multiple users are sending messages. - -3. **Reply view**: This view can be used to extend the Message Bubble with additional elements. It's typically placed above the Content view. - -4. **Content view**: This is the core of the Message Bubble where the message content (text, images, videos, etc.) is displayed. - -5. **Bottom view**: This view can be used to extend the Message Bubble with additional elements, such as link previews or a 'load more' button for long messages. It's typically placed beneath the Content view. - -6. **Thread view**: This is where the thread reply icon and reply counts are displayed. It's located below the footer view. - -7. **Footer view**: This is where the reactions are displayed. It's located at the bottom of the Message Bubble. - -8. **Status Info view**: This is where the timestamp of the message and its delivery or read status are displayed. It's located inside the Message Bubble just below the content view. - -*** - -### Properties - -MessageTemplate provides you with methods that allow you to alter various properties of the Message Bubble. These properties include aspects such as the `type` and `category` of a message, the appearance and behavior of the header, content, and footer sections of the message bubble, - -1. **type** - - Using `type` you can set the type of CometChatMessage, This will map your MessageTemplate to the corresponding CometChatMessage. You can set the MessageTemplates Type using the following code snippet. - -2. **category** - - Using `category` you can set the category of a MessageTemplate. This will create a MessageTemplate with the specified category and link it with a CometChatMessage of the same category. - - Please refer to our guide on [Message Categories](/sdk/javascript/message-structure-and-hierarchy) for a deeper understanding of message categories. - -3. **headerView** - - The `headerView` method allows you to assign a custom header view to the Message Bubble. By default, it is configured to display the sender's name. - -4. **contentView** - - The `contentView` method allows you to assign a custom content view to the Message Bubble. By default, it displays the Text Bubble, Image Bubble, File Bubble, Audio Bubble, or Video Bubble depending on the message type. - -5. **footerView** - - The `footerView` method allows you to assign a custom Footer view to the Message Bubble. By default it shows thr reactions for the message bubble. - -6. **bottomView** - - The `bottomView` method allows you to assign a custom Bottom view to the Message Bubble. By defuault is has buttons such as link previews or a 'load more' button for long messages. - -7. **bubbleView** +## What It Is - The `bubbleView` method allows you to assign a custom Bubble view to the Message Bubble. By default, headerView, contentView, statusInfoView and footerView together form a message bubble. +`CometChatMessageTemplate` is a model class, not a rendered component. Each instance maps a message `type` + `category` pair to a set of view functions that control how that message renders inside `CometChatMessageList`. Pass an array of templates to the `templates` prop on `CometChatMessageList`. -8. **statusInfoView** +```tsx lines +import { useState, useEffect } from "react"; +import { + CometChatMessageList, + CometChatMessageTemplate, + CometChatUIKit, + CometChatUIKitConstants, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; - The `statusInfoView` method allows you to assign a custom status info view to the Message Bubble. By default, it displays the receipt and timestamp. +function CustomTemplateDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); -9. **replyView** + useEffect(() => { + CometChat.getGroup("guid").then((group) => setChatGroup(group)); - The `replyView` method allows you to assign a custom reply view to the Message Bubble. By default, it displays the preview of the replied message. + const allTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); + const modified = allTemplates.map((t) => { + if ( + t.type === CometChatUIKitConstants.MessageTypes.text && + t.category === CometChatUIKitConstants.MessageCategory.message + ) { + t.headerView = (message: CometChat.BaseMessage) => ( + <>{message.getSender().getName()} • 🗓️ In meeting + ); + } + return t; + }); + setTemplates(modified); + }, []); -10. **options** + if (!chatGroup) return null; - The `options` lets you set the list of actions that a user can perform on a message. This includes actions like reacting to, editing, or deleting a message. + return ; +} +``` -*** +--- -## Customization +## Template Structure -Let's dive into how you can use the [properties](#properties) of MessageTemplate to customize an existing template or add a new one to the [MessageList](/ui-kit/react/message-list) component. +A message bubble is composed of these view slots, each overridable per template: -The first step is to fetch the list of existing templates when you want to modify or add to them. This can be done using the getAllMessageTemplates() method from the DataSource of the CometChatUIKit class. +| View | Default rendering | Signature | +| --- | --- | --- | +| `headerView` | Sender name | `(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, textFormatters?: CometChatTextFormatter[]) => JSX.Element \| null` | +| `contentView` | Text / image / video / audio / file bubble | `(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, textFormatters?: CometChatTextFormatter[]) => JSX.Element \| null` | +| `footerView` | Reactions | `(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => JSX.Element \| null` | +| `bottomView` | Link previews, "load more" | `(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => JSX.Element \| null` | +| `statusInfoView` | Receipt + timestamp | `(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, hideReceipts?: boolean, messageSentAtDateTimeFormat?: CalendarObject, showError?: boolean) => JSX.Element \| null` | +| `replyView` | Reply preview | `(message: CometChat.BaseMessage, alignment?: MessageBubbleAlignment, onReplyViewClicked?: (msg: CometChat.BaseMessage) => void, textFormatters?: CometChatTextFormatter[]) => JSX.Element \| null` | +| `bubbleView` | Entire bubble (overrides all above) | `(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => JSX.Element \| null` | +| `options` | Long-press action sheet | `(loggedInUser: CometChat.User, message: CometChat.BaseMessage, group?: CometChat.Group) => CometChatMessageOption[]` | -```javascript -let definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); -``` +--- -### Existing Templates +## Fetching Existing Templates -You will need to first get the MessageTemplate object for the type of message you want to customize. You will be customizing the text message bubble here. The code snippet to get the Text MessageTemplate is as follows. +Retrieve the built-in templates and modify specific ones: - - -```ts +```tsx lines import { CometChatUIKit, CometChatUIKitConstants, + CometChatMessageTemplate, } from "@cometchat/chat-uikit-react"; -let allTemplates: CometChatMessageTemplate[] = +const allTemplates: CometChatMessageTemplate[] = CometChatUIKit.getDataSource().getAllMessageTemplates(); -for (let i = 0; i < allTemplates.length; i++) { - if (allTemplates[i].type === CometChatUIKitConstants.MessageTypes.text) { - //customize allTemplates[i] - } -} -``` - - - - -```js -import { - CometChatUIKit, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -let allTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); for (let i = 0; i < allTemplates.length; i++) { if (allTemplates[i].type === CometChatUIKitConstants.MessageTypes.text) { - //customize allTemplates[i] + // customize allTemplates[i] } } ``` - - - - -You will be using [Message List](/ui-kit/react/message-list) component using the `templates` prop of `CometChatMessageList` component. - - - -```ts -import { CometChatMessageList } from "@cometchat/uikit-react"; - -; -``` - - - - -```js -import { CometChatMessageList } from "@cometchat/uikit-react"; - -; -``` - - - - +--- -#### HeaderView +## Common Patterns -The `headerView` method of MessageTemplate allows you to add custom views to the header of your message bubbles. In the example below, we will add a custom header view of every text message in the MessageList. +### Custom header with status badge - - -```ts -import React, { useEffect, useState } from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - - let definedTemplates: CometChatMessageTemplate[] = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message - ) { - templates.headerView = (message: CometChat.BaseMessage) => - getHeaderView(message); - return templates; - } - return templates; - }); - setTemplates(template); - }, []); - - const getHeaderView = (message: CometChat.BaseMessage) => { - return <> {message.getSender().getName()} • 🗓️ In meeting; - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```js -import React, { useEffect, useState } from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants, + CometChatMessageTemplate, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -const CustomMessageTemplate = () => { - const [templates, setTemplates] = useState([]); - const [chatGroup, setChatGroup] = useState(null); +function HeaderViewDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + CometChat.getGroup("guid").then((group) => setChatGroup(group)); - let definedTemplates = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { + const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); + const modified = definedTemplates.map((t) => { if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message + t.type === CometChatUIKitConstants.MessageTypes.text && + t.category === CometChatUIKitConstants.MessageCategory.message ) { - templates.headerView = (message: CometChat.BaseMessage) => - getHeaderView(message); - return templates; + t.headerView = (message: CometChat.BaseMessage) => ( + <>{message.getSender().getName()} • 🗓️ In meeting + ); } - return templates; + return t; }); - setTemplates(template); + setTemplates(modified); }, []); - const getHeaderView = (message: CometChat.BaseMessage) => { - return <> {message.getSender().getName()} • 🗓️ In meeting; - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; + if (!chatGroup) return null; -export { CustomMessageTemplate }; + return ; +} ``` -
- -
- -#### Contentview - -The `contentview` method of MessageTemplate allows you to add a custom view to the content of your message bubbles. In the example below, we will add a custom layout to the content view of every text message in the MessageList. +### Custom content view for a custom message type @@ -284,8 +168,8 @@ The `contentview` method of MessageTemplate allows you to add a custom view to t -```ts -import React from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChatMessageList, CometChatUIKit, @@ -293,164 +177,43 @@ import { CometChatMessageTemplate, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -import bannerImage from "../../assets/banner.svg"; -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); +function ContentViewDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + useEffect(() => { + CometChat.getGroup("guid").then((group) => setChatGroup(group)); - let definedTemplates: CometChatMessageTemplate[] = - CometChatUIKit.getDataSource().getAllMessageTemplates(); + const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); const CUSTOM_MESSAGE_TYPE = "customType"; - let customMessageTemplate = new CometChatMessageTemplate({ + const customTemplate = new CometChatMessageTemplate({ type: CUSTOM_MESSAGE_TYPE, category: CometChatUIKitConstants.MessageCategory.custom, - contentView: (message: CometChat.BaseMessage) => getContentView(message), - }); - definedTemplates.push(customMessageTemplate); - setTemplates(definedTemplates); - }, []); - - const getContentView = (message: CometChat.BaseMessage) => { - return ( -
-
- -
-
-
+ contentView: (message: CometChat.BaseMessage) => ( +
+
Blazer Casual
Men's Tailored Regular Fit Blazer
-
-
- $37.99{" "} - $74.00 -
-
- Free Delivery + $37.99 $74.00
+
Buy now
-
Buy now
-
- ); - }; - - const getMessageRequestBuilder = () => { - const CUSTOM_MESSAGE_TYPE = "customType"; - let categories = CometChatUIKit.getDataSource().getAllMessageCategories(); - categories.push(CometChatUIKitConstants.MessageCategory.custom); - let types = CometChatUIKit.getDataSource().getAllMessageTypes(); - types.push(CUSTOM_MESSAGE_TYPE); - return new CometChat.MessagesRequestBuilder() - .setCategories(categories) - .setTypes(types) - .hideReplies(true) - .setLimit(30); - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; - -export { CustomMessageTemplate }; -``` - - - - -```js -import React from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, - CometChatMessageTemplate, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import bannerImage from "../../assets/banner.svg"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState([]); - const [chatGroup, setChatGroup] = React.useState(); - - React.useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); + ), }); - - let definedTemplates = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const CUSTOM_MESSAGE_TYPE = "customType"; - let customMessageTemplate = new CometChatMessageTemplate({ - type: CUSTOM_MESSAGE_TYPE, - category: CometChatUIKitConstants.MessageCategory.custom, - contentView: (message: CometChat.BaseMessage) => getContentView(message), - }); - definedTemplates.push(customMessageTemplate); + definedTemplates.push(customTemplate); setTemplates(definedTemplates); }, []); - const getContentView = (message: CometChat.BaseMessage) => { - return ( -
-
- -
-
-
-
Blazer Casual
-
- Men's Tailored Regular Fit Blazer -
-
-
-
- $37.99{" "} - $74.00 -
-
- Free Delivery -
-
-
-
Buy now
-
- ); - }; - const getMessageRequestBuilder = () => { const CUSTOM_MESSAGE_TYPE = "customType"; - let categories = CometChatUIKit.getDataSource().getAllMessageCategories(); + const categories = CometChatUIKit.getDataSource().getAllMessageCategories(); categories.push(CometChatUIKitConstants.MessageCategory.custom); - let types = CometChatUIKit.getDataSource().getAllMessageTypes(); + const types = CometChatUIKit.getDataSource().getAllMessageTypes(); types.push(CUSTOM_MESSAGE_TYPE); return new CometChat.MessagesRequestBuilder() .setCategories(categories) @@ -459,30 +222,20 @@ const CustomMessageTemplate = () => { .setLimit(30); }; + if (!chatGroup) return null; + return ( -
- {chatGroup && ( - - )} -
+ ); -}; - -export { CustomMessageTemplate }; +} ``` -
- - -```css -.content-view__header-banner { - border-radius: 12px; -} - + +```css lines .content-view__body { height: 105px; display: flex; @@ -490,7 +243,6 @@ export { CustomMessageTemplate }; flex-direction: column; text-align: left; gap: 16px; - align-self: stretch; } .content-view__body-title { @@ -514,32 +266,21 @@ export { CustomMessageTemplate }; text-decoration: line-through; } -.content-view__body-delivery-type { - color: #727272; - font: 400 14px/1.2 Roboto; -} - .content-footer { display: flex; height: 40px; padding: 8px 20px; justify-content: center; align-items: center; - gap: 8px; - align-self: stretch; border-top: 1px solid #dcdcdc; color: #6852d6; font: 500 14px/1.2 Roboto; } ``` - - -#### BottomView - -The `bottomView` method of MessageTemplate allows you to add a custom button view to your message bubbles. In the example below, we will add a custom bottom view to every text message in the MessageList. +### Custom bottom view with warning @@ -547,116 +288,48 @@ The `bottomView` method of MessageTemplate allows you to add a custom button vie -```ts -import React, { useEffect, useState } from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants, + CometChatMessageTemplate, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); +function BottomViewDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + CometChat.getGroup("guid").then((group) => setChatGroup(group)); - let definedTemplates: CometChatMessageTemplate[] = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { + const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); + const modified = definedTemplates.map((t) => { if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message + t.type === CometChatUIKitConstants.MessageTypes.text && + t.category === CometChatUIKitConstants.MessageCategory.message ) { - templates.bottomView = (message: CometChat.BaseMessage) => - getBottomView(message); - return templates; + t.bottomView = (message: CometChat.BaseMessage) => ( +
+ According to guidelines you cannot share contact +
+ ); } - return templates; + return t; }); - setTemplates(template); + setTemplates(modified); }, []); - const getBottomView = (message: CometChat.BaseMessage) => { - return ( -
- According to guidelines you cannot - share contact -
- ); - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```js -import React, { useEffect, useState } from "react"; -import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants } from '@cometchat/chat-uikit-react'; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState([]); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }) - - let definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if (templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message) { - templates.bottomView = (message: CometChat.BaseMessage) => getBottomView(message) - return templates; - } - return templates - }) - setTemplates(template); - }, []); - - const getBottomView = (message: CometChat.BaseMessage) => { - return ( -
- According to guidelines you cannot share contact -
) - } - - return ( -
- {chatGroup && } -
- ); -}; + if (!chatGroup) return null; -export { CustomMessageTemplate }; + return ; +} ``` -
- - -```css + +```css lines .cometchat .cometchat-message-bubble__body { border-radius: 12px 12px 0px 0px; } @@ -673,421 +346,91 @@ export { CustomMessageTemplate }; 0deg, rgba(244, 70, 73, 0.2) 0%, rgba(244, 70, 73, 0.2) 100% - ), #fff; + ), + #fff; padding: 0px 8px 0px 5px; } - -.error-icon { - display: flex; - width: 12px; - height: 12px; - justify-content: center; - align-items: center; - flex-shrink: 0; - flex-shrink: 0; - -webkit-mask: url("../assets/infoIcon.svg") center center no-repeat; - mask: url("../assets/infoIcon.svg") center center no-repeat; - -webkit-mask-size: contain; - mask-size: contain; - background-color: #f44649; -} ``` - -
-#### FooterView - -The `footerView` method of MessageTemplate allows you to add a footer view to your message bubbles. In the example below, we will add a custom footer view to every text message in the MessageList. +### Replace entire bubble - + -```ts -import React, { useEffect, useState } from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants, + CometChatMessageTemplate, + MessageBubbleAlignment, + CometChatUIKitLoginListener, + MessageReceiptUtils, + Receipts, + isMessageSentByMe, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); +function BubbleViewDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + CometChat.getGroup("guid").then((group) => setChatGroup(group)); - let definedTemplates: CometChatMessageTemplate[] = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { + const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); + const modified = definedTemplates.map((t) => { if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message + t.type === CometChatUIKitConstants.MessageTypes.text && + t.category === CometChatUIKitConstants.MessageCategory.message ) { - templates.footerView = (message: CometChat.BaseMessage) => - getFooterView(message); - return templates; + t.bubbleView = ( + message: CometChat.BaseMessage, + alignment: MessageBubbleAlignment + ) => { + const isSentByMe = isMessageSentByMe( + message, + CometChatUIKitLoginListener.getLoggedInUser()! + ); + let textMessage = ""; + if (message instanceof CometChat.TextMessage) { + textMessage = message.getText(); + } + return ( +
+
+
{textMessage}
+
+
+ ); + }; } - return templates; + return t; }); - setTemplates(template); + setTemplates(modified); }, []); - const getFooterView = (message: CometChat.BaseMessage) => { - if (message.getReactions().length > 0) { - return ( - <> - - - ); - } else { - return null; - } - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; + if (!chatGroup) return null; -export { CustomMessageTemplate }; + return ; +} ``` -
- - -```js -import React, { useEffect, useState } from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState([]); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - - let definedTemplates = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message - ) { - templates.footerView = (message: CometChat.BaseMessage) => - getFooterView(message); - return templates; - } - return templates; - }); - setTemplates(template); - }, []); - - const getFooterView = (message: CometChat.BaseMessage) => { - if (message.getReactions().length > 0) { - return ( - <> - - - ); - } else { - return null; - } - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```css -.cometchat .cometchat-message-bubble__body-footer-view { - display: flex; - align-items: center; - border-top: 1px solid #dcdcdc; - border-radius: 0px 0px 12px 12px; - background: #e8e8e8; - padding: 8px; -} - -.cometchat-message-bubble__body-wrapper:has( - .cometchat-message-bubble__body-footer-view - ) - .cometchat-message-bubble__body { - border-radius: 12px 12px 0px 0px; -} -``` - - - -
- -#### BubbleView - -The `bubbleView` method of MessageTemplate allows you to add a bubble view to your message bubbles. In the example below, we will add a custom bubble view to the text message in the MessageList. - - - - - - - -```ts -import React, { useEffect, useState } from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, - CometChatMessageTemplate, - Receipts, - MessageBubbleAlignment, - CometChatUIKitLoginListener, - MessageReceiptUtils, - isMessageSentByMe, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import readIcon from "../../assets/message-read.svg"; -import sentIcon from "../../assets/message-sent.svg"; -import deliveredIcon from "../../assets/message-delivered.svg"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); - - let definedTemplates = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message - ) { - templates.bubbleView = ( - message: CometChat.BaseMessage, - alignment: MessageBubbleAlignment - ) => getBubbleView(message, alignment); - return templates; - } - return templates; - }); - setTemplates(template); - }, []); - - const formatTime = (timestamp: number): string => { - const date = new Date(timestamp * 1000); // Convert to milliseconds - const hours = date.getHours(); - const minutes = date.getMinutes(); - const period = hours >= 12 ? "PM" : "AM"; - const formattedHours = hours % 12 || 12; - const formattedMinutes = minutes < 10 ? "0" + minutes : minutes; - return `${formattedHours}:${formattedMinutes} ${period}`; - }; - - const getBubbleView = ( - message: CometChat.BaseMessage, - alignment: MessageBubbleAlignment - ) => { - const isSentByMe = isMessageSentByMe( - message, - CometChatUIKitLoginListener.getLoggedInUser()! - ); - - let textMessage = ""; - if (message instanceof CometChat.TextMessage) { - textMessage = message.getText(); - } - - const receipt = MessageReceiptUtils.getReceiptStatus(message); - let status = sentIcon; - - if (receipt === Receipts.delivered) { - status = deliveredIcon; - } else if (receipt === Receipts.read) { - status = readIcon; - } else { - status = sentIcon; - } - - return ( -
-
-
{textMessage}
-
-
-
- {formatTime(message.getSentAt())} - {isSentByMe && } -
-
- ); - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```js -import React, { useEffect, useState } from "react"; -import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants,CometChatMessageTemplate,Receipts,MessageBubbleAlignment,CometChatUIKitLoginListener,MessageReceiptUtils, isMessageSentByMe } from '@cometchat/chat-uikit-react'; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import readIcon from "../../assets/message-read.svg"; -import sentIcon from "../../assets/message-sent.svg"; -import deliveredIcon from "../../assets/message-delivered.svg"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState([]); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }) - - let definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if (templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message) { - templates.bubbleView = (message, alignment) => getBubbleView(message, alignment) - return templates; - } - return templates - }) - setTemplates(template); - }, []); - - const formatTime = (timestamp) => { - const date = new Date(timestamp * 1000); // Convert to milliseconds - const hours = date.getHours(); - const minutes = date.getMinutes(); - const period = hours >= 12 ? 'PM' : 'AM'; - const formattedHours = hours % 12 || 12; - const formattedMinutes = minutes < 10 ? '0' + minutes : minutes; - return `${formattedHours}:${formattedMinutes} ${period}`; - }; - - const getBubbleView = (message,alignment) => { - const isSentByMe = isMessageSentByMe( - message, - CometChatUIKitLoginListener.getLoggedInUser()! - ); - - let textMessage = ""; - if (message instanceof CometChat.TextMessage) { - textMessage = message.getText(); - } - - const receipt = MessageReceiptUtils.getReceiptStatus(message); - let status = sentIcon; - - if (receipt === Receipts.delivered) { - status = deliveredIcon; - } else if (receipt === Receipts.read) { - status = readIcon; - } else { - status = sentIcon; - } - - return ( -
-
-
{textMessage}
-
-
-
- {formatTime(message.getSentAt())} - {isSentByMe && ( - - )} -
-
- ); - }; - - return ( -
- {chatGroup && } -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```css -.bubble-view { - display: flex; - flex-direction: column; - width: 100%; - padding: 20px; - gap: 12px; -} + +```css lines +.bubble-view { + display: flex; + flex-direction: column; + width: 100%; + padding: 20px; + gap: 12px; +} .bubble-view__outgoing { align-items: flex-end; @@ -1102,15 +445,11 @@ export { CustomMessageTemplate }; display: flex; flex-direction: column; align-items: flex-end; - position: relative; } .bubble-view__content__text { width: fit-content; - display: flex; padding: 4px; - flex-direction: column; - align-items: flex-end; border-radius: 2px 2px 0px 2px; background: #6852d6; color: white; @@ -1120,816 +459,267 @@ export { CustomMessageTemplate }; background-color: #e8e8e8; color: #141414; } - -.bubble-view__content__time { - width: fit-content; - display: flex; - border-radius: 2px 2px 0px 2px; - color: #727272; - gap: 4px; - color: #727272; - text-align: right; - font: 400 10/14 Roboto; - font-style: normal; -} - -.bubble-view__outgoing .triangle { - position: absolute; - bottom: -10px; - right: 0px; - width: 0; - height: 9px; - border-left: 18px solid transparent; - border-top: 10px solid #5a4fcf; -} - -.bubble-view__incoming .triangle { - position: absolute; - bottom: -10px; - left: 0px; - width: 0; - height: 9px; - border-right: 18px solid transparent; - border-top: 10px solid #e8e8e8; -} ``` - -
-#### StatusInfoView - -The `statusInfoView` method of MessageTemplate allows you to add a status info view to your message bubbles. In the example below, we will add a custom status info view to every text message in the MessageList. +### Custom action sheet options - + - - -```ts -import React, { useEffect, useState } from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants, + CometChatMessageTemplate, + CometChatActionsIcon, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); +function OptionsDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); + CometChat.getGroup("guid").then((group) => setChatGroup(group)); - let definedTemplates: CometChatMessageTemplate[] = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { + const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); + const modified = definedTemplates.map((t) => { if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message + t.type === CometChatUIKitConstants.MessageTypes.text && + t.category === CometChatUIKitConstants.MessageCategory.message ) { - templates.statusInfoView = (message: CometChat.BaseMessage) => - getStatusInfo(message); - return templates; + t.options = ( + loggedInUser: CometChat.User, + message: CometChat.BaseMessage, + group?: CometChat.Group + ) => { + const defaultOptions: any = + CometChatUIKit.getDataSource().getMessageOptions(loggedInUser, message, group); + const myView: any = new CometChatActionsIcon({ + id: "refresh", + title: "Refresh", + iconURL: "", + onClick: () => { /* custom logic */ }, + }); + defaultOptions.splice(1, 0, myView); + return defaultOptions; + }; } - return templates; + return t; }); - setTemplates(template); + setTemplates(modified); }, []); - const formatTime = (timestamp: number): string => { - const date = new Date(timestamp * 1000); // Convert to milliseconds - const hours = date.getHours(); - const minutes = date.getMinutes(); - const period = hours >= 12 ? "PM" : "AM"; - const formattedHours = hours % 12 || 12; - const formattedMinutes = minutes < 10 ? "0" + minutes : minutes; - return `${formattedHours}:${formattedMinutes} ${period}`; - }; - - const getStatusInfo = (message: CometChat.BaseMessage) => { - if (message instanceof CometChat.TextMessage) { - const timestamp = message.getSentAt(); - const formattedTime = formatTime(timestamp); - return
{formattedTime}
; - } else { - return null; - } - }; - - return ( -
- {chatGroup && ( - - )} -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```js -import React, { useEffect, useState } from "react"; -import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants } from '@cometchat/chat-uikit-react'; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState([]); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }) - - let definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if (templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message) { - templates.statusInfoView = (message) => getStatusInfo(message) - return templates; - } - return templates - }) - setTemplates(template); - }, []); - - const formatTime = (timestamp) => { - const date = new Date(timestamp * 1000); // Convert to milliseconds - const hours = date.getHours(); - const minutes = date.getMinutes(); - const period = hours >= 12 ? 'PM' : 'AM'; - const formattedHours = hours % 12 || 12; - const formattedMinutes = minutes < 10 ? '0' + minutes : minutes; - return `${formattedHours}:${formattedMinutes} ${period}`; - }; - - const getStatusInfo = (message) => { - if (message instanceof CometChat.TextMessage) { - const timestamp = message.getSentAt(); - const formattedTime = formatTime(timestamp); - return ( -
- {formattedTime} -
- ); - } else { - return null; - } - }; - - return ( -
- {chatGroup && } -
- ); -}; - -export { CustomMessageTemplate }; -``` - -
- - -```css -.status-info { - display: flex; - width: 57px; - height: 24px; - justify-content: flex-end; - align-items: center; - border-radius: 1000px; - color: #727272; - text-align: right; - font: 400 10px/120% Roboto; - font-style: normal; -} - -.cometchat .cometchat-message-bubble__body { - background: none; -} + if (!chatGroup) return null; -.cometchat .cometchat-message-bubble .cometchat-text-bubble { - padding: 8px; + return ; } ``` - +### New template for a custom message type -
- -#### ReplyView - -The `replyView` method of MessageTemplate allows you to add a reply view to your message bubbles. In the example below, we will style the existing reply view in the MessageList. - -

Default Reply View

- - Default Reply View - - -

Custom Reply View

- Custom Reply View + - - - -```ts -import React, { useEffect, useState } from "react"; +```tsx lines +import { useState, useEffect } from "react"; import { - CometChatMessageList + CometChatMessageList, + CometChatUIKit, + CometChatUIKitConstants, + CometChatMessageTemplate, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; -const CustomMessageTemplate = () => { - const [chatGroup, setChatGroup] = React.useState(); +function NewTemplateDemo() { + const [chatGroup, setChatGroup] = useState(); + const [templates, setTemplates] = useState([]); useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); + CometChat.getGroup("guid").then((group) => setChatGroup(group)); + + const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); + const CUSTOM_MESSAGE_TYPE = "customType"; + const customTemplate = new CometChatMessageTemplate({ + type: CUSTOM_MESSAGE_TYPE, + category: CometChatUIKitConstants.MessageCategory.custom, + contentView: (message: CometChat.BaseMessage) => ( +
Custom: {JSON.stringify(message.getData())}
+ ), }); + definedTemplates.push(customTemplate); + setTemplates(definedTemplates); }, []); + const getMessageRequestBuilder = () => { + const CUSTOM_MESSAGE_TYPE = "customType"; + const categories = CometChatUIKit.getDataSource().getAllMessageCategories(); + categories.push(CometChatUIKitConstants.MessageCategory.custom); + const types = CometChatUIKit.getDataSource().getAllMessageTypes(); + types.push(CUSTOM_MESSAGE_TYPE); + return new CometChat.MessagesRequestBuilder() + .setCategories(categories) + .setTypes(types) + .hideReplies(true) + .setLimit(30); + }; + + if (!chatGroup) return null; + return ( -
- {chatGroup && ( - - )} -
+ ); -}; - -export { CustomMessageTemplate }; +} ``` -
- - -```js -import React, { useEffect, useState } from "react"; -import { CometChatMessageList } from '@cometchat/chat-uikit-react'; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }) - }, []); - - return ( -
- {chatGroup && } -
- ); -}; +--- -export { CustomMessageTemplate }; -``` +## Styling -
+`CometChatMessageTemplate` renders inside `.cometchat-message-bubble`. Style individual bubble sections using CSS: - -```css -.cometchat - .cometchat-message-bubble-outgoing - .cometchat-message-bubble__body { - --cometchat-primary-color: #f76808; - --cometchat-extended-primary-color-700: rgba(251, 251, 251, 0.192); +```css lines +.cometchat .cometchat-message-bubble__body { + /* content area overrides */ } -.cometchat .cometchat-message-bubble-incoming .bubble-view{ - --cometchat-primary-color: #f76808; +.cometchat .cometchat-message-bubble__body-footer-view { + /* footer area overrides */ } -.cometchat-message-composer__header .composer-view{ - --cometchat-primary-color: #f76808; +.cometchat .cometchat-message-bubble__body-header-view { + /* header area overrides */ } ``` - - -
- -#### Options - -The `options` method in the MessageTemplate allows you to customize the options that appear in the action sheet when a message is long-pressed. By default, CometChat UI Kit provides a set of options like "Thread Reply", "Copy" ,"Edit", and "Delete". - -However, if you wish to override or modify these options, you can use the `options` method and pass a list of `CometChatActionsIcon`. This list of options will replace the default set. - - - - - - - -```ts -import React, { useEffect, useState } from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, - CometChatMessageTemplate, - CometChatActionsIcon, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = useState( - [] - ); - const [chatGroup, setChatGroup] = useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); +--- - let definedTemplates: CometChatMessageTemplate[] = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message - ) { - templates.options = ( - loggedInUser: CometChat.User, - message: CometChat.BaseMessage, - group?: CometChat.Group - ) => getCustomOptions(loggedInUser, message, chatGroup); - return templates; - } - return templates; - }); - setTemplates(template); - }, []); +## Accessibility - const getCustomOptions = ( - loggedInUser: CometChat.User, - message: CometChat.BaseMessage, - group?: CometChat.Group - ) => { - const defaultOptions: any = - CometChatUIKit.getDataSource().getMessageOptions( - loggedInUser, - message, - chatGroup - ); - const myView: any = new CometChatActionsIcon({ - id: "refresh", - title: "Refresh", - iconURL: "", // Add your custom icon URL - onClick: () => { - /** Add your custom on click logic */ - }, - }); - defaultOptions.splice(1, 0, myView); - return defaultOptions; - }; +Message templates render inside `CometChatMessageList`, which handles keyboard navigation and focus management. Custom views returned from template functions inherit the bubble's focus and ARIA context. Ensure custom content includes appropriate `aria-label` attributes when visual-only indicators are used. - return ( -
- {chatGroup && ( - - )} -
- ); -}; +--- -export { CustomMessageTemplate }; -``` +--- -
+## Properties - -```js -import React, { useEffect, useState } from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, - CometChatActionsIcon, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = useState([]); - const [chatGroup, setChatGroup] = useState(); +### bubbleView - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | - let definedTemplates = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const template = definedTemplates.map((templates) => { - if ( - templates.type === CometChatUIKitConstants.MessageTypes.text && - templates.category === CometChatUIKitConstants.MessageCategory.message - ) { - templates.options = (loggedInUser, message, group) => - getCustomOptions(loggedInUser, message, chatGroup); - return templates; - } - return templates; - }); - setTemplates(template); - }, []); +Replaces the entire message bubble. When set, `headerView`, `contentView`, `footerView`, `bottomView`, `statusInfoView`, and `replyView` are ignored for that template. - const getCustomOptions = (loggedInUser, message, group) => { - const defaultOptions = CometChatUIKit.getDataSource().getMessageOptions( - loggedInUser, - message, - chatGroup - ); - const myView = new CometChatActionsIcon({ - id: "refresh", - title: "Refresh", - iconURL: "", // Add your custom icon URL - onClick: () => { - /** Add your custom on click logic */ - }, - }); - defaultOptions.splice(1, 0, myView); - return defaultOptions; - }; +--- - return ( -
- {chatGroup && ( - - )} -
- ); -}; +### bottomView -export { CustomMessageTemplate }; -``` +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | -
+Custom bottom section below the content area. Default renders link previews or "load more" for long messages. - -```css -#refresh.cometchat-menu-list__menu .cometchat-menu-list__sub-menu-item-title { - overflow: hidden; - color: #6852d6; - font: 400 14px/16.8px Roboto; - font-style: italic; -} +--- -#refresh.cometchat-menu-list__menu - .cometchat-menu-list__sub-menu-list-item-icon { - background-color: #6852d6; -} -``` +### category - +| Key | Value | +| --- | --- | +| Type | `string` | +| Default | `""` | -
+Maps the template to a CometChat message category (e.g., `CometChatUIKitConstants.MessageCategory.message`, `CometChatUIKitConstants.MessageCategory.custom`). -### New Templates +--- -You can create an entirely new template for custom messages is one of the powerful features of CometChat's MessageTemplate. +### contentView - - - +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, textFormatters?: CometChatTextFormatter[]) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | - - -```ts -import React, { useEffect, useState } from "react"; -import { - CometChatMessageList, - CometChatUIKit, - CometChatUIKitConstants, - CometChatMessageTemplate, - MessageReceiptUtils, - isMessageSentByMe, - Receipts, - CometChatUIKitLoginListener, -} from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import readIcon from "../../assets/message-read.svg"; -import sentIcon from "../../assets/message-sent.svg"; -import deliveredIcon from "../../assets/message-delivered.svg"; +Custom content area. Default renders text, image, video, audio, or file bubble based on message type. -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState( - [] - ); - const [chatGroup, setChatGroup] = React.useState(); +--- - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }); +### footerView - let definedTemplates = - CometChatUIKit.getDataSource().getAllMessageTemplates(); - const CUSTOM_MESSAGE_TYPE = "customType"; - let customMessageTemplate = new CometChatMessageTemplate({ - type: CUSTOM_MESSAGE_TYPE, - category: CometChatUIKitConstants.MessageCategory.custom, - contentView: (message: CometChat.BaseMessage) => getContentView(message), - }); - definedTemplates.push(customMessageTemplate); - setTemplates(definedTemplates); - }, []); +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | - const formatTime = (timestamp: number): string => { - const date = new Date(timestamp * 1000); // Convert to milliseconds - const hours = date.getHours(); - const minutes = date.getMinutes(); - const period = hours >= 12 ? "PM" : "AM"; - const formattedHours = hours % 12 || 12; - const formattedMinutes = minutes < 10 ? "0" + minutes : minutes; - return `${formattedHours}:${formattedMinutes} ${period}`; - }; +Custom footer below the content area. Default renders reactions. - const getContentView = (message: CometChat.BaseMessage) => { - const isSentByMe = isMessageSentByMe( - message, - CometChatUIKitLoginListener.getLoggedInUser()! - ); - - const receipt = MessageReceiptUtils.getReceiptStatus(message); - let status = sentIcon; - - if (receipt === Receipts.delivered) { - status = deliveredIcon; - } else if (receipt === Receipts.read) { - status = readIcon; - } else { - status = sentIcon; - } - - return ( -
-
- -
- {formatTime(message.getSentAt())} - {isSentByMe && ( - - )} -
-
-
-
Add Contact
-
Message
-
-
- ); - }; +--- - const getMessageRequestBuilder = () => { - const CUSTOM_MESSAGE_TYPE = "customType"; - let categories = CometChatUIKit.getDataSource().getAllMessageCategories(); - categories.push(CometChatUIKitConstants.MessageCategory.custom); - let types = CometChatUIKit.getDataSource().getAllMessageTypes(); - types.push(CUSTOM_MESSAGE_TYPE); - return new CometChat.MessagesRequestBuilder() - .setCategories(categories) - .setTypes(types) - .hideReplies(true) - .setLimit(30); - }; +### headerView - return ( -
- {chatGroup && ( - - )} -
- ); -}; +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | -export { CustomMessageTemplate }; -``` +Custom header above the content area. Default renders sender name. -
+--- - -```js -import React, { useEffect, useState } from "react"; -import { CometChatMessageList, CometChatUIKit, CometChatUIKitConstants, -CometChatMessageTemplate,MessageReceiptUtils,isMessageSentByMe,Receipts,CometChatUIKitLoginListener } from '@cometchat/chat-uikit-react'; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import readIcon from "../../assets/message-read.svg"; -import sentIcon from "../../assets/message-sent.svg"; -import deliveredIcon from "../../assets/message-delivered.svg"; - - -const CustomMessageTemplate = () => { - const [templates, setTemplates] = React.useState([]); - const [chatGroup, setChatGroup] = React.useState(); - - useEffect(() => { - CometChat.getGroup("guid").then((group) => { - setChatGroup(group); - }) - - let definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates(); - const CUSTOM_MESSAGE_TYPE = "customType"; - let customMessageTemplate = new CometChatMessageTemplate({ - type: CUSTOM_MESSAGE_TYPE, - category: CometChatUIKitConstants.MessageCategory.custom, - contentView: (message) => getContentView(message), - }); - definedTemplates.push(customMessageTemplate); - setTemplates(definedTemplates); - }, []); - - const formatTime = (timestamp) => { - const date = new Date(timestamp * 1000); // Convert to milliseconds - const hours = date.getHours(); - const minutes = date.getMinutes(); - const period = hours >= 12 ? 'PM' : 'AM'; - const formattedHours = hours % 12 || 12; - const formattedMinutes = minutes < 10 ? '0' + minutes : minutes; - return `${formattedHours}:${formattedMinutes} ${period}`; - }; - - const getContentView = (message) => { - const isSentByMe = isMessageSentByMe( - message, - CometChatUIKitLoginListener.getLoggedInUser()! - ); - - const receipt = MessageReceiptUtils.getReceiptStatus(message); - let status = sentIcon; - - if (receipt === Receipts.delivered) { - status = deliveredIcon; - } else if (receipt === Receipts.read) { - status = readIcon; - } else { - status = sentIcon; - } +### options - return ( -
-
- -
- {formatTime(message.getSentAt())} - {isSentByMe && ( - - )} -
-
-
-
Add Contact
-
Message
-
-
- ); - }; - - const getMessageRequestBuilder = () => { - const CUSTOM_MESSAGE_TYPE = "customType"; - let categories = CometChatUIKit.getDataSource().getAllMessageCategories(); - categories.push(CometChatUIKitConstants.MessageCategory.custom); - let types = CometChatUIKit.getDataSource().getAllMessageTypes(); - types.push(CUSTOM_MESSAGE_TYPE); - return new CometChat.MessagesRequestBuilder().setCategories(categories).setTypes(types).hideReplies(true).setLimit(30); - } - - return ( -
- {chatGroup && } -
- ); -}; +| Key | Value | +| --- | --- | +| Type | `(loggedInUser: CometChat.User, message: CometChat.BaseMessage, group?: CometChat.Group) => CometChatMessageOption[]` | +| Default | SDK default options | -export { CustomMessageTemplate }; -``` +Returns the list of action sheet items for long-press on a message bubble. -
+--- - -```css -.content-view { - display: flex; - flex-direction: column; - gap: 4px; -} +### replyView -.content-view .cometchat-list-item { - background: none; -} +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment?: MessageBubbleAlignment, onReplyViewClicked?: (msg: CometChat.BaseMessage) => void, textFormatters?: CometChatTextFormatter[]) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | -.content-view .cometchat-list-item__body-title { - overflow: hidden; - color: #f9f8fd; - text-overflow: ellipsis; - font: 500 14px/16.8px roboto; - font-style: normal; -} +Custom reply preview above the content area. -.cometchat-message-bubble-incoming .cometchat-list-item__body-title, -.cometchat-message-bubble-incoming .content-view__header-time, -.cometchat-message-bubble-incoming .content-view__footer-message, -.cometchat-message-bubble-incoming .content-view__footer-add-contact { - color: #141414; -} +--- -.cometchat-message-bubble-incoming .content-view__footer { - border-top: 1px solid #dcdcdc; -} +### statusInfoView -.cometchat-message-bubble-incoming .content-view__footer-add-contact { - border-right: 1px solid #dcdcdc; -} +| Key | Value | +| --- | --- | +| Type | `((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, hideReceipts?: boolean, messageSentAtDateTimeFormat?: CalendarObject, showError?: boolean) => Element \| JSX.Element \| null) \| null` | +| Default | `null` | -.content-view__header-time { - display: flex; - justify-content: end; - gap: 4px; - color: #f9f8fd; - text-align: right; - font: 400 10px/12px roboto; - font-style: normal; -} +Custom status info area. Default renders receipt icon and timestamp. -.content-view__footer { - border-top: 1px solid #7965db; - display: flex; - height: 40px; - justify-content: center; - align-items: center; - align-self: stretch; -} +--- -.content-view__footer-add-contact { - width: 50%; - height: 100%; - border-right: 1px solid #7965db; - display: flex; - align-items: center; - justify-content: center; - color: #f9f8fd; - font: 500 14px/16.8px roboto; - font-style: normal; -} +### type -.content-view__footer-message { - width: 50%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - color: #f9f8fd; - font: 500 14px/16.8px roboto; - font-style: normal; -} -``` +| Key | Value | +| --- | --- | +| Type | `string` | +| Default | — (required) | - +Maps the template to a CometChat message type (e.g., `CometChatUIKitConstants.MessageTypes.text`, `CometChatUIKitConstants.MessageTypes.image`). -
+--- diff --git a/ui-kit/react/methods.mdx b/ui-kit/react/methods.mdx index 0be19fef4..b679d3684 100644 --- a/ui-kit/react/methods.mdx +++ b/ui-kit/react/methods.mdx @@ -1,33 +1,49 @@ --- title: "Methods" +description: "Reference for CometChat React UI Kit methods including init, login, logout, and message-sending wrappers." --- -## Overview + -The UI Kit's core function is to extend the [Chat SDK](/sdk/javascript/overview), essentially translating the raw data and functionality provided by the underlying methods into visually appealing and easy-to-use UI components. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Import | `import { CometChatUIKit } from "@cometchat/chat-uikit-react";` | +| Init | `CometChatUIKit.init(UIKitSettings)` | +| Login (dev) | `CometChatUIKit.login("UID")` | +| Login (prod) | `CometChatUIKit.loginWithAuthToken("AUTH_TOKEN")` | +| Other methods | `CometChatUIKit.logout()`, `CometChatUIKit.getLoggedinUser()`, `CometChatUIKit.createUser(user)`, `CometChatUIKit.updateUser(user)` | +| Send messages | `CometChatUIKit.sendTextMessage()`, `CometChatUIKit.sendMediaMessage()`, `CometChatUIKit.sendCustomMessage()` | +| Note | Use these wrapper methods instead of raw SDK calls — they manage internal UI Kit eventing | -To effectively manage and synchronize the UI elements and data across all components in the UI Kit, we utilize internal events. These internal events enable us to keep track of changes in real time and ensure that the UI reflects the most current state of data. + -The CometChat UI Kit has thoughtfully encapsulated the critical [Chat SDK](/sdk/javascript/overview) methods within its wrapper to efficiently manage internal eventing. This layer of abstraction simplifies interaction with the underlying CometChat SDK, making it more user-friendly for developers. +The UI Kit wraps the [Chat SDK](/sdk/javascript/overview) methods to manage internal eventing and keep UI components synchronized. Use these wrapper methods instead of raw SDK calls. + + +`CometChatUIKit.init(UIKitSettings)` must be called before rendering any UI Kit components or calling any SDK methods. Initialization must complete before login. + + + +Auth Key is for development/testing only. In production, generate Auth Tokens on the server using the REST API and pass them to the client via `loginWithAuthToken()`. Never expose Auth Keys in production client code. + ## Methods -You can access the methods using the `CometChatUIKit` class. This class provides access to all the public methods exposed by the CometChat UI Kit. +All methods are accessed via the `CometChatUIKit` class. ### Init -This method initializes the settings required for [CometChat JavaScript SDK](/sdk/javascript/overview). First, ensure UIKitSettings is set and then call the `init()` method on the app startup. +Initializes the [CometChat JavaScript SDK](/sdk/javascript/overview). Must be called on app startup before any other UI Kit method. - -Make sure you replace the **APP\_ID**, **REGION** and **AUTH\_KEY** with your CometChat App ID, Region and Auth Key in the below code. The `Auth Key` is an optional property of the `UIKitSettings` Class. It is intended for use primarily during proof-of-concept (POC) development or in the early stages of application development. You can use the [Auth Token](#login-using-auth-token) method to log in securely. - +Replace `APP_ID`, `REGION`, and `AUTH_KEY` with values from the CometChat Dashboard. `Auth Key` is optional — use [Auth Token](#login-using-auth-token) for production. -```js -import { UIKitSettingsBuilder } from "@cometchat/uikit-shared"; //import shared package +```js lines highlight={4-6} +import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; const COMETCHAT_CONSTANTS = { APP_ID: "APP_ID", // Replace with your App ID @@ -57,11 +73,11 @@ CometChatUIKit.init(UIKitSettings)?.then(() => { ### Setting Session Storage Mode -If you want to use session storage instead of the default local storage, you can configure it during initialization: +To use session storage instead of the default local storage, configure it during initialization: -```js +```js lines highlight={5-7} import { CometChat } from "@cometchat/chat-sdk-javascript"; import { UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; @@ -89,7 +105,7 @@ CometChatUIKit.init(UIKitSettings)?.then(() => { -```ts +```ts lines highlight={5-7} import { CometChat } from "@cometchat/chat-sdk-javascript"; import { UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; @@ -119,11 +135,11 @@ CometChatUIKit.init(UIKitSettings)?.then(() => { ### Get Logged In User -You can use this method to check if there is any existing session in the SDK. This method should return the details of the logged-in user. +Checks for an existing session in the SDK. Returns the logged-in user details or `null`. -```js +```js lines import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package CometChatUIKit.getLoggedinUser() @@ -141,11 +157,11 @@ CometChatUIKit.getLoggedinUser() ### Login using Auth Key -This simple authentication procedure is useful when you are creating a POC or if you are in the development phase. For production apps, we suggest you use [AuthToken](#login-using-auth-token) instead of Auth Key. +Simple authentication for development/POC. For production, use [Auth Token](#login-using-auth-token). -```js +```js lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package const UID = "UID"; @@ -170,7 +186,7 @@ CometChatUIKit.getLoggedinUser() -```ts +```ts lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package const UID: string = "UID"; @@ -200,7 +216,7 @@ CometChatUIKit.getLoggedinUser() ### Login using Auth Token -This advanced authentication procedure does not use the Auth Key directly in your client code thus ensuring safety. +Production-safe authentication that does not expose the Auth Key in client code. 1. [Create a User](https://api-explorer.cometchat.com/reference/creates-user) via the CometChat API when the user signs up in your app. 2. [Create an Auth Token](https://api-explorer.cometchat.com/reference/create-authtoken) via the CometChat API for the new user and save the token in your database. @@ -208,7 +224,7 @@ This advanced authentication procedure does not use the Auth Key directly in you -```js +```js lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package const authToken = "AUTH_TOKEN"; @@ -234,12 +250,12 @@ CometChatUIKit.getLoggedinUser() -```ts +```ts lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package const authToken: string = "AUTH_TOKEN"; -CometChat.getLoggedinUser() +CometChatUIKit.getLoggedinUser() .then((user: CometChat.User) => { if (!user) { //Login user @@ -262,11 +278,11 @@ CometChat.getLoggedinUser() ### Logout -This method is used to end the user session of the logged-in user +Ends the current user session. -```js +```js lines import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package CometChatUIKit.logout(); @@ -280,11 +296,11 @@ CometChatUIKit.logout(); ### Create user -This method takes a `User` object and the `Auth Key` as input parameters and returns the created `User` object if the request is successful. +Takes a `User` object and Auth Key, returns the created `User` object. -```js +```js lines highlight={4-6} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package @@ -311,7 +327,7 @@ CometChatUIKit.createUser(user, authKey) -```ts +```ts lines highlight={4-6} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package @@ -343,11 +359,11 @@ CometChatUIKit.createUser(user, authKey) ### Update user -This method takes a `User` object and the `Auth Key` as inputs and returns the updated `User` object on the successful execution of the request. +Takes a `User` object and Auth Key, returns the updated `User` object. -```js +```js lines highlight={4-6} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package @@ -367,7 +383,7 @@ CometChatUIKit.updateUser(user, authKey) -```ts +```ts lines highlight={4-6} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package @@ -394,11 +410,11 @@ CometChatUIKit.updateUser(user, authKey) #### Text message -This method sends a text message in a 1:1 or group chat. You need to pass a `TextMessage` object to it. +Sends a text message in a 1:1 or group chat. Takes a `TextMessage` object. -```tsx +```tsx lines highlight={5-6} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package import { CometChatUIKitConstants } from "@cometchat/uikit-resources"; //import shared package @@ -422,7 +438,7 @@ CometChatUIKit.sendTextMessage(textMessage) -```tsx +```tsx lines highlight={5-6} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package import { CometChatUIKitConstants } from "@cometchat/uikit-resources"; //import shared package @@ -451,17 +467,15 @@ CometChatUIKit.sendMessage(textMessage) #### Media message -This method sends a media message in a 1:1 or group chat. You need to pass a `MediaMessage` object to it. +Sends a media message in a 1:1 or group chat. Takes a `MediaMessage` object. - -Make sure you replace the `INPUT FILE OBJECT` with the actual [file](https://developer.mozilla.org/en-US/docs/Web/API/File). - +Replace `INPUT FILE OBJECT` with the actual [File](https://developer.mozilla.org/en-US/docs/Web/API/File) object. -```tsx +```tsx lines highlight={5} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package import { CometChatUIKitConstants } from "@cometchat/uikit-resources"; //import shared package @@ -486,7 +500,7 @@ CometChatUIKit.sendMediaMessage(mediaMessage) -```tsx +```tsx lines highlight={5} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package import { CometChatUIKitConstants } from "@cometchat/uikit-resources"; //import shared package @@ -516,11 +530,11 @@ CometChatUIKit.sendMediaMessage(mediaMessage) #### Custom message -This method allows you to send custom messages which are neither text nor media messages. +Sends a custom message (neither text nor media) in a 1:1 or group chat. Takes a `CustomMessage` object. -```tsx +```tsx lines highlight={5,7,8} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package import { CometChatUIKitConstants } from "@cometchat/uikit-resources"; //import shared package @@ -549,7 +563,7 @@ CometChatUIKit.sendCustomMessage(customMessage) -```tsx +```tsx lines highlight={5,7,8} import { CometChat } from "@cometchat/chat-sdk-javascript"; //import sdk package import { CometChatUIKit } from "@cometchat/chat-uikit-react"; //import uikit package import { CometChatUIKitConstants } from "@cometchat/uikit-resources"; //import shared package diff --git a/ui-kit/react/next-conversation.mdx b/ui-kit/react/next-conversation.mdx index 1d8800f66..c1e3d00c6 100644 --- a/ui-kit/react/next-conversation.mdx +++ b/ui-kit/react/next-conversation.mdx @@ -1,227 +1,212 @@ --- -title: "Building A Conversation List + Message View" +title: "Conversation List + Message View" sidebarTitle: "Conversation List + Message View" +description: "Build a two-panel conversation list + message view layout in Next.js with CometChat UI Kit." --- -The **Conversation List + Message View** layout offers a seamless **two-panel chat interface**, commonly used in modern messaging applications like **WhatsApp Web, Slack, and Microsoft Teams**. + -This design enables users to switch between conversations effortlessly while keeping the chat window open, ensuring a **smooth, real-time messaging experience**. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Framework | Next.js | +| Components | `CometChatConversations`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Two-panel — conversation list (left) + message view (right) | +| Prerequisite | Complete [Next.js Integration](/ui-kit/react/next-js-integration) Steps 1–5 first | +| SSR | Dynamic import with `ssr: false` — CometChat requires browser APIs | +| Pattern | WhatsApp Web, Slack, Microsoft Teams | -[](https://link.cometchat.com/next-conversation-list-message) - -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. + -*** +This guide builds a two-panel chat layout — conversation list on the left, messages on the right. Users tap a conversation to open it. -## **User Interface Overview** +This assumes you've already completed [Next.js Integration](/ui-kit/react/next-js-integration) (project created, UI Kit installed, CSS imported). -This layout is structured into three key sections: - -1. **Sidebar (Conversation List)** – Displays active conversations, including users and groups. -2. **Message View** – Shows chat messages for the selected conversation in real-time. -3. **Message Composer** – Provides an input field for typing and sending messages, along with support for media, emojis, and reactions. - -*** +[](https://link.cometchat.com/next-conversation-list-message) -## **Step-by-Step Guide** +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -### **Step 1: Create Sidebar** +--- -Let's create the `Sidebar` component which will render different conversations. +## What You're Building -#### **Folder Structure** +Three sections working together: -Create a `CometChatSelector` folder inside your `src/app` directory and add the following files: +1. **Sidebar (conversation list)** — shows all active conversations (users and groups) +2. **Message view** — displays chat messages for the selected conversation in real time +3. **Message composer** — text input with support for media, emojis, and reactions -```swift -src/app/ -│── CometChatSelector/ -│ ├── CometChatSelector.tsx -│ ├── CometChatSelector.css -``` +--- -#### **Download the Icon** +## Step 1 — Create the Sidebar Component -These icons are available in the **CometChat UI Kit assets folder**. You can find them at:\ -🔗 [GitHub Assets Folder](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/assets) + + + + + + + + + + -```tsx CometChatSelector.tsx +```tsx title="CometChatSelector.tsx" lines import { useEffect, useState } from "react"; -import { Conversation, Group, User } from "@cometchat/chat-sdk-javascript"; +import { Conversation, Group, User, CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatConversations, CometChatUIKitLoginListener } from "@cometchat/chat-uikit-react"; -import { CometChat } from '@cometchat/chat-sdk-javascript'; import "./CometChatSelector.css"; -// Define props interface for component interface SelectorProps { - onSelectorItemClicked?: (input: User | Group | Conversation, type: string) => void; + onSelectorItemClicked?: (input: User | Group | Conversation, type: string) => void; } -// CometChatSelector component definition export const CometChatSelector = (props: SelectorProps) => { - const { - onSelectorItemClicked = () => { }, // Default function if no prop is provided - } = props; - - // State to store the currently logged-in user - const [loggedInUser, setLoggedInUser] = useState(); - - // State to track the currently selected item (conversation, user, group, or call) - const [activeItem, setActiveItem] = useState< - CometChat.Conversation | CometChat.User | CometChat.Group | CometChat.Call | undefined - >(); - - useEffect(() => { - // Retrieve the logged-in user from CometChat's login listener - let loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - setLoggedInUser(loggedInUser); - }, [CometChatUIKitLoginListener?.getLoggedInUser()]); // Dependency array to trigger effect when user changes - - return ( - <> - {/* Render CometChatConversations only if a user is logged in */} - {loggedInUser && ( - <> - { - setActiveItem(e); // Update the selected item state - onSelectorItemClicked(e, "updateSelectedItem"); // Trigger callback with selected item - }} - /> - - )} - - ); -}; + const { onSelectorItemClicked = () => {} } = props; + const [loggedInUser, setLoggedInUser] = useState(); + const [activeItem, setActiveItem] = useState< + CometChat.Conversation | CometChat.User | CometChat.Group | undefined + >(); + + useEffect(() => { + const user = CometChatUIKitLoginListener.getLoggedInUser(); + setLoggedInUser(user); + }, []); + + return ( + <> + {loggedInUser && ( + { + setActiveItem(e); + onSelectorItemClicked(e, "updateSelectedItem"); + }} + /> + )} + + ); +}; ``` - -```css CometChatSelector.css -/* Style for the icon in the header menu of the conversation list */ +```css title="CometChatSelector.css" lines .selector-wrapper .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon { - background: var(--cometchat-icon-color-primary); + background: var(--cometchat-icon-color-primary); } -/* Change background color of icon on hover */ .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon:hover { - background: var(--cometchat-icon-color-highlight); + background: var(--cometchat-icon-color-highlight); } -/* Remove the right border from the search bar */ .cometchat-list__header-search-bar { - border-right: none; + border-right: none; } -/* Align submenu items to the left */ .cometchat .cometchat-menu-list__sub-menu-list-item { - text-align: left; + text-align: left; } -/* Set specific width and positioning for submenu list */ .cometchat .cometchat-conversations .cometchat-menu-list__sub-menu-list { - width: 212px; - top: 40px !important; - left: 172px !important; + width: 212px; + top: 40px !important; + left: 172px !important; } -/* Style the logged-in user section with a bottom border */ #logged-in-user { - border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8); + border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8); } -/* Prevent cursor interaction on logged-in user menu items */ #logged-in-user .cometchat-menu-list__sub-menu-item-title, #logged-in-user .cometchat-menu-list__sub-menu-list-item { - cursor: default; + cursor: default; } -/* Style for logout icon with error color */ .cometchat-menu-list__sub-menu-list-item-icon-log-out { - background-color: var(--cometchat-error-color, #F44649); + background-color: var(--cometchat-error-color, #F44649); } -/* Style for logout text with error color */ .cometchat-menu-list__sub-menu-item-title-log-out { - color: var(--cometchat-error-color, #F44649); + color: var(--cometchat-error-color, #F44649); } -/* Allow pointer interaction on submenu items inside chat menu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu-item-title { - cursor: pointer; + cursor: pointer; } -/* Remove shadow from submenu inside chat menu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu { - box-shadow: none; + box-shadow: none; } -/* Style for submenu icons inside chat menu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu-icon { - background-color: var(--cometchat-icon-color-primary, #141414); - width: 24px; - height: 24px; + background-color: var(--cometchat-icon-color-primary, #141414); + width: 24px; + height: 24px; } ``` - -### **Step 2: Render Experience** +--- -Now we will create the `CometChatNoSSR.tsx` & `CometChatNoSSR.css` files. Here, we will initialize the CometChat UI Kit, log in a user, and build the messaging experience using `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` components. +## Step 2 — Create the CometChatNoSSR Component -``` -src/ -│── CometChatNoSSR/ -│ ├── CometChatNoSSR.tsx -│ ├── CometChatNoSSR.css -``` +This component handles init, login, and renders the full chat experience. It runs client-side only. + + + + + + + + + + + -```tsx CometChatNoSSR.tsx +```tsx title="CometChatNoSSR.tsx" lines highlight={15-17, 20} import React, { useEffect, useState } from "react"; -import { - CometChatMessageComposer, - CometChatMessageHeader, - CometChatMessageList, - CometChatUIKit, - UIKitSettingsBuilder +import { + CometChatMessageComposer, + CometChatMessageHeader, + CometChatMessageList, + CometChatUIKit, + UIKitSettingsBuilder, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatSelector } from "../CometChatSelector/CometChatSelector"; import "./CometChatNoSSR.css"; -// Constants for CometChat configuration +// Replace with your actual credentials const COMETCHAT_CONSTANTS = { - APP_ID: "", - REGION: "", - AUTH_KEY: "", + APP_ID: "", // Replace with your App ID + REGION: "", // Replace with your Region + AUTH_KEY: "", // Replace with your Auth Key (dev only) }; -// Functional Component +const UID = "cometchat-uid-1"; // Replace with your actual UID + const CometChatNoSSR: React.FC = () => { - // State to store the logged-in user const [user, setUser] = useState(undefined); - // State to store selected user or group const [selectedUser, setSelectedUser] = useState(undefined); const [selectedGroup, setSelectedGroup] = useState(undefined); useEffect(() => { - // Initialize UIKit settings const UIKitSettings = new UIKitSettingsBuilder() .setAppId(COMETCHAT_CONSTANTS.APP_ID) .setRegion(COMETCHAT_CONSTANTS.REGION) @@ -229,15 +214,12 @@ const CometChatNoSSR: React.FC = () => { .subscribePresenceForAllUsers() .build(); - // Initialize CometChat UIKit CometChatUIKit.init(UIKitSettings) ?.then(() => { console.log("Initialization completed successfully"); - // Check if user is already logged in CometChatUIKit.getLoggedinUser().then((loggedInUser) => { if (!loggedInUser) { - // Perform login if no user is logged in - CometChatUIKit.login("cometchat-uid-1") + CometChatUIKit.login(UID) .then((user) => { console.log("Login Successful", { user }); setUser(user); @@ -254,16 +236,13 @@ const CometChatNoSSR: React.FC = () => { return user ? (
- {/* Sidebar with conversation list */}
- { let item = activeItem; - // Extract the conversation participant if (activeItem instanceof CometChat.Conversation) { item = activeItem.getConversationWith(); } - // Update states based on the type of selected item if (item instanceof CometChat.User) { setSelectedUser(item as CometChat.User); setSelectedGroup(undefined); @@ -274,11 +253,10 @@ const CometChatNoSSR: React.FC = () => { setSelectedUser(undefined); setSelectedGroup(undefined); } - }} + }} />
- - {/* Message view section */} + {selectedUser || selectedGroup ? (
@@ -286,7 +264,7 @@ const CometChatNoSSR: React.FC = () => {
) : ( -
Select Conversation to start
+
Select a conversation to start chatting
)}
) : undefined; @@ -296,169 +274,115 @@ export default CometChatNoSSR; ```
- -```css CometChatNoSSR.css -/* Layout for the main conversations and messages container */ +```css title="CometChatNoSSR.css" lines .conversations-with-messages { - display: flex; - height: 100%; - width: 100%; + display: flex; + height: 100%; + width: 100%; } -/* Sidebar wrapper for conversations */ .conversations-wrapper { - height: 100%; - width: 480px; /* Fixed width for conversation list */ - overflow: hidden; - display: flex; - flex-direction: column; - height: inherit; + height: 100%; + width: 480px; + overflow: hidden; + display: flex; + flex-direction: column; + height: inherit; } -/* Hide overflow for the conversation list */ .conversations-wrapper > .cometchat { - overflow: hidden; + overflow: hidden; } -/* Message section layout */ .messages-wrapper { - width: calc(100% - 480px); /* Take remaining space */ - height: 100%; - display: flex; - flex-direction: column; + width: calc(100% - 480px); + height: 100%; + display: flex; + flex-direction: column; } -/* Display styling for when no conversation is selected */ .empty-conversation { - height: 100%; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - background: white; - color: var(--cometchat-text-color-secondary, #727272); - font: var(--cometchat-font-body-regular, 400 14px Roboto); + height: 100%; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + background: white; + color: var(--cometchat-text-color-secondary, #727272); + font: var(--cometchat-font-body-regular, 400 14px Roboto); } -/* Ensure message composer does not have rounded corners */ .cometchat .cometchat-message-composer { - border-radius: 0px; + border-radius: 0px; } ``` -
-### **Step 3: Disabling SSR for `CometChatNoSSR.tsx` in Next.js** - -In this update, we will **disable Server-Side Rendering (SSR) for `CometChatNoSSR.tsx`** while keeping the rest of the application’s SSR functionality intact. This ensures that the **CometChat UI Kit components load only on the client-side**, preventing SSR-related issues. +--- -#### **Disabling SSR in `index.tsx`** +## Step 3 — Disable SSR in Your Page -Modify your `index.tsx` file to dynamically import the `CometChatNoSSR.tsx` component with `{ ssr: false }`. +Dynamically import `CometChatNoSSR` with `ssr: false` so it only loads client-side. -```tsx index.tsx -import { Inter } from "next/font/google"; +```tsx title="index.tsx" lines import dynamic from "next/dynamic"; +import "@cometchat/chat-uikit-react/css-variables.css"; -import '@cometchat/chat-uikit-react/css-variables.css'; - -const inter = Inter({ subsets: ["latin"] }); - -// Dynamically import CometChat component with SSR disabled -const CometChatComponent = dynamic(() => import("../CometChatNoSSR/CometChatNoSSR"), { - ssr: false, -}); +const CometChatComponent = dynamic( + () => import("../CometChatNoSSR/CometChatNoSSR"), + { ssr: false } +); export default function Home() { return ; } ``` -#### **Why disable SSR?** - -* The CometChat UI Kit depends on browser APIs (window, document, WebSockets). -* Next.js pre-renders components on the server, which can cause errors with browser-specific features. -* By setting `{ ssr: false }`, we ensure that CometChatNoSSR.tsx only loads on the client. +CometChat depends on browser APIs (`window`, `WebSocket`, `document`). Setting `ssr: false` ensures the component only renders on the client, avoiding hydration errors. -### **Step 4: Update Global CSS** - -Next, add the following styles to global.css to ensure CometChat UI Kit is properly styled. - -```css global.css -:root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -/** Give your App a height of `100%`. Keep other CSS properties in the below selector as it is. */ -.root { - height: 100%; -} - -#__next { - height: 100%; -} - -html, -body { - height: 100%; -} - -html, -body { - max-width: 100vw; - overflow-x: hidden; -} - -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} +--- -* { - box-sizing: border-box; - padding: 0; - margin: 0; -} +## Step 4 — Run the Project -a { - color: inherit; - text-decoration: none; -} - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} + + +```bash lines +npm run dev ``` - -### **Step 5: Run the project** - + + +```bash lines +pnpm dev ``` -npm run dev + + +```bash lines +yarn dev ``` + + -*** - -## **Next Steps** - -### **Enhance the User Experience** +You should see the conversation list on the left. Tap any conversation to load messages on the right. -* **[Advanced Customizations](/ui-kit/react/theme)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Customize colors, fonts, and styles to match your brand + + + Browse all prebuilt UI components + + } href="/ui-kit/react/next-js-integration"> + Back to the main setup guide + + + Chat features included out of the box + + diff --git a/ui-kit/react/next-js-integration.mdx b/ui-kit/react/next-js-integration.mdx index 0d4c40aac..740b4d7c3 100644 --- a/ui-kit/react/next-js-integration.mdx +++ b/ui-kit/react/next-js-integration.mdx @@ -1,138 +1,96 @@ --- -title: "Getting Started With CometChat React UI Kit For Next.js" +title: "Next.js Integration" sidebarTitle: "Integration" +description: "Add CometChat to a Next.js app in 5 steps: create project, install, init, login, render." --- -The **CometChat UI Kit for React** streamlines the integration of in-app chat functionality by providing a **comprehensive set of prebuilt UI components**. It offers seamless **theming options**, including **light and dark modes**, customizable fonts, colors, and extensive styling capabilities. + -With built-in support for **one-to-one and group conversations**, developers can efficiently enable chat features within their applications. Follow this guide to **quickly integrate chat functionality** using the CometChat React UI Kit. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Peer deps | `react` >=18, `react-dom` >=18, `rxjs` ^7.8.1 | +| Init | `CometChatUIKit.init(UIKitSettings)` — must resolve before `login()` | +| Login | `CometChatUIKit.login("UID")` — must resolve before rendering components | +| Order | `init()` → `login()` → render. Breaking this order = blank screen | +| Auth Key | Dev/testing only. Use Auth Token in production | +| SSR | CometChat requires browser APIs — use dynamic import with `ssr: false` | +| CSS | `@import url("@cometchat/chat-uikit-react/css-variables.css");` in global CSS | +| Calling | Optional. Install `@cometchat/calls-sdk-javascript` to enable | +| Other frameworks | [React.js](/ui-kit/react/react-js-integration) · [React Router](/ui-kit/react/react-router-integration) · [Astro](/ui-kit/react/astro-integration) | -{/* - - */} + + +This guide walks you through adding CometChat to a Next.js app. By the end you'll have a working chat UI. -*** - -## **Prerequisites** - -Before installing the **CometChat UI Kit for React**, you must first **create a CometChat application** via the **[CometChat Dashboard](https://app.cometchat.com/)**. The dashboard provides all the essential chat service components, including: - -* **User Management** -* **Group Chat & Messaging** -* **Voice & Video Calling** -* **Real-time Notifications** - -> To initialize the **UI Kit**, you will need the following credentials from your **CometChat application**: -> -> 1. **App ID** -> 2. **Auth Key** -> 3. **Region** -> -> Ensure you have these details ready before proceeding with the installation and configuration. - -*** - -## **Register & Set Up CometChat** - -Follow these steps to **register on CometChat** and **set up your development environment**. - -### **Step 1: Register on CometChat** - -To use **CometChat UI Kit**, you first need to register on the **CometChat Dashboard**. - -🔗 **[Click here to Sign Up](https://app.cometchat.com/login)** - -### **Step 2: Get Your Application Keys** - -After registering, create a **new app** and retrieve your **authentication details**: + +CometChat UI Kit requires browser APIs (`window`, `WebSocket`, `document`). In Next.js, always load CometChat components client-side using dynamic imports with `ssr: false`. + -1. Navigate to **Application**, then select the **Credentials** section. - -2. Note down the following keys: - - * **App ID** - * **Auth Key** - * **Region** - - - -Each CometChat application can be integrated with a **single client app**. Users within the same application can communicate across multiple platforms, including **web and mobile**. - - - -### **Step 3: Set Up Your Development Environment** - -Ensure your system meets the following **prerequisites** before proceeding with integration. +--- -**System Requirements:** +## Prerequisites -* **Node.js** installed on your machine. -* A code editor like **[Visual Studio Code](https://code.visualstudio.com/)** or **[Cursor](https://www.cursor.com/)**. -* **npm** or **Yarn** package manager installed. +You need three things from the [CometChat Dashboard](https://app.cometchat.com/): -*** +| Credential | Where to find it | +| --- | --- | +| App ID | Dashboard → Your App → Credentials | +| Auth Key | Dashboard → Your App → Credentials | +| Region | Dashboard → Your App → Credentials (e.g. `us`, `eu`, `in`) | -## **Built With** +You also need Node.js (v16+) and npm/yarn installed. -The CometChat UI Kit for React relies on the following technologies: + +Auth Key is for development only. In production, generate Auth Tokens server-side via the [REST API](https://api-explorer.cometchat.com/) and use [`loginWithAuthToken()`](/ui-kit/react/methods#login-using-auth-token). Never ship Auth Keys in client code. + -| Technology | Description | -| ---------------------------------------------------- | ------------------------------------- | -| [Node.js](https://nodejs.org/) | JavaScript runtime environment | -| [npm](https://www.npmjs.com/get-npm) | Node Package Manager | -| [React](https://www.npmjs.com/package/react) | JavaScript library for UI development | -| [React DOM](https://www.npmjs.com/package/react-dom) | React package for rendering UI | +--- -*** +## Step 1 — Create a Next.js Project -## **Getting Started** +```bash lines +npx create-next-app@latest my-app --typescript +cd my-app +``` -### **Step 1: Create a Next.js Project** +--- -1. **Open your code editor** (e.g., **VS Code**, **Cursor**). -2. **Initialize a new Next.js project** using one of the following methods: +## Step 2 — Install the UI Kit - -**Using Create Next App** - + +```bash lines +npm install @cometchat/chat-uikit-react ``` -npx create-next-app@latest my-app --typescript -cd my-app + + +```bash lines +yarn add @cometchat/chat-uikit-react ``` - - -3. **Open the project directory in your code editor**. -4. **Begin developing your Next.js application in the "app" directory.**. -5. **Install additional dependencies as needed**. - -*** - -### **Step 2: Install Dependencies** +This installs the UI Kit and its dependency `@cometchat/chat-sdk-javascript` automatically. -The **CometChat UI Kit for React** is an **extension** of the **CometChat JavaScript SDK**.\ -Installing it will **automatically** include the core **Chat SDK**, enabling **seamless integration**. +If you want voice/video calling, also install: -```java -npm install @cometchat/chat-uikit-react +```bash lines +npm install @cometchat/calls-sdk-javascript ``` -*** +--- -### **Step 3: Initialize CometChat UI Kit** +## Step 3 — Initialize CometChat -Before using any features of the **CometChat UI Kit** or **CometChat SDK**, you must **initialize** the required settings. -```ts +```ts lines highlight={7-9} import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; /** @@ -144,35 +102,24 @@ const COMETCHAT_CONSTANTS = { AUTH_KEY: "AUTH_KEY", // Replace with your Auth Key (leave blank if using Auth Token) }; -/** - * Configure the CometChat UI Kit using the UIKitSettingsBuilder. - * This setup determines how the chat UI behaves. - */ const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) // Assign the App ID - .setRegion(COMETCHAT_CONSTANTS.REGION) // Assign the App's Region - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) // Assign the Authentication Key (if applicable) - .subscribePresenceForAllUsers() // Enable real-time presence updates for all users - .build(); // Build the final configuration + .setAppId(COMETCHAT_CONSTANTS.APP_ID) + .setRegion(COMETCHAT_CONSTANTS.REGION) + .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) + .subscribePresenceForAllUsers() + .build(); -/** - * Initialize the CometChat UI Kit with the configured settings. - * Once initialized successfully, you can proceed with user authentication and chat features. - */ -CometChatUIKit.init(UIKitSettings)! - .then(() => { +CometChatUIKit.init(UIKitSettings) + ?.then(() => { console.log("CometChat UI Kit initialized successfully."); - // You can now call login function to authenticate users }) .catch((error) => { - console.error("CometChat UI Kit initialization failed:", error); // Log errors if initialization fails + console.error("CometChat UI Kit initialization failed:", error); }); ``` - - -```js +```js lines highlight={7-9} import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; /** @@ -184,80 +131,45 @@ const COMETCHAT_CONSTANTS = { AUTH_KEY: "AUTH_KEY", // Replace with your Auth Key (leave blank if using Auth Token) }; -/** - * Configure the CometChat UI Kit using the UIKitSettingsBuilder. - * This setup determines how the chat UI behaves. - */ const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) // Assign the App ID - .setRegion(COMETCHAT_CONSTANTS.REGION) // Assign the App's Region - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) // Assign the Authentication Key (if applicable) - .subscribePresenceForAllUsers() // Enable real-time presence updates for all users - .build(); // Build the final configuration + .setAppId(COMETCHAT_CONSTANTS.APP_ID) + .setRegion(COMETCHAT_CONSTANTS.REGION) + .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) + .subscribePresenceForAllUsers() + .build(); -/** - * Initialize the CometChat UI Kit with the configured settings. - * Once initialized successfully, you can proceed with user authentication and chat features. - */ CometChatUIKit.init(UIKitSettings) .then(() => { console.log("CometChat UI Kit initialized successfully."); - // You can now call login function to authenticate users }) .catch((error) => { - console.error("CometChat UI Kit initialization failed:", error); // Log errors if initialization fails + console.error("CometChat UI Kit initialization failed:", error); }); ``` - - - - -Ensure you replace the placeholders with your actual CometChat credentials. - - - -*** - -### **Step 4: User Login** - -To authenticate a user, you need a **`UID`**. You can either: - -1. **Create new users** on the **[CometChat Dashboard](https://app.cometchat.com)**, **[CometChat SDK Method](/ui-kit/react/methods#create-user)** or **[via the API](https://api-explorer.cometchat.com/reference/creates-user)**. + +`init()` must resolve before you call `login()`. If you call `login()` before init completes, it will fail silently. Note the `?.then()` — in Next.js, `init()` may return `undefined` if settings are invalid. + -2. **Use pre-generated test users**: - - * `cometchat-uid-1` - * `cometchat-uid-2` - * `cometchat-uid-3` - * `cometchat-uid-4` - * `cometchat-uid-5` - -The **Login** method returns a **User object** containing all relevant details of the logged-in user. - -*** +--- - +## Step 4 — Login -**Security Best Practices** +After init resolves, log the user in. For development, use one of the pre-created test UIDs: -* The **Auth Key** method is recommended for **proof-of-concept (POC) development** and early-stage testing. -* For **production environments**, it is strongly advised to use an **[Auth Token](/ui-kit/react/methods#login-using-auth-token)** instead of an **Auth Key** to enhance security and prevent unauthorized access. - - +`cometchat-uid-1` · `cometchat-uid-2` · `cometchat-uid-3` · `cometchat-uid-4` · `cometchat-uid-5` -```ts +```ts lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; const UID = "UID"; // Replace with your actual UID CometChatUIKit.getLoggedinUser().then((user: CometChat.User | null) => { if (!user) { - // If no user is logged in, proceed with login CometChatUIKit.login(UID) .then((user: CometChat.User) => { console.log("Login Successful:", { user }); @@ -265,22 +177,19 @@ CometChatUIKit.getLoggedinUser().then((user: CometChat.User | null) => { }) .catch(console.log); } else { - // If user is already logged in, mount your app + // Already logged in — mount your app } }); ``` - - -```js +```js lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; const UID = "UID"; // Replace with your actual UID CometChatUIKit.getLoggedinUser().then((user) => { if (!user) { - // If no user is logged in, proceed with login CometChatUIKit.login(UID) .then((user) => { console.log("Login Successful:", { user }); @@ -288,147 +197,147 @@ CometChatUIKit.getLoggedinUser().then((user) => { }) .catch(console.log); } else { - // If user is already logged in, mount your app + // Already logged in — mount your app } }); ``` - - -*** - -### **Step 5: Choose a Chat Experience** +Key points: +- `getLoggedinUser()` checks for an existing session so you don't re-login unnecessarily. +- `login(uid)` skips the API call if a session already exists and returns the cached user. +- Components must not render until login resolves — use a state flag to gate rendering. -Integrate a conversation view that suits your application's **UX requirements**. Below are the available options: - -*** - -#### **1️⃣ Conversation List + Message View** + +For production, use [`loginWithAuthToken()`](/ui-kit/react/methods#login-using-auth-token) instead of Auth Key. Generate tokens server-side via the REST API. + -**Best for:** Applications that need a **two-panel layout**, such as web-based chat interfaces (e.g., WhatsApp Web, Slack). +--- -**Features:** +## Step 5 — Add the CSS Import -* **Two-panel layout** – Displays the conversation list on the left and the active chat window on the right. -* **One-to-one & group conversations** – Seamless switching between private and group chats. -* **Multiple conversations** – Effortlessly switch between different chat windows. -* **Easy navigation** – Intuitive UI for finding and accessing chats quickly. -* **Tap-to-view on mobile** – In mobile layouts, tapping a conversation opens the **Message View**, optimizing space. -* **Real-time updates** – Auto-refreshes messages and conversation lists. -* **Message sync** – Ensures messages stay updated across all sessions and devices. +Add this line at the top of your global CSS file (e.g. `globals.css`): - - - +```css title="globals.css" lines +@import url("@cometchat/chat-uikit-react/css-variables.css"); +``` -**Recommended for:** +Also ensure your global CSS sets `height: 100%` on the root elements: -* Desktop-first applications -* Apps requiring a **rich user experience** with seamless navigation -* Platforms supporting both **individual and group messaging** -* **Mobile-friendly** apps needing a **tap-to-open message view** +```css title="globals.css" lines +html, +body { + height: 100%; +} -[](https://link.cometchat.com/next-conversation-list-message) +#__next { + height: 100%; +} +``` -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. +Without the CSS import, components will render with broken or missing styles. Without the height rules, the chat UI won't fill the viewport. -[Integrate Conversation List + Message](./next-conversation) +--- -*** +## Step 6 — Choose a Chat Experience -#### **2️⃣ One-to-One/Group Chat** +Integrate a conversation view that suits your app's UX. Each option below includes a live CodeSandbox demo and a step-by-step guide. -**Best for:** Apps that require a **focused, direct messaging experience** without a sidebar. +### Conversation List + Message View -**Features:** +Two-panel layout — conversation list on the left, messages on the right. Think WhatsApp Web or Slack. -* **Dedicated chat window** – Ideal for one-on-one or group messaging. -* **No conversation list** – Users directly enter the chat without navigating through a list. -* **Supports both One-to-One and Group Chats** – Easily configurable with minor code modifications. -* **Optimized for mobile** – Full-screen chat experience without distractions. -* **Seamless real-time communication** – Auto-updates messages for a smooth experience. -* **Ideal for support chat or community-based messaging.** +- Two-panel layout with conversation list and active chat window +- Switch between one-to-one and group conversations +- Tap-to-view on mobile — tapping a conversation opens the message view +- Real-time updates and message sync across sessions - + -**Recommended for:** - -* **Support chat applications** – Direct user-agent communication. -* **Apps focusing on direct messaging** – No distractions from other conversations. -* **Community or group chat applications** – A structured way to interact in groups. -* **Mobile-first applications** – Designed for compact and dedicated messaging experiences. - -[](https://link.cometchat.com/next-one-on-one) - -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. +[](https://link.cometchat.com/next-conversation-list-message) -[Integrate One-to-One/Group Chat](./next-one-to-one-chat) +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -*** + + Step-by-step guide to build this layout + -#### **3️⃣ Tab-Based Chat Experience** +--- -**Best for:** Apps that need a **structured, multi-feature navigation system** for seamless interaction between **chats, calls, users, and settings**. +### One-to-One / Group Chat -**Features:** +Single chat window — no sidebar. Good for support chat, embedded widgets, or focused messaging. -* **Tab Navigation** – Easily switch between **Chat, Call Logs, Users, and Settings**. -* **Dedicated Chat Window** – Full-screen messaging experience for focused communication. -* **No Sidebar** – Unlike multi-panel UI, this design prioritizes individual interactions. -* **Unified Experience** – Users can seamlessly manage conversations, call history, and settings from a single interface. -* **Scalable for future features** – Easily extend to include more functionalities such as notifications or contact management. -* **Optimized for both desktop and mobile** – Ensures a smooth experience across different screen sizes. +- Dedicated chat window for one-on-one or group messaging +- No conversation list — users go directly into the chat +- Full-screen experience optimized for mobile +- Ideal for support chat or community messaging - + -**Recommended for:** +[](https://link.cometchat.com/next-one-on-one) -* **Apps requiring structured navigation** – Clearly separate chat, calls, and settings. -* **Multi-feature chat apps** – Supporting different functionalities in an organized way. -* **Mobile-first applications** – Ideal for apps needing tab-based UI for easy access to features. -* **Support & enterprise chat solutions** – Perfect for help desks, business chat platforms, and customer support apps. +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -[](https://link.cometchat.com/next-tabs-sidebar-message) + + Step-by-step guide to build this layout + -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. +--- -[Integrate Tab-Based Chat](./next-tab-based-chat) +### Tab-Based Chat -*** +Tabbed navigation — Chat, Call Logs, Users, Settings in separate tabs. Good for full-featured apps. -## **Build Your Own Chat Experience** +- Tab navigation between Chat, Call Logs, Users, and Settings +- Full-screen messaging within each tab +- Unified experience for conversations, call history, and settings +- Scales well for adding future features like notifications or contacts -**Best for:** Developers who need complete control over their chat interface, allowing customization of components, themes, and features to align with their app’s design and functionality. Whether you're enhancing an existing chat experience or building from scratch, this approach provides the flexibility to tailor every aspect to your needs. + + + -**Recommended for:** +[](https://link.cometchat.com/next-tabs-sidebar-message) -* Apps that require **a fully customized chat experience**. -* Developers who want to **extend functionalities and modify UI components**. -* Businesses integrating chat seamlessly into **existing platforms**. +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -**Key Areas to Explore:** + + Step-by-step guide to build this layout + -* **[React Sample App](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app)** – Fully functional sample applications to accelerate your development. -* **[Core Features](./core-features)** – Learn about messaging, real-time updates, and other essential capabilities. -* **[Components](./components-overview)** – Utilize prebuilt UI elements or customize them to fit your design. -* **[Themes](./theme)** – Adjust colors, fonts, and styles to match your branding. -* **[Build Your Own UI](./../../../sdk/javascript/overview)** – Prefer a custom UI over our UI Kits? Explore our SDKs to create a tailored chat experience. +--- -*** +## Build Your Own Chat Experience -## **Next Steps** +Need full control over the UI? Use individual components, customize themes, and wire up your own layouts. -Now that you’ve selected your **chat experience**, proceed to the **integration guide**: +- [Sample App](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) — Working reference app to compare against +- [Components](/ui-kit/react/components-overview) — All prebuilt UI elements with props and customization options +- [Core Features](/ui-kit/react/core-features) — Messaging, real-time updates, and other capabilities +- [Theming](/ui-kit/react/theme) — Colors, fonts, dark mode, and custom styling +- [Build Your Own UI](/sdk/javascript/overview) — Skip the UI Kit entirely and build on the raw SDK -* **[Integrate Conversation List + Message](/ui-kit/react/next-conversation)** -* **[Integrate One-to-One Chat](/ui-kit/react/next-one-to-one-chat)** -* **[Integrate Tab-Based Chat](/ui-kit/react/next-tab-based-chat)** -* **[Advanced Customizations](/ui-kit/react/theme)** +--- -*** +## Next Steps + + + + Browse all prebuilt UI components + + + Customize colors, fonts, and styles + + + Chat features included out of the box + + + Common issues and fixes + + diff --git a/ui-kit/react/next-one-to-one-chat.mdx b/ui-kit/react/next-one-to-one-chat.mdx index 6b9ca33f4..af5dbacb7 100644 --- a/ui-kit/react/next-one-to-one-chat.mdx +++ b/ui-kit/react/next-one-to-one-chat.mdx @@ -1,91 +1,89 @@ --- -title: "Building A One To One/Group Chat Experience" -sidebarTitle: "One To One/Group Chat" +title: "One-to-One / Group Chat" +sidebarTitle: "One-to-One / Group Chat" +description: "Build a focused one-to-one or group chat experience in Next.js with CometChat UI Kit." --- -The **One-to-One Chat** feature provides a streamlined **direct messaging interface**, making it ideal for **support chats, dating apps, and private messaging platforms**. This setup eliminates distractions by focusing solely on a **dedicated chat window**. + -[](https://link.cometchat.com/next-one-on-one) +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Framework | Next.js | +| Components | `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Single chat window — no sidebar, no conversation list | +| Prerequisite | Complete [Next.js Integration](/ui-kit/react/next-js-integration) Steps 1–5 first | +| SSR | Dynamic import with `ssr: false` — CometChat requires browser APIs | +| Pattern | Support chat, embedded widgets, focused messaging | -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. + -*** +This guide builds a single chat window — no sidebar, no conversation list. Users go directly into a one-to-one or group chat. Good for support chat, embedded widgets, or any focused messaging experience. -## **User Interface Preview** +This assumes you've already completed [Next.js Integration](/ui-kit/react/next-js-integration) (project created, UI Kit installed, CSS imported). -### **Key Components** - -1. **Chat Header** – Displays recipient details and optional call/video call buttons. -2. **Message View** – Shows real-time chat history. -3. **Message Input Box** – Enables users to send messages, media, and reactions. - -*** - -## **Step-by-Step Guide** - -### **Step 1: Implement the Chat Header** - -* Display **profile picture, name, and online status**. -* Add **voice and video call buttons** (optional). - -```html - -``` - -### **Step 2: Build the Message View** +[](https://link.cometchat.com/next-one-on-one) -* Load **chat history** and **real-time messages**. -* Ensure **smooth scrolling and timestamp visibility**. +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -```html - -``` +--- -### **Step 3: Add the Message Composer** +## What You're Building -* Include a **text input field**. -* Support **media uploads, file attachments, emojis, and reactions**. +Three components stacked vertically: -```html - -``` +1. **Chat header** — displays recipient name, avatar, online status, and optional call buttons +2. **Message list** — real-time chat history with scrolling +3. **Message composer** — text input with media, emojis, and reactions -*** +--- -#### **Implementation** +## Step 1 — Create the CometChatNoSSR Component -Now we will create the `CometChatNoSSR.tsx` & `CometChatNoSSR.css` files. Here, we will initialize the CometChat UI Kit, log in a user, and build the messaging experience using `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` components. +This component handles init, login, fetches the target user/group, and renders the chat UI. It runs client-side only. -``` -src/ -│── CometChatNoSSR/ -│ ├── CometChatNoSSR.tsx -│ ├── CometChatNoSSR.css -``` + + + + + + + + + + -```tsx CometChatNoSSR.tsx +```tsx title="CometChatNoSSR.tsx" lines highlight={13-15, 19} import React, { useEffect, useState } from "react"; -import { CometChatMessageComposer, CometChatMessageHeader, CometChatMessageList, CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; +import { + CometChatMessageComposer, + CometChatMessageHeader, + CometChatMessageList, + CometChatUIKit, + UIKitSettingsBuilder, +} from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import "./CometChatNoSSR.css"; const COMETCHAT_CONSTANTS = { - APP_ID: "", - REGION: "", - AUTH_KEY: "", + APP_ID: "", // Replace with your App ID + REGION: "", // Replace with your Region + AUTH_KEY: "", // Replace with your Auth Key (dev only) }; +// Fetch the user whose chat you want to load +const UID = "cometchat-uid-1"; + const CometChatNoSSR: React.FC = () => { const [user, setUser] = useState(undefined); const [selectedUser, setSelectedUser] = useState(undefined); - // eslint-disable-next-line @typescript-eslint/no-unused-vars const [selectedGroup, setSelectedGroup] = useState(undefined); useEffect(() => { @@ -101,7 +99,7 @@ const CometChatNoSSR: React.FC = () => { console.log("Initialization completed successfully"); CometChatUIKit.getLoggedinUser().then((loggedInUser) => { if (!loggedInUser) { - CometChatUIKit.login("superhero1") + CometChatUIKit.login("cometchat-uid-2") .then((user) => { console.log("Login Successful", { user }); setUser(user); @@ -118,26 +116,16 @@ const CometChatNoSSR: React.FC = () => { useEffect(() => { if (user) { - // Fetch user or group from CometChat SDK whose chat you want to load. - - /** Fetching User */ - const UID = "cometchat-uid-1"; CometChat.getUser(UID).then( - user => { - setSelectedUser(user); - }, error => { - console.log("User fetching failed with error:", error); - } + (user) => setSelectedUser(user), + (error) => console.log("User fetching failed with error:", error) ); - /** Fetching Group */ - // const GUID = "GUID" + // To load a group chat instead, uncomment below: + // const GUID = "GUID"; // CometChat.getGroup(GUID).then( - // group => { - // setSelectedGroup(group); - // }, error => { - // console.log("User fetching failed with error:", error); - // } + // (group) => setSelectedGroup(group), + // (error) => console.log("Group fetching failed with error:", error) // ); } }, [user]); @@ -151,7 +139,9 @@ const CometChatNoSSR: React.FC = () => {
) : ( -
Select Conversation to start
+
+ Set a user or group UID in CometChatNoSSR.tsx to start chatting +
)} ) : undefined; @@ -161,174 +151,113 @@ export default CometChatNoSSR; ``` - -```css CometChatNoSSR.css +```css title="CometChatNoSSR.css" lines .messages-wrapper { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; } .empty-conversation { - height: 100%; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - background: white; - color: var(--cometchat-text-color-secondary, #727272); - font: var(--cometchat-font-body-regular, 400 14px Roboto); + height: 100%; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + background: white; + color: var(--cometchat-text-color-secondary, #727272); + font: var(--cometchat-font-body-regular, 400 14px Roboto); } .cometchat .cometchat-message-composer { - border-radius: 0px; + border-radius: 0px; } ``` - -In the code snippet above, ensure you select either a user or a group based on your chat requirement. You can also determine this dynamically depending on the conversation type. +Key points: +- `CometChat.getUser(UID)` fetches the user object from the SDK — you need a real user object, not a manually constructed one. +- Pass either `user` or `group` to the message components, never both. +- The highlighted lines show where to set your credentials. -#### **Fetching a User (One-on-One Chat)** +--- -```javascript -const UID = "cometchat-uid-1"; -CometChat.getUser(UID).then( - user => { - setSelectedUser(user); - }, error => { - console.log("User fetching failed with error:", error); - } -); -``` +## Switching Between User and Group Chat -#### **Fetching a Group (Group Chat)** +To load a group chat instead of one-to-one, replace the `getUser` call with `getGroup`: -```javascript -const GUID = "GUID" -CometChat.getGroup(GUID).then( - group => { - setSelectedGroup(group); - }, error => { - console.log("User fetching failed with error:", error); - } -); -``` +```tsx highlight={1} lines +const GUID = "GUID"; // Replace with your actual Group ID -### **Step 4: Disabling SSR for `CometChatNoSSR.tsx` in Next.js** +CometChat.getGroup(GUID) + .then((group) => setSelectedGroup(group)) + .catch((error) => console.error("Failed to fetch group:", error)); +``` -In this update, we will **disable Server-Side Rendering (SSR) for `CometChatNoSSR.tsx`** while keeping the rest of the application’s SSR functionality intact. This ensures that the **CometChat UI Kit components load only on the client-side**, preventing SSR-related issues. +--- -#### **Disabling SSR in `index.tsx`** +## Step 2 — Disable SSR in Your Page -Modify your `index.tsx` file to dynamically import the `CometChatNoSSR.tsx` component with `{ ssr: false }`. +Dynamically import `CometChatNoSSR` with `ssr: false` so it only loads client-side. -```tsx index.tsx -import { Inter } from "next/font/google"; +```tsx title="index.tsx" lines import dynamic from "next/dynamic"; +import "@cometchat/chat-uikit-react/css-variables.css"; -import '@cometchat/chat-uikit-react/css-variables.css'; - -const inter = Inter({ subsets: ["latin"] }); - -// Dynamically import CometChat component with SSR disabled -const CometChatComponent = dynamic(() => import("../CometChatNoSSR/CometChatNoSSR"), { - ssr: false, -}); +const CometChatComponent = dynamic( + () => import("../CometChatNoSSR/CometChatNoSSR"), + { ssr: false } +); export default function Home() { return ; } ``` -#### **Why disable SSR?** - -* The CometChat UI Kit depends on browser APIs (window, document, WebSockets). -* Next.js pre-renders components on the server, which can cause errors with browser-specific features. -* By setting `{ ssr: false }`, we ensure that CometChatNoSSR.tsx only loads on the client. - -*** - -### **Step 5: Update Global CSS** - -Next, add the following styles to global.css to ensure CometChat UI Kit is properly styled. - -```css global.css -:root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -/** Give your App a height of `100%`. Keep other CSS properties in the below selector as it is. */ -.root { - height: 100%; -} - -#__next { - height: 100%; -} - -html, -body { - height: 100%; -} - -html, -body { - max-width: 100vw; - overflow-x: hidden; -} - -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; -} +--- -a { - color: inherit; - text-decoration: none; -} +## Step 3 — Run the Project -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} + + +```bash lines +npm run dev ``` - -*** - -### **Step 6: Run the project** - + + +```bash lines +pnpm dev ``` -npm run dev + + +```bash lines +yarn dev ``` + + -## **Next Steps** - -### **Enhance the User Experience** +You should see the chat window load with the conversation for the UID you set. -* **[Advanced Customizations](/ui-kit/react/theme)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Customize colors, fonts, and styles to match your brand + + + Browse all prebuilt UI components + + } href="/ui-kit/react/next-js-integration"> + Back to the main setup guide + + + Chat features included out of the box + + diff --git a/ui-kit/react/next-tab-based-chat.mdx b/ui-kit/react/next-tab-based-chat.mdx index 91f61a656..afd95dcc1 100644 --- a/ui-kit/react/next-tab-based-chat.mdx +++ b/ui-kit/react/next-tab-based-chat.mdx @@ -1,90 +1,92 @@ --- -title: "Building A Messaging UI With Tabs, Sidebar, And Message View" -sidebarTitle: "Tab Based Chat Experience" +title: "Tab-Based Chat" +sidebarTitle: "Tab-Based Chat" +description: "Build a tab-based messaging UI with chats, calls, users, and groups in Next.js with CometChat UI Kit." --- -This guide walks you through creating a **tab-based messaging UI** using **React** and **CometChat UIKit**. The UI will include different sections for **Chats, Calls, Users, and Groups**, allowing seamless navigation. + -[](https://link.cometchat.com/next-tabs-sidebar-message) +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Framework | Next.js | +| Components | `CometChatConversations`, `CometChatCallLogs`, `CometChatUsers`, `CometChatGroups`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Tabbed sidebar (Chats, Calls, Users, Groups) + message view | +| Prerequisite | Complete [Next.js Integration](/ui-kit/react/next-js-integration) Steps 1–5 first | +| SSR | Dynamic import with `ssr: false` — CometChat requires browser APIs | +| Pattern | Full-featured messaging app with multiple sections | -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. + -*** +This guide builds a tabbed messaging UI — Chats, Calls, Users, and Groups tabs in the sidebar, with a message view on the right. Good for full-featured apps that need more than just conversations. -## **User Interface Preview** +This assumes you've already completed [Next.js Integration](/ui-kit/react/next-js-integration) (project created, UI Kit installed, CSS imported). -This layout consists of: - -1. **Sidebar (Conversation List)** – Displays recent conversations with active users and groups. -2. **Message View** – Shows the selected chat with real-time messages. -3. **Message Input Box** – Allows users to send messages seamlessly. - -*** - -## **Step-by-Step Guide** - -### **Step 1: Create a Tab Component** - -To manage navigation, let's build a **`CometChatTabs`** component. This component will render different tabs and allow switching between sections dynamically. +[](https://link.cometchat.com/next-tabs-sidebar-message) -#### **Folder Structure** +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -Create a `CometChatTabs` folder inside your `src` directory and add the following files: +--- -```php -public/ -├── assets # These are the images you need to save -│ ├── chats.svg -│ ├── calls.svg -│ ├── users.svg -│ ├── groups.svg -src/ -│── CometChatTabs/ -│ ├── CometChatTabs.tsx -│ ├── CometChatTabs.css -``` +## What You're Building -#### **Download the Icons** +Three sections working together: -These icons are available in the **CometChat UI Kit assets folder**. You can find them at:\ -🔗 [GitHub Assets Folder](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/assets) +1. **Tab bar** — switches between Chats, Calls, Users, and Groups +2. **Sidebar** — renders the list for the active tab +3. **Message view** — header + messages + composer for the selected item -*** +--- -#### **Implementation** +## Step 1 — Create the Tab Component + + + + + + + + + + + + +Tab icons need to be placed in `public/assets/`. Download them from the [CometChat UI Kit assets folder on GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/assets). + + + + + + + + + + + -```tsx CometChatTabs.tsx +```tsx title="CometChatTabs.tsx" lines import { useState } from "react"; import "./CometChatTabs.css"; -// Define icon paths for each tab const chatsIcon = "/assets/chats.svg"; const callsIcon = "/assets/calls.svg"; const usersIcon = "/assets/users.svg"; const groupsIcon = "/assets/groups.svg"; -// CometChatTabs component to display tab options export const CometChatTabs = (props: { - onTabClicked?: (tabItem: { name: string; icon?: string }) => void; // Callback when a tab is clicked - activeTab?: string; // Name of the currently active tab + onTabClicked?: (tabItem: { name: string; icon?: string }) => void; + activeTab?: string; }) => { - // Destructure props with default fallback - const { - onTabClicked = () => {}, // Fallback to no-op if not provided - activeTab, - } = props; - - // State to track the currently hovered tab + const { onTabClicked = () => {}, activeTab } = props; const [hoverTab, setHoverTab] = useState(""); - // Array of tab items with their labels and icons const tabItems = [ { name: "CHATS", icon: chatsIcon }, { name: "CALLS", icon: callsIcon }, @@ -94,7 +96,6 @@ export const CometChatTabs = (props: { return (
- {/* Loop through each tab item to render it */} {tabItems.map((tabItem) => { const isActive = activeTab === tabItem.name.toLowerCase() || @@ -104,9 +105,8 @@ export const CometChatTabs = (props: {
onTabClicked(tabItem)} // Invoke callback on click + onClick={() => onTabClicked(tabItem)} > - {/* Icon section with mask styling */}
setHoverTab(tabItem.name.toLowerCase())} onMouseLeave={() => setHoverTab("")} /> - - {/* Tab label */}
- -```css CometChatTabs.css -/* Main container for the CometChat tab bar */ +```css title="CometChatTabs.css" lines .cometchat-tab-component { - display: flex; /* Align child tabs horizontally */ - width: 100%; /* Full-width tab bar */ - padding: 0px 8px; /* Horizontal padding */ - align-items: flex-start; /* Align tab items to the top */ - gap: 8px; /* Space between tab items */ - border-top: 1px solid var(--cometchat-border-color-light, #F5F5F5); /* Top border */ - border-right: 1px solid var(--cometchat-border-color-light, #F5F5F5); /* Right border */ - background: var(--cometchat-background-color-01, #FFF); /* Background color */ + display: flex; + width: 100%; + padding: 0px 8px; + align-items: flex-start; + gap: 8px; + border-top: 1px solid var(--cometchat-border-color-light, #F5F5F5); + border-right: 1px solid var(--cometchat-border-color-light, #F5F5F5); + background: var(--cometchat-background-color-01, #FFF); } -/* Styles for each individual tab */ .cometchat-tab-component__tab { display: flex; - flex-direction: column; /* Stack icon and text vertically */ - justify-content: center; /* Center vertically */ - align-items: center; /* Center horizontally */ - padding: 12px 0px 10px 0px; /* Top and bottom spacing */ - gap: 4px; /* Space between icon and text */ - flex: 1 0 0; /* Equally distribute available space among tabs */ - min-height: 48px; /* Minimum height for consistent layout */ + padding: 12px 0px 10px 0px; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 4px; + flex: 1 0 0; + min-height: 48px; } -/* Default tab icon style */ .cometchat-tab-component__tab-icon { display: flex; width: 32px; height: 32px; justify-content: center; align-items: center; - background: var(--cometchat-icon-color-secondary); /* Default icon background */ + background: var(--cometchat-icon-color-secondary); -webkit-mask-size: contain; -webkit-mask-position: center; -webkit-mask-repeat: no-repeat; @@ -187,116 +181,92 @@ export const CometChatTabs = (props: { cursor: pointer; } -/* Tab text label style */ .cometchat-tab-component__tab-text { - color: var(--cometchat-text-color-secondary, #727272); /* Default label color */ + color: var(--cometchat-text-color-secondary, #727272); text-align: center; - font: var(--cometchat-font-caption1-medium, 500 12px Roboto); /* Font style */ + font: var(--cometchat-font-caption1-medium, 500 12px Roboto); cursor: pointer; } -/* Highlighted icon style for active/hovered tab */ .cometchat-tab-component__tab-icon-active { - background: var(--cometchat-icon-color-highlight); /* Highlight color */ + background: var(--cometchat-icon-color-highlight); } -/* Highlighted text style for active/hovered tab */ .cometchat-tab-component__tab-text-active { - color: var(--cometchat-text-color-highlight); /* Highlighted text color */ + color: var(--cometchat-text-color-highlight); } ``` - -*** - -### **Step 2: Create Sidebar** - -Let's create the `Sidebar` component which will render different conversations. +--- -#### **Folder Structure** +## Step 2 — Create the Sidebar Component -Create a `CometChatSelector` folder inside your `src/app` directory and add the following files: +The sidebar renders the list for whichever tab is active, plus the tab bar at the bottom. -``` -src/ -│── CometChatSelector/ -│ ├── CometChatSelector.tsx -│ ├── CometChatSelector.css -``` + + + + + + + + + + -```tsx CometChatSelector.tsx +```tsx title="CometChatSelector.tsx" lines import { useEffect, useState } from "react"; import { Call, Conversation, Group, User, - CometChat + CometChat, } from "@cometchat/chat-sdk-javascript"; - import { CometChatCallLogs, CometChatConversations, CometChatGroups, - CometChatUIKit, CometChatUIKitLoginListener, - CometChatUsers + CometChatUsers, } from "@cometchat/chat-uikit-react"; - import { CometChatTabs } from "../CometChatTabs/CometChatTabs"; -// Define props interface for selector interface SelectorProps { - onSelectorItemClicked?: (input: User | Group | Conversation | Call, type: string) => void; + onSelectorItemClicked?: ( + input: User | Group | Conversation | Call, + type: string + ) => void; } export const CometChatSelector = (props: SelectorProps) => { - const { - onSelectorItemClicked = () => {}, - } = props; - - // State to manage currently logged in user + const { onSelectorItemClicked = () => {} } = props; const [loggedInUser, setLoggedInUser] = useState(); - - // State to track selected conversation, user, group, or call const [activeItem, setActiveItem] = useState< Conversation | User | Group | Call | undefined >(); - - // State to track currently active tab: "chats", "calls", "users", or "groups" const [activeTab, setActiveTab] = useState("chats"); - // Fetch logged-in user once component mounts useEffect(() => { const user = CometChatUIKitLoginListener.getLoggedInUser(); setLoggedInUser(user); - }, [CometChatUIKitLoginListener?.getLoggedInUser()]); - - // Logout function to clear user session - const logOut = () => { - CometChatUIKit.logout() - .then(() => { - setLoggedInUser(null); - }) - .catch((error) => { - console.log("Logout error:", error); - }); - }; + }, []); return ( <> - {/* Render selector content only if a user is logged in */} {loggedInUser && ( <> {activeTab === "chats" && ( { setActiveItem(item); onSelectorItemClicked(item, "updateSelectedItem"); @@ -336,12 +306,9 @@ export const CometChatSelector = (props: SelectorProps) => { )} - {/* Render the tab switcher at the bottom */} { - setActiveTab(item.name.toLowerCase()); // Update tab on click - }} + onTabClicked={(item) => setActiveTab(item.name.toLowerCase())} /> ); @@ -349,69 +316,56 @@ export const CometChatSelector = (props: SelectorProps) => { ``` - -```css CometChatSelector.css -/* Style the icon inside header menu in conversation list */ +```css title="CometChatSelector.css" lines .selector-wrapper .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon { - background: var(--cometchat-icon-color-primary); /* Primary icon color */ + background: var(--cometchat-icon-color-primary); } -/* Highlight icon on hover */ .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon:hover { - background: var(--cometchat-icon-color-highlight); /* Highlighted icon color on hover */ + background: var(--cometchat-icon-color-highlight); } -/* Remove right border from the search bar inside the list */ .cometchat-list__header-search-bar { border-right: none; } -/* Align menu list items to the left */ .cometchat .cometchat-menu-list__sub-menu-list-item { text-align: left; } -/* Positioning for the submenu inside conversations menu */ .cometchat .cometchat-conversations .cometchat-menu-list__sub-menu-list { width: 212px; top: 40px !important; left: 172px !important; } -/* Style for the logged-in user section with bottom border */ #logged-in-user { border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8); } -/* Make submenu items under logged-in user non-clickable */ #logged-in-user .cometchat-menu-list__sub-menu-item-title, #logged-in-user .cometchat-menu-list__sub-menu-list-item { cursor: default; } -/* Logout icon color inside submenu */ .cometchat-menu-list__sub-menu-list-item-icon-log-out { - background-color: var(--cometchat-error-color, #F44649); /* Error color */ + background-color: var(--cometchat-error-color, #F44649); } -/* Logout label/text color inside submenu */ .cometchat-menu-list__sub-menu-item-title-log-out { color: var(--cometchat-error-color, #F44649); } -/* Enable pointer cursor for chat menu item titles */ .chat-menu .cometchat .cometchat-menu-list__sub-menu-item-title { cursor: pointer; } -/* Remove shadow from the chat menu's submenu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu { box-shadow: none; } -/* Style the icons inside chat menu items */ .chat-menu .cometchat .cometchat-menu-list__sub-menu-icon { background-color: var(--cometchat-icon-color-primary, #141414); width: 24px; @@ -420,46 +374,56 @@ export const CometChatSelector = (props: SelectorProps) => { ``` - -### **Step 3: Render Experience** +--- + +## Step 3 — Create the CometChatNoSSR Component -Now we will update the `CometChatNoSSR.tsx` & `CometChatNoSSR.css` files to import these new components as below, +This component handles init, login, and renders the full tabbed chat experience. It runs client-side only. + + + + + + + + + + + -```tsx CometChatNoSSR.tsx +```tsx title="CometChatNoSSR.tsx" highlight={15-17, 20} lines import React, { useEffect, useState } from "react"; -import { - CometChatMessageComposer, - CometChatMessageHeader, - CometChatMessageList, - CometChatUIKit, - UIKitSettingsBuilder +import { + CometChatMessageComposer, + CometChatMessageHeader, + CometChatMessageList, + CometChatUIKit, + UIKitSettingsBuilder, } from "@cometchat/chat-uikit-react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatSelector } from "../CometChatSelector/CometChatSelector"; import "./CometChatNoSSR.css"; -// Constants for CometChat configuration +// Replace with your actual credentials const COMETCHAT_CONSTANTS = { - APP_ID: "", - REGION: "", - AUTH_KEY: "", + APP_ID: "", // Replace with your App ID + REGION: "", // Replace with your Region + AUTH_KEY: "", // Replace with your Auth Key (dev only) }; -// Functional component for CometChatNoSSR +const UID = "cometchat-uid-4"; // Replace with your actual UID + const CometChatNoSSR: React.FC = () => { - // State to store the logged-in user const [user, setUser] = useState(undefined); - // State to store selected user or group const [selectedUser, setSelectedUser] = useState(undefined); const [selectedGroup, setSelectedGroup] = useState(undefined); useEffect(() => { - // Initialize UIKit settings const UIKitSettings = new UIKitSettingsBuilder() .setAppId(COMETCHAT_CONSTANTS.APP_ID) .setRegion(COMETCHAT_CONSTANTS.REGION) @@ -467,15 +431,12 @@ const CometChatNoSSR: React.FC = () => { .subscribePresenceForAllUsers() .build(); - // Initialize CometChat UIKit CometChatUIKit.init(UIKitSettings) ?.then(() => { console.log("Initialization completed successfully"); - // Check if user is already logged in CometChatUIKit.getLoggedinUser().then((loggedInUser) => { if (!loggedInUser) { - // Perform login if no user is logged in - CometChatUIKit.login("cometchat-uid-4") + CometChatUIKit.login(UID) .then((user) => { console.log("Login Successful", { user }); setUser(user); @@ -492,16 +453,13 @@ const CometChatNoSSR: React.FC = () => { return user ? (
- {/* Sidebar with conversation list */}
- { let item = activeItem; - // Extract the conversation participant if (activeItem instanceof CometChat.Conversation) { item = activeItem.getConversationWith(); - } - // Update states based on the type of selected item + } if (item instanceof CometChat.User) { setSelectedUser(item as CometChat.User); setSelectedGroup(undefined); @@ -512,11 +470,10 @@ const CometChatNoSSR: React.FC = () => { setSelectedUser(undefined); setSelectedGroup(undefined); } - }} + }} />
- - {/* Message view section */} + {selectedUser || selectedGroup ? (
@@ -524,7 +481,7 @@ const CometChatNoSSR: React.FC = () => {
) : ( -
Select Conversation to start
+
Select a conversation to start chatting
)}
) : undefined; @@ -534,169 +491,118 @@ export default CometChatNoSSR; ```
- -```css CometChatNoSSR.css -/* Layout for the main container that holds conversations and messages */ +```css title="CometChatNoSSR.css" lines .conversations-with-messages { - display: flex; - height: 100%; - width: 100%; + display: flex; + height: 100%; + width: 100%; } -/* Sidebar wrapper for conversation list */ .conversations-wrapper { - height: 100%; - width: 480px; /* Fixed width for conversation list */ - overflow: hidden; /* Hide any overflowing content */ - display: flex; - flex-direction: column; - height: inherit; + height: 100%; + width: 480px; + overflow: hidden; + display: flex; + flex-direction: column; + height: inherit; } -/* Hide overflow content inside the conversation component */ .conversations-wrapper > .cometchat { - overflow: hidden; + overflow: hidden; } -/* Message section layout */ .messages-wrapper { - width: calc(100% - 480px); /* Take remaining space */ - height: 100%; - display: flex; - flex-direction: column; + width: calc(100% - 480px); + height: 100%; + display: flex; + flex-direction: column; } -/* Styling for when no conversation is selected */ .empty-conversation { - height: 100%; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - background: white; - color: var(--cometchat-text-color-secondary, #727272); - font: var(--cometchat-font-body-regular, 400 14px Roboto); + height: 100%; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + background: white; + color: var(--cometchat-text-color-secondary, #727272); + font: var(--cometchat-font-body-regular, 400 14px Roboto); } -/* Ensure message composer does not have rounded corners */ .cometchat .cometchat-message-composer { - border-radius: 0px; + border-radius: 0px; } ``` -
-### **Step 4: Disabling SSR for `CometChatNoSSR.tsx` in Next.js** +How it works: +- Selections from any tab (Chats, Calls, Users, Groups) flow through the same `onSelectorItemClicked` callback. +- Conversation items are unwrapped via `getConversationWith()` to extract the underlying `User` or `Group`. +- Only one of `selectedUser` / `selectedGroup` is set at a time — the other is cleared. -In this update, we will **disable Server-Side Rendering (SSR) for `CometChatNoSSR.tsx`** while keeping the rest of the application’s SSR functionality intact. This ensures that the **CometChat UI Kit components load only on the client-side**, preventing SSR-related issues. +--- -#### **Disabling SSR in `index.tsx`** +## Step 4 — Disable SSR in Your Page -Modify your `index.tsx` file to dynamically import the `CometChatNoSSR.tsx` component with `{ ssr: false }`. +Dynamically import `CometChatNoSSR` with `ssr: false` so it only loads client-side. -```tsx index.tsx -import { Inter } from "next/font/google"; +```tsx title="index.tsx" lines import dynamic from "next/dynamic"; +import "@cometchat/chat-uikit-react/css-variables.css"; -import '@cometchat/chat-uikit-react/css-variables.css'; - -const inter = Inter({ subsets: ["latin"] }); - -// Dynamically import CometChat component with SSR disabled -const CometChatComponent = dynamic(() => import("../CometChatNoSSR/CometChatNoSSR"), { - ssr: false, -}); +const CometChatComponent = dynamic( + () => import("../CometChatNoSSR/CometChatNoSSR"), + { ssr: false } +); export default function Home() { return ; } ``` -#### **Why disable SSR?** - -* The CometChat UI Kit depends on browser APIs (window, document, WebSockets). -* Next.js pre-renders components on the server, which can cause errors with browser-specific features. -* By setting `{ ssr: false }`, we ensure that CometChatNoSSR.tsx only loads on the client. - -### **Step 5: Update Global CSS** - -Next, add the following styles to global.css to ensure CometChat UI Kit is properly styled. - -```css global.css -:root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -/** Give your App a height of `100%`. Keep other CSS properties in the below selector as it is. */ -.root { - height: 100%; -} - -#__next { - height: 100%; -} - -html, -body { - height: 100%; -} - -html, -body { - max-width: 100vw; - overflow-x: hidden; -} - -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; -} +--- -a { - color: inherit; - text-decoration: none; -} +## Step 5 — Run the Project -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} + + +```bash lines +npm run dev ``` - -### **Step 6: Run the project** - + + +```bash lines +pnpm dev ``` -npm run dev + + +```bash lines +yarn dev ``` + + -*** - -## **Next Steps** - -### **Enhance the User Experience** +You should see the tab bar at the bottom of the sidebar. Switch between Chats, Calls, Users, and Groups — tapping any item loads the message view on the right. -* **[Advanced Customizations](/ui-kit/react/theme)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Customize colors, fonts, and styles to match your brand + + + Browse all prebuilt UI components + + } href="/ui-kit/react/next-js-integration"> + Back to the main setup guide + + + Chat features included out of the box + + diff --git a/ui-kit/react/outgoing-call.mdx b/ui-kit/react/outgoing-call.mdx index 89413847a..e874a0d8e 100644 --- a/ui-kit/react/outgoing-call.mdx +++ b/ui-kit/react/outgoing-call.mdx @@ -1,388 +1,562 @@ --- title: "Outgoing Call" +description: "Overlay component displaying an outgoing voice/video call with recipient info and cancel control." --- + +```json +{ + "component": "CometChatOutgoingCall", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatOutgoingCall } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Overlay component displaying an outgoing voice/video call with recipient info and cancel control.", + "cssRootClass": ".cometchat-outgoing-call", + "primaryOutput": { + "prop": "onCallCanceled", + "type": "Function" + }, + "props": { + "data": { + "call": { + "type": "CometChat.Call", + "default": "undefined", + "note": "Must come from CometChat.initiateCall()" + } + }, + "callbacks": { + "onCallCanceled": "Function", + "onError": "((error: CometChat.CometChatException) => void) | null" + }, + "sound": { + "disableSoundForCalls": { "type": "boolean", "default": false }, + "customSoundForCalls": { "type": "string", "default": "built-in" } + }, + "viewSlots": { + "titleView": "JSX.Element", + "subtitleView": "JSX.Element", + "avatarView": "JSX.Element", + "cancelButtonView": "JSX.Element" + } + }, + "events": [ + { + "name": "CometChatCallEvents.ccOutgoingCall", + "payload": "CometChat.Call", + "description": "Call initiated" + }, + { + "name": "CometChatCallEvents.ccCallAccepted", + "payload": "CometChat.Call", + "description": "Recipient accepts" + }, + { + "name": "CometChatCallEvents.ccCallRejected", + "payload": "CometChat.Call", + "description": "Recipient rejects" + }, + { + "name": "CometChatCallEvents.ccCallEnded", + "payload": "CometChat.Call", + "description": "Call session ends" + } + ], + "sdkListeners": [], + "compositionExample": { + "description": "App-level overlay rendered after CometChat.initiateCall()", + "components": ["CometChatOutgoingCall"], + "flow": "CometChat.initiateCall() returns CometChat.Call -> pass to call prop -> onCallCanceled ends session" + } +} +``` + -## Overview - -The outgoing call component is a visual representation of a user-initiated call, whether it's a voice or video call. It serves as an interface for managing outgoing calls, providing users with essential options to control the call experience. This component typically includes information about the call recipient, call controls for canceling the call, and feedback on the call status, such as indicating when the call is in progress. - - - - - -The `Outgoing Call` is comprised of the following components: - -| Components | Description | -| ---------------- | ------------------------------------------------------------------------------------------------------------------- | -| CometChat Button | This component represents a button with optional icon and text. | -| CometChat Avatar | This component component displays an image or user's avatar with fallback to the first two letters of the username. | - -## Usage +## Where It Fits -### Integration +`CometChatOutgoingCall` is an overlay component that displays the outgoing call screen with the recipient's name, avatar, and a cancel button. It plays a ringtone while the call is pending. Typically rendered at the app root level after initiating a call via `CometChat.initiateCall()`. - - -```tsx +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatOutgoingCall, CometChatUIKitConstants, } from "@cometchat/chat-uikit-react"; -import React from "react"; +import "@cometchat/chat-uikit-react/css-variables.css"; -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); +function OutgoingCallDemo() { + const [call, setCall] = useState(); - React.useEffect(() => { + useEffect(() => { const uid = "uid"; - const callObject = new CometChat.Call( uid, CometChatUIKitConstants.MessageTypes.audio, CometChatUIKitConstants.MessageReceiverType.user ); CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) + .then((c) => setCall(c)) .catch(console.log); }, []); return call ? : null; -}; +} export default OutgoingCallDemo; ``` - + + + - -```tsx -import { OutgoingCallDemo } from "./OutgoingCallDemo"; +--- -export default function App() { - return ( -
-
- -
-
- ); +## Minimal Render + +```tsx lines +import { CometChatOutgoingCall } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function OutgoingCallMinimal() { + // `call` must be a CometChat.Call object from CometChat.initiateCall() + return call ? : null; } ``` -
+Root CSS class: `.cometchat-outgoing-call` -
+--- -### Actions +## Actions and Events -[Actions](/ui-kit/react/components-overview#actions) dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type, allowing you to tailor the behavior of the component to fit your specific needs. +### Callback Props -##### 1. onCallCanceled +#### onCallCanceled -The `onCallCanceled` event gets activated when the cancel button is clicked. It does not have a default behavior. However, you can override its behavior using the following code snippet. +Fires when the cancel button is clicked. Pauses the ringtone internally before invoking the callback. - - -```ts +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatOutgoingCall, CometChatUIKitConstants, } from "@cometchat/chat-uikit-react"; -import React from "react"; -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); +function OutgoingCallWithCancel() { + const [call, setCall] = useState(); - React.useEffect(() => { + useEffect(() => { const uid = "uid"; - const callObject = new CometChat.Call( uid, CometChatUIKitConstants.MessageTypes.audio, CometChatUIKitConstants.MessageReceiverType.user ); CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) + .then((c) => setCall(c)) .catch(console.log); }, []); const cancelCall = () => { - //your custom cancel call click actions - CometChat.endCall(call!.getSessionId()).then(() => { - setCall(undefined); - }); + CometChat.endCall(call!.getSessionId()).then(() => setCall(undefined)); }; + return call ? ( ) : null; -}; +} +``` -export default OutgoingCallDemo; +#### onError + +Fires on internal errors. + +```tsx lines +import { CometChatOutgoingCall } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; + +function OutgoingCallWithError() { + return ( + { + console.error("OutgoingCall error:", error); + }} + /> + ); +} ``` - +### Global UI Events - -```js -import React, { useState, useEffect } from 'react'; -import { CometChat } from '@cometchat/chat-sdk-javascript'; -import { CometChatOutgoingCall, CometChatUIKitConstants } from '@cometchat/chat-uikit-react'; +`CometChatCallEvents` emits call lifecycle events subscribable from anywhere. Subscribe in a `useEffect` and unsubscribe on cleanup. -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); +| Event | Fires when | Payload | +| --- | --- | --- | +| `ccOutgoingCall` | A call is initiated | `CometChat.Call` | +| `ccCallAccepted` | The recipient accepts the call | `CometChat.Call` | +| `ccCallRejected` | The recipient rejects the call | `CometChat.Call` | +| `ccCallEnded` | The call session ends | `CometChat.Call` | - useEffect(() => { - const uid = "uid"; +```tsx lines +import { useEffect } from "react"; +import { CometChatCallEvents } from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user +function useCallEvents() { + useEffect(() => { + const acceptedSub = CometChatCallEvents.ccCallAccepted.subscribe( + (call: CometChat.Call) => { + console.log("Call accepted:", call.getSessionId()); + } + ); + const rejectedSub = CometChatCallEvents.ccCallRejected.subscribe( + (call: CometChat.Call) => { + console.log("Call rejected:", call.getSessionId()); + } + ); + const endedSub = CometChatCallEvents.ccCallEnded.subscribe( + (call: CometChat.Call) => { + console.log("Call ended:", call.getSessionId()); + } ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); + return () => { + acceptedSub?.unsubscribe(); + rejectedSub?.unsubscribe(); + endedSub?.unsubscribe(); + }; }, []); +} +``` - const cancelCall = () =>{ - //your custom cancel call click actions - CometChat.endCall(call!.getSessionId()) - .then(() => { - setCall(undefined); - }) - }; +### SDK Events (Real-Time, Automatic) - return ( - call && ( - - ) - ); -}; -export default OutgoingCallDemo; -``` +The component internally manages call sound playback. It plays the outgoing call ringtone on mount (unless `disableSoundForCalls={true}`) and pauses it on unmount or cancel. No SDK call listeners are attached by the component itself — call status updates are handled by the parent application. - +--- - +## Custom View Slots -##### 2. onError +All view slots on `CometChatOutgoingCall` are `JSX.Element` (not functions). They do not receive parameters — pass call data via closure if needed. -This action doesn't change the behavior of the component but rather listens for any errors that occur in the Outgoing Call component. +| Slot | Type | Replaces | +| --- | --- | --- | +| `titleView` | `JSX.Element` | Recipient name | +| `subtitleView` | `JSX.Element` | "Calling..." text | +| `avatarView` | `JSX.Element` | Recipient avatar | +| `cancelButtonView` | `JSX.Element` | Cancel call button | + +### titleView + +Replace the recipient name. + + + + -```ts +```tsx lines import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatOutgoingCall, CometChatUIKitConstants, } from "@cometchat/chat-uikit-react"; -import React from "react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); - - React.useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - function handleOnError(error: CometChat.CometChatException) { - //Your Custom Error Actions - console.log(error); - } +function OutgoingCallCustomTitle() { + // assume `call` is a CometChat.Call from CometChat.initiateCall() + const getTitleView = (call: CometChat.Call) => ( +
+ {call.getCallInitiator().getName()} {" <> "}{" "} + {call.getCallReceiver().getName()} +
+ ); return call ? ( - + ) : null; -}; - -export default OutgoingCallDemo; +} ``` -
+ +```css lines +.outgoing-call__title { + color: #141414; + text-align: center; + font: 500 24px Roboto; +} +``` + +
- -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); - - useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); +### subtitleView - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); +Replace the "Calling..." text. - function handleOnError(error) { - //Your Custom Error Actions - console.log(error); - } - return call && ; -}; + + + -export default OutgoingCallDemo; + + +```tsx lines +const getSubtitleView = (call: CometChat.Call) => ( +
+
+ {"Calling..."} +
+); + +; ``` - + +```css lines +.outgoing-call__subtitle { + display: flex; + justify-content: center; + align-items: flex-start; + gap: 8px; + color: #727272; + text-align: center; + font: 400 16px Roboto; +} +.outgoing-call__subtitle-icon { + -webkit-mask: url("") center center no-repeat; + background: #a1a1a1; + height: 24px; + width: 24px; +} +``` + -*** +### avatarView -### Filters +Replace the recipient avatar. -**Filters** allow you to customize the data displayed in a list within a `Component`. You can filter the list based on your specific criteria, allowing for a more customized. Filters can be applied using `RequestBuilders` of Chat SDK. + + + -The `Outgoing Call` component does not have any exposed filters. + + +```tsx lines +import { + CometChatAvatar, + CometChatOutgoingCall, +} from "@cometchat/chat-uikit-react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; -*** +function OutgoingCallCustomAvatar() { + const getAvatarView = (call: CometChat.Call) => ( +
+ +
+
+ ); -### Events + return call ? ( + + ) : null; +} +``` + + +```css lines +.outgoing-call__avatar .cometchat-avatar, +.outgoing-call__avatar .cometchat-avatar__image { + width: 160px; + height: 160px; + border-radius: 20px; +} -[Events](/ui-kit/react/components-overview#events) are emitted by a `Component`. By using event you can extend existing functionality. Being global events, they can be applied in Multiple Locations and are capable of being Added or Removed. +.outgoing-call__avatar-status { + background-image: url(""); + height: 44px; + width: 44px; + background-size: contain; + position: relative; + top: -45px; + right: -60px; +} +``` + + -The `Outgoing Call` component does not have any exposed filters. +### cancelButtonView -*** +Replace the cancel call button. -## Customization + + + -To fit your app's design requirements, you can customize the appearance of the Outgoing Call component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs. + + +```tsx lines +function OutgoingCallCustomCancel() { + const getCancelButtonView = (call: CometChat.Call) => ( +
+
+
+ {"End Call"} +
+
+ ); -### Style + return call ? ( + + ) : null; +} +``` + + +```css lines +.outgoing-call__cancel-button-wrapper { + height: 64px; + display: flex; + justify-content: center; + cursor: pointer; +} -Using CSS you can customize the look and feel of the component in your app like the color, size, shape, and fonts. +.outgoing-call__cancel-button { + display: flex; + width: 330px; + padding: 12px 30px; + justify-content: center; + align-items: center; + gap: 12px; + border-radius: 12px; + background-color: #f44649; + color: #fff; + font: 500 20px Roboto; +} -**Example** +.outgoing-call__cancel-button-icon { + -webkit-mask: url("") center center no-repeat; + background: #e8e8e8; + height: 32px; + width: 32px; +} +``` + + - - - +--- - - -```ts +## Common Patterns + +### Cancel and end the call session + +```tsx lines +import { useState, useEffect } from "react"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatOutgoingCall, CometChatUIKitConstants, - OutgoingCallStyle, } from "@cometchat/chat-uikit-react"; -import React from "react"; -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); +function OutgoingCallWithEndSession() { + const [call, setCall] = useState(); - React.useEffect(() => { + useEffect(() => { const uid = "uid"; - const callObject = new CometChat.Call( uid, CometChatUIKitConstants.MessageTypes.audio, CometChatUIKitConstants.MessageReceiverType.user ); CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) + .then((c) => setCall(c)) .catch(console.log); }, []); - return call ? : null; -}; + const handleCancel = () => { + if (call) { + CometChat.endCall(call.getSessionId()).then(() => setCall(undefined)); + } + }; -export default OutgoingCallDemo; + return call ? ( + + ) : null; +} ``` - +### Custom ringtone - -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, - OutgoingCallStyle, -} from "@cometchat/chat-uikit-react"; +```tsx lines +import { CometChatOutgoingCall } from "@cometchat/chat-uikit-react"; -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); +function OutgoingCallCustomSound() { + return ( + + ); +} +``` - useEffect(() => { - const uid = "uid"; +### Silent outgoing call (no ringtone) - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); +```tsx lines +import { CometChatOutgoingCall } from "@cometchat/chat-uikit-react"; - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); +function SilentOutgoingCall() { + return ( + + ); +} +``` - return call && ; -}; +--- -export default OutgoingCallDemo; -``` +## CSS Architecture - +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens (e.g., `--cometchat-primary-color`, `--cometchat-error-color`) set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-outgoing-call`) consumes these tokens via `var()` with fallback values. +3. Overrides target `.cometchat-outgoing-call` descendant selectors in a global stylesheet. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-outgoing-call` | +| Title container | `.cometchat-outgoing-call__title-container` | +| Title text | `.cometchat-outgoing-call__title` | +| Subtitle text | `.cometchat-outgoing-call__subtitle` | +| Avatar container | `.cometchat-outgoing-call__avatar` | +| Avatar image | `.cometchat-outgoing-call__avatar .cometchat-avatar` | +| Avatar text | `.cometchat-outgoing-call__avatar .cometchat-avatar__text` | +| Cancel button wrapper | `.cometchat-outgoing-call__button` | +| Cancel button | `.cometchat-outgoing-call__button .cometchat-button` | +| Cancel button icon | `.cometchat-outgoing-call__button .cometchat-button .cometchat-button__icon` | + +### Example: Themed outgoing call + + + + - -```css +```css lines .cometchat-outgoing-call__avatar .cometchat-avatar { - display: flex; - justify-content: center; - align-items: center; - flex-shrink: 0; border-radius: 16px; background: #fbaa75; } -.cometchat-outgoing-call__button { - display: flex; - align-items: center; +.cometchat-outgoing-call__button .cometchat-button { border-radius: 8px; background: #f44649; } @@ -393,636 +567,155 @@ export default OutgoingCallDemo; } ``` - +### Customization Matrix - +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Handle cancel action | Component props | `onCallCanceled` | `onCallCanceled={() => endCall()}` | +| Disable ringtone | Component props | `disableSoundForCalls` | `disableSoundForCalls={true}` | +| Custom ringtone | Component props | `customSoundForCalls` | `customSoundForCalls="/sounds/ring.mp3"` | +| Replace UI sections | Component props | View slot props | `titleView={
Custom
}` | +| Change colors, fonts, spacing | Global CSS | Target `.cometchat-outgoing-call` class | `.cometchat-outgoing-call__title { color: red; }` | -### Functionality +--- -These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can change text, set custom icons, and toggle the visibility of UI elements. +## Accessibility -Here is a code snippet demonstrating how you can customize the functionality of the `Outgoing Call` component. +The component renders a modal-like overlay. The cancel button is keyboard-focusable and activates on Enter/Space. The recipient name and "Calling..." subtitle are rendered as text content accessible to screen readers. The avatar includes the recipient name as alt text via `CometChatAvatar`. - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import React from "react"; +--- -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); - - React.useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - - return call ? ( - - ) : null; -}; - -export default OutgoingCallDemo; -``` - - - - -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); - - useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - - return ( - call && - ); -}; - -export default OutgoingCallDemo; -``` - - - - - -Below is a list of customizations along with corresponding code snippets - -| Property | Description | Code | -| ----------------- | ---------------------------------------------------------------------- | --------------------------------------------------- | -| **Call** | The CometChat call object used to set up and launch the outgoing call. | `call={call}` | -| **Disable Sound** | Disables the sound of outgoing calls. | `disableSoundForCalls={false}` | -| **Custom Sound** | Specifies a custom sound to play for outgoing calls. | `customSoundForCalls='Your Custom Sound For Calls'` | - -*** - -### Advanced - -For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component. - -*** - -#### TitleView - -This prop renders the custom title view for the outgoing call. Use this to override the existing title of user name from the outgoing call. - -The customized chat interface is displayed below. - - - - - -Use the following code to achieve the customization shown above. - - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import React from "react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); - - React.useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - - const getTitleView = (call: Call) => { - return ( -
- {call.getCallInitiator().getName()} {" <> "} {call.getCallReceiver().getName()} -
- ); - }; - - return ( - call && - ); -}; - -export default OutgoingCallDemo; -``` - -
- - -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); - - useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - - const getTitleView = (call) => { - return ( -
- {call.getCallInitiator().getName()} {" <> "} {call.getCallReceiver().getName()} -
- ); - }; - - return ( - call && - ); -}; - -export default OutgoingCallDemo; -``` - -
- - -```css -.outgoing-call__title { - color: #141414; - text-align: center; - font: 500 24px Roboto; -} -``` - - - -
- -#### SubtitleView - -This prop renders the custom sub title view for the outgoing call. Use this to override the existing sub title text from the outgoing call. - -The customized chat interface is displayed below. - - - - - -Use the following code to achieve the customization shown above. - - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import React from "react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); - - React.useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - - const getSubtitleView = (call: Call) => { - return ( -
-
- {"Calling..."} -
- ); - }; - - return ( - call && - ); -}; - -export default OutgoingCallDemo; -``` - - - - -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); - - useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); - - const getSubtitleView = (call) => { - return ( -
-
- {"Calling..."} -
- ); - }; - - return ( - call && - ); -}; - -export default OutgoingCallDemo; -``` - - - - -```css -.outgoing-call__subtitle { - display: flex; - justify-content: center; - align-items: flex-start; - gap: 8px; - color: #727272; - text-align: center; - font: 400 16px Roboto; -} - -.outgoing-call__subtitle-icon { - -webkit-mask: url("") center center no-repeat; - background: #A1A1A1; - height: 24px; - width: 24px; -} -``` - - - - - -#### AvatarView - -This prop renders the custom avatar view for the outgoing call. Use this to override the existing avatar image from the outgoing call. - -The customized chat interface is displayed below. - - - - - -Use the following code to achieve the customization shown above. - - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatAvatar, - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import React from "react"; - -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); - - React.useEffect(() => { - const uid = "uid"; - - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); +--- - const getAvatarView = (call: CometChat.Call) => { - return ( -
- -
-
- ); - }; +## Props - return ( - call && - ); -}; +All props are optional unless noted. Sorted alphabetically. -export default OutgoingCallDemo; -``` +### avatarView - +Custom JSX replacing the recipient avatar. - -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatAvatar, - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in avatar | -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); +--- - useEffect(() => { - const uid = "uid"; +### call - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); +The outgoing call object from `CometChat.initiateCall()`. - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); +| | | +| --- | --- | +| Type | `CometChat.Call` | +| Default | `undefined` | - const getAvatarView = (call) => { - return ( -
- -
-
- ); - }; +Component renders nothing when `call` is not provided. - return ( - call && - ); -}; +--- -export default OutgoingCallDemo; -``` +### cancelButtonView - +Custom JSX replacing the cancel call button. - -```css -.outgoing-call__avatar .cometchat-avatar, -.outgoing-call__avatar .cometchat-avatar__image { - width: 160px; - height: 160px; - border-radius: 20px; -} +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in cancel button | -.outgoing-call__avatar-status { - background-image: url(""); - height: 44px; - width: 44px; - background-size: contain; - position: relative; - top: -45px; - right: -60px; -} -``` +--- - +### customSoundForCalls - +URL to a custom audio file for the outgoing call ringtone. -#### CancelButtonView +| | | +| --- | --- | +| Type | `string` | +| Default | Built-in ringtone | -This prop renders the custom cancel-call button view for the outgoing call. Use this to override the existing cancel call button view from the outgoing call. +--- -The customized chat interface is displayed below. +### disableSoundForCalls - - - +Disables the outgoing call ringtone. -Use the following code to achieve the customization shown above. +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | - - -```ts -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; -import React from "react"; +--- -const OutgoingCallDemo = () => { - const [call, setCall] = React.useState(); +### onCallCanceled - React.useEffect(() => { - const uid = "uid"; +Callback fired when the cancel button is clicked. - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); +| | | +| --- | --- | +| Type | `Function` | +| Default | `undefined` | - const getCancelButtonView = (call: Call) => { - return ( -
-
-
- {"End Call"} -
-
- ); - }; +--- - return ( - call && - ); -}; +### onError -export default OutgoingCallDemo; -``` +Callback fired when the component encounters an error. - +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `undefined` | - -```js -import React, { useState, useEffect } from "react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { - CometChatOutgoingCall, - CometChatUIKitConstants, -} from "@cometchat/chat-uikit-react"; +--- -const OutgoingCallDemo = () => { - const [call, setCall] = useState(null); +### subtitleView - useEffect(() => { - const uid = "uid"; +Custom JSX replacing the "Calling..." subtitle text. - const callObject = new CometChat.Call( - uid, - CometChatUIKitConstants.MessageTypes.audio, - CometChatUIKitConstants.MessageReceiverType.user - ); +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in subtitle | - CometChat.initiateCall(callObject) - .then((c) => { - setCall(c); - }) - .catch(console.log); - }, []); +--- - const getCancelButtonView = (call) => { - return ( -
-
-
- {"End Call"} -
-
- ); - }; +### titleView - return ( - call && - ); -}; +Custom JSX replacing the recipient name. -export default OutgoingCallDemo; -``` +| | | +| --- | --- | +| Type | `JSX.Element` | +| Default | Built-in title | - +--- - -```css -.outgoing-call__cancel-button-wrapper { - height: 64px; - display: flex; - justify-content: center; - cursor: pointer; -} +## Events -.outgoing-call__cancel-button { - display: flex; - width: 330px; - padding: 12px 30px; - justify-content: center; - align-items: center; - gap: 12px; - align-self: stretch; - border-radius: 12px; - background-color: #F44649; - color: #FFF; - font: 500 20px Roboto; -} +| Event | Payload | Fires when | +| --- | --- | --- | +| `CometChatCallEvents.ccOutgoingCall` | `CometChat.Call` | Call initiated | +| `CometChatCallEvents.ccCallAccepted` | `CometChat.Call` | Recipient accepts | +| `CometChatCallEvents.ccCallRejected` | `CometChat.Call` | Recipient rejects | +| `CometChatCallEvents.ccCallEnded` | `CometChat.Call` | Call session ends | -.outgoing-call__cancel-button-icon { - -webkit-mask: url("") center center no-repeat; - background: #E8E8E8; - height: 32px; - width: 32px; -} -``` +All events are `Subject` from RxJS. Subscribe with `.subscribe()`, unsubscribe with the returned subscription's `.unsubscribe()`. - +--- - +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-outgoing-call` | +| Title container | `.cometchat-outgoing-call__title-container` | +| Title text | `.cometchat-outgoing-call__title` | +| Subtitle text | `.cometchat-outgoing-call__subtitle` | +| Avatar container | `.cometchat-outgoing-call__avatar` | +| Avatar image | `.cometchat-outgoing-call__avatar .cometchat-avatar` | +| Avatar text | `.cometchat-outgoing-call__avatar .cometchat-avatar__text` | +| Cancel button wrapper | `.cometchat-outgoing-call__button` | +| Cancel button | `.cometchat-outgoing-call__button .cometchat-button` | +| Cancel button icon | `.cometchat-outgoing-call__button .cometchat-button .cometchat-button__icon` | diff --git a/ui-kit/react/overview.mdx b/ui-kit/react/overview.mdx index 42b82d980..ee3a0041a 100644 --- a/ui-kit/react/overview.mdx +++ b/ui-kit/react/overview.mdx @@ -1,214 +1,106 @@ --- -title: "CometChat UI Kit For React" +title: "React UI Kit" sidebarTitle: "Overview" +description: "Prebuilt React components for chat, voice, and video calling. Supports React.js, Next.js, React Router, and Astro." --- -The **CometChat UI Kit** for React is a powerful solution designed to seamlessly integrate chat functionality into applications. It provides a robust set of **prebuilt UI components** that are **modular, customizable, and highly scalable**, allowing developers to accelerate their development process with minimal effort. + -*** +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` v6.3.x | +| Peer deps | `react` >=18, `react-dom` >=18, `rxjs` ^7.8.1 | +| Calling | Optional — `@cometchat/calls-sdk-javascript` | +| SSR | Client-side only. Use `ssr: false` or `client:only="react"` | +| Localization | 19 languages built-in | +| Source | [GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6) | -## **Why Choose CometChat UI Kit?** + -* **Rapid Integration** – Prebuilt UI components for faster deployment. -* **Customizable & Flexible** – Modify the UI to align with your brand’s identity. -* **Cross-Platform Compatibility** – Works seamlessly across various React-based frameworks. -* **Scalable & Reliable** – Built on CometChat's **robust chat infrastructure** for enterprise-grade performance. - -*** - -## **User Interface Preview** +The CometChat React UI Kit provides prebuilt, customizable components for adding chat, voice, and video calling to any React app. Each component handles its own data fetching, real-time listeners, and state — you just drop them into your layout. -*** - -## **Try Live Demo** +--- -**Experience the CometChat UI Kit in action:** +## Try It - - - - - + + Try the full chat experience in your browser + + + Fork, add your credentials, and start building + +--- -{/* [](https://link.cometchat.com/cometchat-demo) - -[](https://link.cometchat.com/react-conversation-list-message) */} - - -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key) in the code, and immediately preview how the UI and messages respond in real time. - -*** - -## **Integration** - -{/* ### **Option 1: UI Kit Builder (Pre-Assembled UI)** - -A ready-to-use chat interface—configured via a UI Kit Builder—built on top of our UI Kits. +## Get Started - + -**How It Works** - -* Toggle features like @mentions, reactions, media uploads, and more in a visual interface. -* Drag-and-drop or point-and-click to enable or disable components. -* Customize layouts and styles—no deep coding required. - -**Why It’s Great** - -* **Fastest Setup** – Minimal component wiring. -* **Continuous Customization** – Only turn on the features you want. -* **Fewer Moving Parts** – Reliable, pre-assembled UI that’s easy to maintain. - - - -} - href="/ui-kit/react/builder-integration" - horizontal -/> - -} - href="/ui-kit/react/builder-integration-nextjs" - horizontal -/> - -} - href="/ui-kit/react/builder-integration-react-router" - horizontal -/> - +Pick your framework and follow the step-by-step integration guide: + + + + Vite or Create React App + + } href="/ui-kit/react/next-js-integration"> + App Router with client-side rendering + + } href="/ui-kit/react/react-router-integration"> + SPA with React Router v6+ + + } href="/ui-kit/react/astro-integration"> + React islands with client:only directive + -*** - -### **Option 2: UI Components (Assemble It Yourself)** */} - -A collection of individual components—like conversation lists, message lists, message composer, etc.—each with built-in chat logic so you can customize every element. - - - - +--- -**How It Works** +## Explore + + + + Browse all prebuilt UI components + + + Chat, calling, AI, and extensions + + + Colors, fonts, dark mode, and custom styling + + + Threaded messages, new chat, search, and more + + -* Import the components you need from our UI Kits. -* Arrange them in your desired layout, applying styling or customization as needed. -* You don’t need to rewrite the SDK calls yourself—each component already integrates with CometChat logic. +--- -**Why It’s Great** +## Resources -* **Flexible Design** – You control the final UI arrangement. -* **No Extra Overhead** – Implement only the features you need. -* **Modular** – Use exactly what you want, when you want. - - -} - href="/ui-kit/react/react-js-integration" - horizontal -/> - -} - href="/ui-kit/react/builder-integration-nextjs" - horizontal -/> - -} - href="/ui-kit/react/builder-integration-react-router" - horizontal -/> - -} - href="/ui-kit/react/astro-integration" - horizontal -/> - - - -*** - -## **Next Steps for Developers** - -1. **Learn the Basics** – [Key Concepts](/fundamentals/key-concepts). - -2. **Pick a Framework** – React.js or Next.js or React Router or Astro. - -3. **Follow the Setup Guide** – - - * **UI Components** – [React.js](/ui-kit/react/react-js-integration) or [Next.js](/ui-kit/react/next-js-integration) or [React Router](/ui-kit/react/react-router-integration) or [Astro](/ui-kit/react/astro-integration). - -4. **Customize UI** – Adjust [styles, themes](/ui-kit/react/theme), and [components](/ui-kit/react/components-overview). - -5. **Test & Deploy** – Run tests and launch your chat app. - -*** - -## **Helpful Resources** - -Explore these essential resources to gain a deeper understanding of **CometChat UI Kits** and streamline your integration process. - - - - - - Fully functional sample applications to accelerate your development. - - View on GitHub - - - - - - Access the complete UI Kit source code on GitHub. - - View on GitHub - - - - - - UI design resources for customization and prototyping. - - View on Figma - - - + + Working reference app + + + Full UI Kit source on GitHub + + + Design resources and prototyping + + + Common issues and fixes + + + Open a support ticket + + + Upgrading from v5 + - -*** - -## **Need Help?** - -If you need assistance, check out: - -* [Developer Community](http://community.cometchat.com/) -* [Support Portal](https://help.cometchat.com/hc/en-us/requests/new) diff --git a/ui-kit/react/property-changes.mdx b/ui-kit/react/property-changes.mdx index 3358b3d16..3e24db884 100644 --- a/ui-kit/react/property-changes.mdx +++ b/ui-kit/react/property-changes.mdx @@ -1,6 +1,18 @@ --- -title: "Property Changes" +title: "Property Changes from V5 to V6" +description: "Detailed reference of renamed, added, and removed properties and methods when upgrading from CometChat React UI Kit v5 to v6." --- + + +| Field | Value | +| --- | --- | +| Migration scope | Property and method changes between v5 and v6 for all components | +| Components affected | Conversations, Users, Groups, Group Members, Message Header, Message List, Message Composer, Incoming Call, Outgoing Call, Call Buttons, Call Logs, CometChatLocalize | +| Key pattern change | `datePattern` (DatePatterns) replaced with `CalendarObject`-based props across all components | +| Localization | `setLocale` → `setCurrentLanguage`, `localize` → `getLocalizedString` | +| Full migration guide | [Upgrading from v5](/ui-kit/react/upgrading-from-v5) | + + ## Conversations @@ -89,6 +101,27 @@ title: "Property Changes" | Name | Description | | ------------------ | ------------------------------------------------------------------- | | getLanguageCode | Returns the language code of current language. | -| setDefaultLanguage | Sets the default lannguage if no language is passed in init method. | +| setDefaultLanguage | Sets the default language if no language is passed in init method. | | isRTL | Returns true if the active language is rtl otherwise return false. | | getDir | Returns `rtl` or `ltr` based on the active language. | + +*** + +## Next Steps + + + + Full migration guide with breaking changes. + + + Explore all v6 prebuilt UI components. + + + Init, login, logout, and other UI Kit methods. + + + Subscribe to real-time events across components. + + + +*** diff --git a/ui-kit/react/react-conversation.mdx b/ui-kit/react/react-conversation.mdx index 03ab256f4..309691b76 100644 --- a/ui-kit/react/react-conversation.mdx +++ b/ui-kit/react/react-conversation.mdx @@ -1,53 +1,63 @@ --- -title: "Building A Conversation List + Message View" +title: "Conversation List + Message View" sidebarTitle: "Conversation List + Message View" +description: "Build a two-panel conversation list + message view layout in React.js with CometChat UI Kit." --- -The **Conversation List + Message View** layout offers a seamless **two-panel chat interface**, commonly used in modern messaging applications like **WhatsApp Web, Slack, and Microsoft Teams**. + -This design enables users to switch between conversations effortlessly while keeping the chat window open, ensuring a **smooth, real-time messaging experience**. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Framework | React.js | +| Components | `CometChatConversations`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Two-panel — conversation list (left) + message view (right) | +| Prerequisite | Complete [React.js Integration](/ui-kit/react/react-js-integration) Steps 1–5 first | +| Pattern | WhatsApp Web, Slack, Microsoft Teams | -[](https://link.cometchat.com/react-conversation-list-message) - -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. + -*** +This guide builds a two-panel chat layout — conversation list on the left, messages on the right. Users tap a conversation to open it. -## **User Interface Overview** +This assumes you've already completed [React.js Integration](/ui-kit/react/react-js-integration) (project created, UI Kit installed, init + login working, CSS imported). -This layout is structured into three key sections: +[](https://link.cometchat.com/react-conversation-list-message) -1. **Sidebar (Conversation List)** – Displays active conversations, including users and groups. -2. **Message View** – Shows chat messages for the selected conversation in real-time. -3. **Message Composer** – Provides an input field for typing and sending messages, along with support for media, emojis, and reactions. +> Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -*** +--- -## **Step-by-Step Guide** +## What You're Building -### **Step 1: Create Sidebar** +Three sections working together: -Let's create the `Sidebar` component which will render different conversations. +1. **Sidebar (conversation list)** — shows all active conversations (users and groups) +2. **Message view** — displays chat messages for the selected conversation in real time +3. **Message composer** — text input with support for media, emojis, and reactions -#### **Folder Structure** +--- -Create a `CometChatSelector` folder inside your `src` directory and add the following files: +## Step 1 — Create the Sidebar Component -``` -src/ -│── CometChatSelector/ -│ ├── CometChatSelector.tsx -│ ├── CometChatSelector.css -``` +Create a `CometChatSelector` folder inside `src/`: + + + + + + + + + -```tsx CometChatSelector.tsx +```tsx title="CometChatSelector.tsx" lines import { useEffect, useState } from "react"; import { Conversation, @@ -61,189 +71,167 @@ import { } from "@cometchat/chat-uikit-react"; import "./CometChatSelector.css"; -// Define the props for the CometChatSelector component interface SelectorProps { onSelectorItemClicked?: ( input: User | Group | Conversation, type: string ) => void; - onHide?: () => void; - onNewChatClicked?: () => void; } -// CometChatSelector component export const CometChatSelector = (props: SelectorProps) => { - // Destructure props with a default function for onSelectorItemClicked const { onSelectorItemClicked = () => {} } = props; - - // State to store the logged-in user const [loggedInUser, setLoggedInUser] = useState(); - - // State to track the currently selected item (it can be a Conversation, User, or Group) const [activeItem, setActiveItem] = useState< CometChat.Conversation | CometChat.User | CometChat.Group | undefined >(); - // useEffect hook to fetch and set the logged-in user useEffect(() => { - const loggedInUser = CometChatUIKitLoginListener.getLoggedInUser(); - setLoggedInUser(loggedInUser); - }, [loggedInUser]); // Dependency on loggedInUser causes unnecessary re-renders + const user = CometChatUIKitLoginListener.getLoggedInUser(); + setLoggedInUser(user); + }, []); return ( <> - {/* Render chat conversations if a user is logged in */} {loggedInUser && ( - <> - { - setActiveItem(e); // Update the active item when an item is clicked - onSelectorItemClicked(e, "updateSelectedItem"); // Notify parent component - }} - /> - + { + setActiveItem(e); + onSelectorItemClicked(e, "updateSelectedItem"); + }} + /> )} - ); }; ``` - -```css CometChatSelector.css -/* Styles for the menu icon in the conversation header */ +```css title="CometChatSelector.css" lines +/* Menu icon in conversation header */ .selector-wrapper .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon { - background: var(--cometchat-icon-color-primary); + background: var(--cometchat-icon-color-primary); } -/* Change background color of the menu icon on hover */ .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon:hover { - background: var(--cometchat-icon-color-highlight); + background: var(--cometchat-icon-color-highlight); } -/* Remove the right border from the search bar */ .cometchat-list__header-search-bar { - border-right: none; + border-right: none; } -/* Aligns submenu list items to the left */ .cometchat .cometchat-menu-list__sub-menu-list-item { - text-align: left; + text-align: left; } -/* Adjust the width and positioning of the conversation menu list */ .cometchat .cometchat-conversations .cometchat-menu-list__sub-menu-list { - width: 212px; - top: 40px !important; - left: 172px !important; + width: 212px; + top: 40px !important; + left: 172px !important; } -/* Styles for the logged-in user section */ +/* Logged-in user section */ #logged-in-user { - border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8); + border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8); } -/* Disable cursor interaction for menu items inside logged-in user section */ #logged-in-user .cometchat-menu-list__sub-menu-item-title, #logged-in-user .cometchat-menu-list__sub-menu-list-item { - cursor: default; + cursor: default; } -/* Background color for the logout button icon */ .cometchat-menu-list__sub-menu-list-item-icon-log-out { - background-color: var(--cometchat-error-color, #F44649); + background-color: var(--cometchat-error-color, #F44649); } -/* Text color for the logout menu item */ .cometchat-menu-list__sub-menu-item-title-log-out { - color: var(--cometchat-error-color, #F44649); + color: var(--cometchat-error-color, #F44649); } -/* Enable pointer cursor for menu items inside the chat menu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu-item-title { - cursor: pointer; + cursor: pointer; } -/* Remove box-shadow from submenu in the chat menu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu { - box-shadow: none; + box-shadow: none; } -/* Styles for the submenu icon inside the chat menu */ .chat-menu .cometchat .cometchat-menu-list__sub-menu-icon { - background-color: var(--cometchat-icon-color-primary, #141414); - width: 24px; - height: 24px; + background-color: var(--cometchat-icon-color-primary, #141414); + width: 24px; + height: 24px; } -/* Styling for the chat selector container */ +/* Selector container */ .cometchat-selector { - display: flex; - width: 100%; - padding: 0px 8px; - align-items: flex-start; - gap: 8px; - border-top: 1px solid var(--cometchat-border-color-light, #F5F5F5); - border-right: 1px solid var(--cometchat-border-color-light, #F5F5F5); - background: var(--cometchat-background-color-01, #FFF); + display: flex; + width: 100%; + padding: 0px 8px; + align-items: flex-start; + gap: 8px; + border-top: 1px solid var(--cometchat-border-color-light, #F5F5F5); + border-right: 1px solid var(--cometchat-border-color-light, #F5F5F5); + background: var(--cometchat-background-color-01, #FFF); } -/* Styling for each tab inside the chat selector */ .cometchat-selector__tab { - display: flex; - padding: 12px 0px 10px 0px; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 4px; - flex: 1 0 0; - min-height: 48px; + display: flex; + padding: 12px 0px 10px 0px; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 4px; + flex: 1 0 0; + min-height: 48px; } -/* Styles for the active tab icon */ .cometchat-selector__tab-icon-active { - display: flex; - width: 32px; - height: 32px; - justify-content: center; - align-items: center; - -webkit-mask-size: contain; - mask-size: contain; - cursor: default; - background: var(--cometchat-icon-color-highlight); - -webkit-mask: url('./assets/chats.svg') no-repeat center; - mask: url('./assets/chats.svg') no-repeat center; + display: flex; + width: 32px; + height: 32px; + justify-content: center; + align-items: center; + -webkit-mask-size: contain; + mask-size: contain; + cursor: default; + background: var(--cometchat-icon-color-highlight); + -webkit-mask: url('./assets/chats.svg') no-repeat center; + mask: url('./assets/chats.svg') no-repeat center; } -/* Styles for the active tab text */ .cometchat-selector__tab-text-active { - text-align: center; - font: var(--cometchat-font-caption1-medium, 500 12px Roboto); - cursor: default; - color: var(--cometchat-text-color-highlight); + text-align: center; + font: var(--cometchat-font-caption1-medium, 500 12px Roboto); + cursor: default; + color: var(--cometchat-text-color-highlight); } ``` - -### **Step 2: Update App** +Key points about the sidebar: +- `CometChatUIKitLoginListener.getLoggedInUser()` checks for an active session — the component only renders if a user is logged in. +- `activeConversation` highlights the currently selected conversation in the list. +- `onItemClick` fires when a user taps a conversation, passing the `Conversation` object to the parent. + +--- + +## Step 2 — Update App.tsx and App.css -Now we will update the `App.tsx` & `App.css` files to import these new components as below, +Wire the sidebar and message components together in your main app file. -```tsx App.tsx +```tsx title="App.tsx" lines import { useState } from "react"; import { CometChatMessageComposer, @@ -253,102 +241,100 @@ import { import { CometChat } from "@cometchat/chat-sdk-javascript"; import { CometChatSelector } from "./CometChatSelector/CometChatSelector"; import "./App.css"; -import '@cometchat/chat-uikit-react/css-variables.css'; +import "@cometchat/chat-uikit-react/css-variables.css"; function App() { - // State to track the currently selected user - const [selectedUser, setSelectedUser] = useState(undefined); - - // State to track the currently selected group - const [selectedGroup, setSelectedGroup] = useState(undefined); + const [selectedUser, setSelectedUser] = useState< + CometChat.User | undefined + >(undefined); + const [selectedGroup, setSelectedGroup] = useState< + CometChat.Group | undefined + >(undefined); return (
- {/* Sidebar for selecting conversations */} + {/* Sidebar — conversation list */}
{ let item = activeItem; - // If the selected item is a conversation, extract the user/group from it + // Extract user/group from Conversation object if (activeItem instanceof CometChat.Conversation) { item = activeItem.getConversationWith(); } - // Determine if the selected item is a User or a Group and update the state accordingly if (item instanceof CometChat.User) { setSelectedUser(item as CometChat.User); - setSelectedGroup(undefined); // Ensure no group is selected + setSelectedGroup(undefined); } else if (item instanceof CometChat.Group) { - setSelectedUser(undefined); // Ensure no user is selected + setSelectedUser(undefined); setSelectedGroup(item as CometChat.Group); } else { setSelectedUser(undefined); - setSelectedGroup(undefined); // Reset if selection is invalid + setSelectedGroup(undefined); } }} />
- {/* If a user or group is selected, display the chat interface */} + {/* Message view — header + messages + composer */} {selectedUser || selectedGroup ? (
- {/* Header displaying user/group details */} - - {/* List of messages for the selected user/group */} - - {/* Message input composer */} - +
) : ( - // Default message when no conversation is selected -
Select Conversation to start
+
+ Select a conversation to start chatting +
)}
); -}; +} export default App; ```
- -```css App.css -/* Root container settings */ +```css title="App.css" lines +@import url("@cometchat/chat-uikit-react/css-variables.css"); + #root { text-align: center; - width: 100vw; /* Full viewport width */ - height: 100vh; /* Full viewport height */ - background-color: #282c34; /* Dark background */ + width: 100vw; + height: 100vh; + background-color: #282c34; } -/* Layout container for conversations and messages */ +/* Two-panel layout */ .conversations-with-messages { display: flex; height: 100%; width: 100%; - flex-direction: row; /* Horizontal layout */ + flex-direction: row; } -/* Sidebar container for the conversation list */ +/* Left panel — conversation list */ .conversations-wrapper { height: 100vh; - width: 480px; /* Fixed width for the sidebar */ + width: 480px; overflow: hidden; display: flex; flex-direction: column; } -/* Prevent scrolling inside the conversation list */ .conversations-wrapper > .cometchat { overflow: hidden; } -/* Main chat messages container */ +/* Right panel — messages */ .messages-wrapper { width: 100%; height: 100%; @@ -356,40 +342,65 @@ export default App; flex-direction: column; } -/* Styles for the placeholder when no conversation is selected */ +/* Empty state */ .empty-conversation { height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; - background: var(--cometchat-background-color-03, #F5F5F5); /* Light gray background */ - color: var(--cometchat-text-color-secondary, #727272); /* Secondary text color */ + background: var(--cometchat-background-color-03, #F5F5F5); + color: var(--cometchat-text-color-secondary, #727272); font: var(--cometchat-font-body-regular, 400 14px Roboto); } -/* Remove border-radius for the message composer input */ .cometchat .cometchat-message-composer { border-radius: 0px; } ``` -
-### **Step 3: Run the project** +How it works: +- When a conversation is tapped, `onSelectorItemClicked` extracts the `User` or `Group` from the `Conversation` object. +- `selectedUser` / `selectedGroup` state drives which chat is displayed — pass either `user` or `group` to the message components, never both. +- The empty state shows until a conversation is selected. -```powershell -npm start -``` +--- -*** +## Step 3 — Run the Project -## **Next Steps** + + +```bash lines +npm run dev +``` + + +```bash lines +npm start +``` + + -### **Enhance the User Experience** +You should see the conversation list on the left. Tap any conversation to load messages on the right. -* **[Advanced Customizations](/ui-kit/react/theme)** – Personalize the chat UI to align with your brand. +--- -*** +## Next Steps + + + + Customize colors, fonts, and styles to match your brand + + + Browse all prebuilt UI components + + + Back to the main setup guide + + + Chat features included out of the box + + diff --git a/ui-kit/react/react-js-integration.mdx b/ui-kit/react/react-js-integration.mdx index 55d433935..91da28f67 100644 --- a/ui-kit/react/react-js-integration.mdx +++ b/ui-kit/react/react-js-integration.mdx @@ -1,178 +1,110 @@ --- -title: "Getting Started With CometChat React UI Kit" +title: "React.js Integration" sidebarTitle: "Integration" +description: "Add CometChat to a React.js app in 5 steps: create project, install, init, login, render." --- -The **CometChat UI Kit for React** streamlines the integration of in-app chat functionality by providing a **comprehensive set of prebuilt UI components**. It offers seamless **theming options**, including **light and dark modes**, customizable fonts, colors, and extensive styling capabilities. + -With built-in support for **one-to-one and group conversations**, developers can efficiently enable chat features within their applications. Follow this guide to **quickly integrate chat functionality** using the CometChat React UI Kit. +| Field | Value | +| --- | --- | +| Package | `@cometchat/chat-uikit-react` | +| Peer deps | `react` >=18, `react-dom` >=18, `rxjs` ^7.8.1 | +| Init | `CometChatUIKit.init(UIKitSettings)` — must resolve before `login()` | +| Login | `CometChatUIKit.login("UID")` — must resolve before rendering components | +| Order | `init()` → `login()` → render. Breaking this order = blank screen | +| Auth Key | Dev/testing only. Use Auth Token in production | +| CSS | `@import url("@cometchat/chat-uikit-react/css-variables.css");` in global CSS | +| Calling | Optional. Install `@cometchat/calls-sdk-javascript` to enable | +| Other frameworks | [Next.js](/ui-kit/react/next-js-integration) · [React Router](/ui-kit/react/react-router-integration) · [Astro](/ui-kit/react/astro-integration) | -{/* - - */} + + +This guide walks you through adding CometChat to a React.js app. By the end you'll have a working chat UI. -*** - -## **Prerequisites** - -Before installing the **CometChat UI Kit for React**, you must first **create a CometChat application** via the **[CometChat Dashboard](https://app.cometchat.com/)**. The dashboard provides all the essential chat service components, including: - -* **User Management** -* **Group Chat & Messaging** -* **Voice & Video Calling** -* **Real-time Notifications** - -> To initialize the **UI Kit**, you will need the following credentials from your **CometChat application**: -> -> 1. **App ID** -> 2. **Auth Key** -> 3. **Region** -> -> Ensure you have these details ready before proceeding with the installation and configuration. - -*** - -## **Register & Set Up CometChat** - -Follow these steps to **register on CometChat** and **set up your development environment**. - -### **Step 1: Register on CometChat** - -To use **CometChat UI Kit**, you first need to register on the **CometChat Dashboard**. - -🔗 **[Click here to Sign Up](https://app.cometchat.com/login)** - -### **Step 2: Get Your Application Keys** - -After registering, create a **new app** and retrieve your **authentication details**: - -1. Navigate to **Application**, then select the **Credentials** section. - -2. Note down the following keys: - - * **App ID** - * **Auth Key** - * **Region** - - - -Each CometChat application can be integrated with a **single client app**. Users within the same application can communicate across multiple platforms, including **web and mobile**. - - - -### **Step 3: Set Up Your Development Environment** - -Ensure your system meets the following **prerequisites** before proceeding with integration. - -**System Requirements:** - -* **Node.js** installed on your machine. -* A code editor like **[Visual Studio Code](https://code.visualstudio.com/)** or **[Cursor](https://www.cursor.com/)**. -* **npm** or **Yarn** package manager installed. - -*** +--- -## **Built With** +## Prerequisites -The CometChat UI Kit for React relies on the following technologies: +You need three things from the [CometChat Dashboard](https://app.cometchat.com/): -| Technology | Description | -| ---------------------------------------------------- | ------------------------------------- | -| [Node.js](https://nodejs.org/) | JavaScript runtime environment | -| [npm](https://www.npmjs.com/get-npm) | Node Package Manager | -| [React](https://www.npmjs.com/package/react) | JavaScript library for UI development | -| [React DOM](https://www.npmjs.com/package/react-dom) | React package for rendering UI | +| Credential | Where to find it | +| --- | --- | +| App ID | Dashboard → Your App → Credentials | +| Auth Key | Dashboard → Your App → Credentials | +| Region | Dashboard → Your App → Credentials (e.g. `us`, `eu`, `in`) | -*** +You also need Node.js (v16+) and npm/yarn installed. -## **Getting Started** + +Auth Key is for development only. In production, generate Auth Tokens server-side via the [REST API](https://api-explorer.cometchat.com/) and use [`loginWithAuthToken()`](/ui-kit/react/methods#login-using-auth-token). Never ship Auth Keys in client code. + -### **Step 1: Create a React Project** +--- -1. **Open your code editor** (e.g., **VS Code**, **Cursor**). -2. **Initialize a new React project** using one of the following methods: +## Step 1 — Create a React Project - -**Using Vite (Recommended)** - -``` -npm create vite@latest my-app --template react-ts + +```bash lines +npm create vite@latest my-app -- --template react-ts cd my-app ``` - - - -**Using Create React App** - -``` + +```bash lines npx create-react-app my-app --template typescript cd my-app ``` - - -3. **Open the project directory in your code editor**. -4. **Start developing your React components inside the src directory**. -5. **Install additional dependencies as needed**. - -*** - -### **Step 2: Install Dependencies** - -The **CometChat UI Kit for React** is an **extension** of the **CometChat JavaScript SDK**.\ -Installing it will **automatically** include the core **Chat SDK**, enabling **seamless integration**. +--- -* To install the **CometChat UI Kit** +## Step 2 — Install the UI Kit -``` +```bash lines npm install @cometchat/chat-uikit-react ``` - - -``` +```bash lines yarn add @cometchat/chat-uikit-react ``` - - -*** +This installs the UI Kit and its dependency `@cometchat/chat-sdk-javascript` automatically. -### **Step 3: Initialize CometChat UI Kit** +If you want voice/video calling, also install: -Before using any features of the **CometChat UI Kit** or **CometChat SDK**, you must **initialize** the required settings. This is done using the [`Init`](/ui-kit/react/methods#init) method. - -* Initialization Process - -Call the `Init` method at the **beginning of your application** to ensure all CometChat functionalities are properly configured. - -*** +```bash lines +npm install @cometchat/calls-sdk-javascript +``` - -**Auth Key Usage** +--- -The **Auth Key** is an **optional property** of the `UIKitSettings` class. It is primarily recommended for **proof-of-concept (POC) development** or **early-stage application development**. +## Step 3 — Initialize CometChat -For secure authentication, use the [`Auth Token`](/ui-kit/react/methods#login-using-auth-token) method instead. +Create a constants file and initialize the UI Kit before anything else. - +```ts title="src/AppConstants.ts" lines +export const COMETCHAT_CONSTANTS = { + APP_ID: "APP_ID", // Replace with your App ID + REGION: "REGION", // Replace with your Region + AUTH_KEY: "AUTH_KEY", // Replace with your Auth Key (dev only) +}; +``` -```ts +```ts lines highlight={7-9} import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; /** @@ -184,35 +116,24 @@ const COMETCHAT_CONSTANTS = { AUTH_KEY: "AUTH_KEY", // Replace with your Auth Key (leave blank if using Auth Token) }; -/** - * Configure the CometChat UI Kit using the UIKitSettingsBuilder. - * This setup determines how the chat UI behaves. - */ const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) // Assign the App ID - .setRegion(COMETCHAT_CONSTANTS.REGION) // Assign the App's Region - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) // Assign the Authentication Key (if applicable) - .subscribePresenceForAllUsers() // Enable real-time presence updates for all users - .build(); // Build the final configuration + .setAppId(COMETCHAT_CONSTANTS.APP_ID) + .setRegion(COMETCHAT_CONSTANTS.REGION) + .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) + .subscribePresenceForAllUsers() + .build(); -/** - * Initialize the CometChat UI Kit with the configured settings. - * Once initialized successfully, you can proceed with user authentication and chat features. - */ -CometChatUIKit.init(UIKitSettings)! +CometChatUIKit.init(UIKitSettings) .then(() => { console.log("CometChat UI Kit initialized successfully."); - // You can now call login function to authenticate users }) .catch((error) => { - console.error("CometChat UI Kit initialization failed:", error); // Log errors if initialization fails + console.error("CometChat UI Kit initialization failed:", error); }); ``` - - -```js +```js lines highlight={7-9} import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; /** @@ -224,92 +145,49 @@ const COMETCHAT_CONSTANTS = { AUTH_KEY: "AUTH_KEY", // Replace with your Auth Key (leave blank if using Auth Token) }; -/** - * Configure the CometChat UI Kit using the UIKitSettingsBuilder. - * This setup determines how the chat UI behaves. - */ const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) // Assign the App ID - .setRegion(COMETCHAT_CONSTANTS.REGION) // Assign the App's Region - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) // Assign the Authentication Key (if applicable) - .subscribePresenceForAllUsers() // Enable real-time presence updates for all users - .build(); // Build the final configuration + .setAppId(COMETCHAT_CONSTANTS.APP_ID) + .setRegion(COMETCHAT_CONSTANTS.REGION) + .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) + .subscribePresenceForAllUsers() + .build(); -/** - * Initialize the CometChat UI Kit with the configured settings. - * Once initialized successfully, you can proceed with user authentication and chat features. - */ CometChatUIKit.init(UIKitSettings) .then(() => { console.log("CometChat UI Kit initialized successfully."); - // You can now call login function to authenticate users }) .catch((error) => { - console.error("CometChat UI Kit initialization failed:", error); // Log errors if initialization fails + console.error("CometChat UI Kit initialization failed:", error); }); ``` - - - - -Ensure you replace the following placeholders with your actual CometChat credentials: - -* APP\_ID → Your CometChat App ID -* AUTH\_KEY → Your CometChat Auth Key -* REGION → Your App Region - -These values are required for proper authentication and seamless integration. - - + +`init()` must resolve before you call `login()`. If you call `login()` before init completes, it will fail silently. + - -You can choose between different storage methods to store data. By default, we use local storage. To learn more about available storage options and how to configure them, [click here](/ui-kit/react/methods#setting-session-storage-mode). - +By default, session data is stored in `localStorage`. To use `sessionStorage` instead, see [Setting Session Storage Mode](/ui-kit/react/methods#setting-session-storage-mode). -*** - -### **Step 4: User Login** - -To authenticate a user, you need a **`UID`**. You can either: - -1. **Create new users** on the **[CometChat Dashboard](https://app.cometchat.com)**, **[CometChat SDK Method](/ui-kit/react/methods#create-user)** or **[via the API](https://api-explorer.cometchat.com/reference/creates-user)**. - -2. **Use pre-generated test users**: - - * `cometchat-uid-1` - * `cometchat-uid-2` - * `cometchat-uid-3` - * `cometchat-uid-4` - * `cometchat-uid-5` - -The **Login** method returns a **User object** containing all relevant details of the logged-in user. - -*** - - +--- -**Security Best Practices** +## Step 4 — Login -* The **Auth Key** method is recommended for **proof-of-concept (POC) development** and early-stage testing. -* For **production environments**, it is strongly advised to use an **[Auth Token](/ui-kit/react/methods#login-using-auth-token)** instead of an **Auth Key** to enhance security and prevent unauthorized access. +After init resolves, log the user in. For development, use one of the pre-created test UIDs: - +`cometchat-uid-1` · `cometchat-uid-2` · `cometchat-uid-3` · `cometchat-uid-4` · `cometchat-uid-5` -```ts +```ts lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; const UID = "UID"; // Replace with your actual UID CometChatUIKit.getLoggedinUser().then((user: CometChat.User | null) => { if (!user) { - // If no user is logged in, proceed with login CometChatUIKit.login(UID) .then((user: CometChat.User) => { console.log("Login Successful:", { user }); @@ -317,22 +195,19 @@ CometChatUIKit.getLoggedinUser().then((user: CometChat.User | null) => { }) .catch(console.log); } else { - // If user is already logged in, mount your app + // Already logged in — mount your app } }); ``` - - -```js +```js lines highlight={3} import { CometChatUIKit } from "@cometchat/chat-uikit-react"; const UID = "UID"; // Replace with your actual UID CometChatUIKit.getLoggedinUser().then((user) => { if (!user) { - // If no user is logged in, proceed with login CometChatUIKit.login(UID) .then((user) => { console.log("Login Successful:", { user }); @@ -340,164 +215,152 @@ CometChatUIKit.getLoggedinUser().then((user) => { }) .catch(console.log); } else { - // If user is already logged in, mount your app + // Already logged in — mount your app } }); ``` - - -*** +Key points: +- `getLoggedinUser()` checks for an existing session so you don't re-login unnecessarily. +- `login(uid)` skips the API call if a session already exists and returns the cached user. +- Components must not render until login resolves — use a state flag to gate rendering. -### **Step 5: Choose a Chat Experience** + +For production, use [`loginWithAuthToken()`](/ui-kit/react/methods#login-using-auth-token) instead of Auth Key. Generate tokens server-side via the REST API. + + +--- -Integrate a conversation view that suits your application's **UX requirements**. Below are the available options: +## Step 5 — Add the CSS Import -*** +Add this line at the top of your global CSS file (e.g. `src/App.css` or `src/index.css`): -#### **1️⃣ Conversation List + Message View** +```css title="src/App.css" lines +@import url("@cometchat/chat-uikit-react/css-variables.css"); +``` + +Without this import, components will render with broken or missing styles. + +--- -**Best for:** Applications that need a **two-panel layout**, such as web-based chat interfaces (e.g., WhatsApp Web, Slack). +## Step 6 — Choose a Chat Experience -**Features:** +Integrate a conversation view that suits your app's UX. Each option below includes a live CodeSandbox demo and a step-by-step guide. -* **Two-panel layout** – Displays the conversation list on the left and the active chat window on the right. -* **One-to-one & group conversations** – Seamless switching between private and group chats. -* **Multiple conversations** – Effortlessly switch between different chat windows. -* **Easy navigation** – Intuitive UI for finding and accessing chats quickly. -* **Tap-to-view on mobile** – In mobile layouts, tapping a conversation opens the **Message View**, optimizing space. -* **Real-time updates** – Auto-refreshes messages and conversation lists. -* **Message sync** – Ensures messages stay updated across all sessions and devices. +### Conversation List + Message View + +Two-panel layout — conversation list on the left, messages on the right. Think WhatsApp Web or Slack. + +- Two-panel layout with conversation list and active chat window +- Switch between one-to-one and group conversations +- Tap-to-view on mobile — tapping a conversation opens the message view +- Real-time updates and message sync across sessions -**Recommended for:** - -* Desktop-first applications -* Apps requiring a **rich user experience** with seamless navigation -* Platforms supporting both **individual and group messaging** -* **Mobile-friendly** apps needing a **tap-to-open message view** - [](https://link.cometchat.com/react-conversation-list-message) -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. +> **Tip:** Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -[Integrate Conversation List + Message](./react-conversation) + + Step-by-step guide to build this layout + -*** - -#### **2️⃣ One-to-One/Group Chat** +--- -**Best for:** Apps that require a **focused, direct messaging experience** without a sidebar. +### One-to-One / Group Chat -**Features:** +Single chat window — no sidebar. Good for support chat, embedded widgets, or focused messaging. -* **Dedicated chat window** – Ideal for one-on-one or group messaging. -* **No conversation list** – Users directly enter the chat without navigating through a list. -* **Supports both One-to-One and Group Chats** – Easily configurable with minor code modifications. -* **Optimized for mobile** – Full-screen chat experience without distractions. -* **Seamless real-time communication** – Auto-updates messages for a smooth experience. -* **Ideal for support chat or community-based messaging.** +- Dedicated chat window for one-on-one or group messaging +- No conversation list — users go directly into the chat +- Full-screen experience optimized for mobile +- Ideal for support chat or community messaging -**Recommended for:** - -* **Support chat applications** – Direct user-agent communication. -* **Apps focusing on direct messaging** – No distractions from other conversations. -* **Community or group chat applications** – A structured way to interact in groups. -* **Mobile-first applications** – Designed for compact and dedicated messaging experiences. - [](https://link.cometchat.com/react-one-on-one) -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. - -[Integrate One-to-One/Group Chat](./react-one-to-one-chat) +> **Tip:** Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -*** + + Step-by-step guide to build this layout + -#### **3️⃣ Tab-Based Chat Experience** +--- -**Best for:** Apps that need a **structured, multi-feature navigation system** for seamless interaction between **chats, calls, users, and settings**. +### Tab-Based Chat -**Features:** +Tabbed navigation — Chat, Call Logs, Users, Settings in separate tabs. Good for full-featured apps. -* **Tab Navigation** – Easily switch between **Chat, Call Logs, Users, and Settings**. -* **Dedicated Chat Window** – Full-screen messaging experience for focused communication. -* **No Sidebar** – Unlike multi-panel UI, this design prioritizes individual interactions. -* **Unified Experience** – Users can seamlessly manage conversations, call history, and settings from a single interface. -* **Scalable for future features** – Easily extend to include more functionalities such as notifications or contact management. -* **Optimized for both desktop and mobile** – Ensures a smooth experience across different screen sizes. +- Tab navigation between Chat, Call Logs, Users, and Settings +- Full-screen messaging within each tab +- Unified experience for conversations, call history, and settings +- Scales well for adding future features like notifications or contacts -**Recommended for:** - -* **Apps requiring structured navigation** – Clearly separate chat, calls, and settings. -* **Multi-feature chat apps** – Supporting different functionalities in an organized way. -* **Mobile-first applications** – Ideal for apps needing tab-based UI for easy access to features. -* **Support & enterprise chat solutions** – Perfect for help desks, business chat platforms, and customer support apps. - [](https://link.cometchat.com/react-tabs-sidebar-message) -> **Tip:** You can **fork** the sandbox, insert your **CometChat credentials** (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time. - -[Integrate Tab-Based Chat](./react-tab-based-chat) - -*** +> **Tip:** Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time. -## **Build Your Own Chat Experience** + + Step-by-step guide to build this layout + -**Best for:** Developers who need complete control over their chat interface, allowing customization of components, themes, and features to align with their app’s design and functionality. Whether you're enhancing an existing chat experience or building from scratch, this approach provides the flexibility to tailor every aspect to your needs. - -**Recommended for:** +--- -* Apps that require **a fully customized chat experience**. -* Developers who want to **extend functionalities and modify UI components**. -* Businesses integrating chat seamlessly into **existing platforms**. +## Build Your Own Chat Experience -**Key Areas to Explore:** +Need full control over the UI? Use individual components, customize themes, and wire up your own layouts. -* **[React Sample App](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app)** – Fully functional sample applications to accelerate your development. -* **[Core Features](./core-features)** – Learn about messaging, real-time updates, and other essential capabilities. -* **[Components](./components-overview)** – Utilize prebuilt UI elements or customize them to fit your design. -* **[Themes](./theme)** – Adjust colors, fonts, and styles to match your branding. -* **[Build Your Own UI](./../../../sdk/javascript/overview)** – Prefer a custom UI over our UI Kits? Explore our SDKs to create a tailored chat experience. +- [Sample App](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app) — Working reference app to compare against +- [Components](/ui-kit/react/components-overview) — All prebuilt UI elements with props and customization options +- [Core Features](/ui-kit/react/core-features) — Messaging, real-time updates, and other capabilities +- [Theming](/ui-kit/react/theme) — Colors, fonts, dark mode, and custom styling +- [Build Your Own UI](/sdk/javascript/overview) — Skip the UI Kit entirely and build on the raw SDK -*** +--- -## iFrame Support +## iFrame Embedding -If you’re embedding your React app inside an `