diff --git a/docs.json b/docs.json
index 035cebab9..deb145882 100644
--- a/docs.json
+++ b/docs.json
@@ -1186,6 +1186,7 @@
"ui-kit/react-native/threaded-messages-header",
"ui-kit/react-native/incoming-call",
"ui-kit/react-native/outgoing-call",
+ "ui-kit/react-native/ongoing-call",
"ui-kit/react-native/call-buttons",
"ui-kit/react-native/call-logs",
"ui-kit/react-native/ai-assistant-chat-history",
@@ -1211,6 +1212,7 @@
"ui-kit/react-native/guide-search-messages",
"ui-kit/react-native/guide-message-privately",
"ui-kit/react-native/guide-block-unblock-user",
+ "ui-kit/react-native/custom-message-types",
"ui-kit/react-native/custom-text-formatter-guide",
"ui-kit/react-native/mentions-formatter-guide",
"ui-kit/react-native/url-formatter-guide",
diff --git a/sdk/react-native/campaigns.mdx b/sdk/react-native/campaigns.mdx
index d31eb9bca..083256278 100644
--- a/sdk/react-native/campaigns.mdx
+++ b/sdk/react-native/campaigns.mdx
@@ -3,6 +3,23 @@ title: "Campaigns"
description: "Fetch notification feed items, listen for real-time delivery, mark items as read/delivered, report engagement, and track push notifications using the CometChat React Native SDK."
---
+{/* TL;DR for Agents and Quick Reference */}
+
+
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `addNotificationFeedListener()`, `getNotificationFeedItem()`, `getNotificationFeedUnreadCount()`, `markFeedItemAsRead()`, `markFeedItemAsDelivered()`, `markPushNotificationDelivered()`, `markPushNotificationClicked()`, `reportFeedEngagement()` |
+| Key Classes | `NotificationFeedItem`, `NotificationFeedRequest`, `NotificationFeedRequestBuilder`, `NotificationCategoriesRequestBuilder`, `NotificationFeedListener`, `PushNotification` |
+| Prerequisites | SDK initialized via [`CometChat.init()`](/sdk/react-native/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/react-native/authentication-overview) · channels, categories, templates and campaigns configured in the [dashboard](/campaigns#setup-flow) |
+| Primary output | `NotificationFeedRequest.fetchNext()` → `Promise`; `getNotificationFeedItem()` → `Promise`; `getNotificationFeedUnreadCount()` → `Promise<{ count: number }>`; the mark and report methods → `Promise` |
+| Constraints | Card messages are receive-only: they are created through the Platform API and the dashboard, never from the SDK. The cards library only renders a card — your own code decides what its actions do. Feed items carry Card Schema JSON, so render them with the cards library rather than reading the payload by hand. |
+| Related | [Notification Feed component](/ui-kit/react-native/notification-feed) · [Dashboard setup](/campaigns#setup-flow) · [Card Builder](/card-builder/overview) · [Real-time Listeners](/sdk/react-native/real-time-listeners#message-listener) |
+| Full reference | [NotificationFeedItem fields](#notificationfeeditem-fields) · [NotificationCategory fields](#notificationcategory-fields) |
+
+
+
CometChat Campaigns lets you deliver targeted, rich notifications to users via an in-app notification feed. Each notification is a **Card Schema JSON** — a structured layout rendered natively by the CometChat Cards library.
The SDK provides APIs to fetch feed items, listen for real-time delivery, mark items as read/delivered, report engagement, and retrieve unread counts.
diff --git a/sdk/react-native/overview.mdx b/sdk/react-native/overview.mdx
index bb6e25856..832738b43 100644
--- a/sdk/react-native/overview.mdx
+++ b/sdk/react-native/overview.mdx
@@ -7,6 +7,18 @@ description: "Add real-time chat, voice, video, users, groups, messages, and pus
{/* TL;DR for Agents and Quick Reference */}
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `init()`, `login()`, `getLoggedinUser()` |
+| Key Classes | `AppSettings`, `AppSettingsBuilder`, `User`, `CometChatException` |
+| Prerequisites | An App ID, Region and Auth Key from the [CometChat Dashboard](https://app.cometchat.com) · React Native 0.63+, Android `minSdkVersion` 24, iOS 11.0 |
+| Primary output | `init()` → `Promise`; `login()` → `Promise`; `getLoggedinUser()` → `Promise` |
+| Constraints | Call `init()` once, before any other SDK call, and log a user in before sending or fetching anything. `getLoggedinUser()` resolves to `null` when nobody is logged in. Use the Auth Key for development only; log users in with an Auth Token in production. |
+| Related | [Setup SDK](/sdk/react-native/setup-sdk) · [Authentication](/sdk/react-native/authentication-overview) · [Key Concepts](/sdk/react-native/key-concepts) · [Send a Message](/sdk/react-native/send-message) |
+| Full reference | [`User`](/sdk/reference/entities#user) · [`CometChatException`](/sdk/reference/auxiliary#cometchatexception) |
+
```bash
npm install @cometchat/chat-sdk-react-native
```
diff --git a/sdk/react-native/pin-conversation.mdx b/sdk/react-native/pin-conversation.mdx
index a27cffc80..bff2b6d03 100644
--- a/sdk/react-native/pin-conversation.mdx
+++ b/sdk/react-native/pin-conversation.mdx
@@ -7,6 +7,18 @@ description: "Pin and unpin conversations and fetch the pinned conversation list
{/* TL;DR for Agents and Quick Reference */}
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `pinConversation()`, `unpinConversation()`, `isPinConversationEnabled()`, `getPinConversationLimit()`, `getSystemPinConversationLimit()` |
+| Key Classes | `Conversation`, `ConversationsRequest`, `ConversationsRequestBuilder`, `CometChatException` |
+| Prerequisites | SDK initialized via [`CometChat.init()`](/sdk/react-native/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/react-native/authentication-overview) |
+| Primary output | `pinConversation()` and `unpinConversation()` → `Promise`; `isPinConversationEnabled()` → `Promise`; `getPinConversationLimit()` and `getSystemPinConversationLimit()` → `Promise` |
+| Constraints | Pin by the peer's UID or GUID plus the receiver type, not by conversation ID. The feature needs the `features.ux.conversations.pinned.enabled` flag, which no plan seeds — it must be mapped per app. A conversation that has never been messaged, or that is hidden, rejects with `ERR_CONVERSATION_NOT_ACCESSIBLE`. `setPinnedBy()` takes exact, case-sensitive strings and silently drops anything else. This SDK has no `ConversationListener`, so keep the list in sync yourself. |
+| Related | [Retrieve Conversations](/sdk/react-native/retrieve-conversations) · [Pin a Message](/sdk/react-native/pin-message) · [Save a Message](/sdk/react-native/save-message) · [Delete a Conversation](/sdk/react-native/delete-conversation) |
+| Full reference | [`Conversation`](/sdk/reference/entities#conversation) · [`CometChatException`](/sdk/reference/auxiliary#cometchatexception) |
+
```javascript
// Pin / unpin — addressed by peer + type, not by conversationId
await CometChat.pinConversation("UID", CometChat.RECEIVER_TYPE.USER);
diff --git a/sdk/react-native/pin-message.mdx b/sdk/react-native/pin-message.mdx
index a5b713509..fd864b524 100644
--- a/sdk/react-native/pin-message.mdx
+++ b/sdk/react-native/pin-message.mdx
@@ -7,6 +7,18 @@ description: "Pin and unpin messages in a conversation, fetch the pinned list, a
{/* TL;DR for Agents and Quick Reference */}
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `pinMessage()`, `unpinMessage()`, `isPinMessageEnabled()`, `getPinMessageLimit()`, `addMessageListener()`, `removeMessageListener()` |
+| Key Classes | `BaseMessage`, `MessagesRequest`, `MessagesRequestBuilder`, `MessageListener`, `CometChatException` |
+| Prerequisites | SDK initialized via [`CometChat.init()`](/sdk/react-native/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/react-native/authentication-overview) |
+| Primary output | `pinMessage()` and `unpinMessage()` → `Promise`; `isPinMessageEnabled()` → `Promise`; `getPinMessageLimit()` → `Promise` |
+| Constraints | Pinning is a moderation action: only an admin, moderator or group owner may pin or unpin, and the server is the authority. A just-sent message may not be pinnable yet while moderation is pending. On a cap breach the rejection carries the server-owned ceiling in `errorParams.limit`. There is no `isPinned()` or `isSystemPinned()` in this SDK — read `getPinnedAt()`. Fetch the pinned list with `setPinnedOnly(true)`, scoped to one conversation. |
+| Related | [Save a Message](/sdk/react-native/save-message) · [Pin a Conversation](/sdk/react-native/pin-conversation) · [Real-time Listeners](/sdk/react-native/real-time-listeners) · [Message Filtering](/sdk/react-native/additional-message-filtering) |
+| Full reference | [`BaseMessage`](/sdk/reference/messages#basemessage) · [`CometChatException`](/sdk/reference/auxiliary#cometchatexception) |
+
```javascript
// Pin / unpin a message
const pinned = await CometChat.pinMessage(messageId);
diff --git a/sdk/react-native/save-message.mdx b/sdk/react-native/save-message.mdx
index 558dfe91b..a42e7ef85 100644
--- a/sdk/react-native/save-message.mdx
+++ b/sdk/react-native/save-message.mdx
@@ -7,6 +7,18 @@ description: "Save and unsave messages privately, fetch the saved list across co
{/* TL;DR for Agents and Quick Reference */}
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `saveMessage()`, `unsaveMessage()`, `isSaveMessageEnabled()`, `getSaveMessageLimit()`, `addMessageListener()` |
+| Key Classes | `BaseMessage`, `MessagesRequest`, `MessagesRequestBuilder`, `MessageListener`, `CometChatException` |
+| Prerequisites | SDK initialized via [`CometChat.init()`](/sdk/react-native/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/react-native/authentication-overview) |
+| Primary output | `saveMessage()` and `unsaveMessage()` → `Promise`; `isSaveMessageEnabled()` → `Promise`; `getSaveMessageLimit()` → `Promise` |
+| Constraints | Saves are private and per-viewer: `savedAt` is only ever set in the acting user's own context. They are account-wide, so do not combine `setSavedOnly(true)` with `setUID()` or `setGUID()`. There is no `isSaved()` in this SDK — read `getSavedAt()`. The real-time callbacks fire for saves made on your other devices, not on the one that performed the save. |
+| Related | [Pin a Message](/sdk/react-native/pin-message) · [Pin a Conversation](/sdk/react-native/pin-conversation) · [Retrieve Conversations](/sdk/react-native/retrieve-conversations) · [Message Filtering](/sdk/react-native/additional-message-filtering) |
+| Full reference | [`BaseMessage`](/sdk/reference/messages#basemessage) · [`CometChatException`](/sdk/reference/auxiliary#cometchatexception) |
+
```javascript
// Save / unsave a message
const saved = await CometChat.saveMessage(messageId);
diff --git a/sdk/react-native/thread-subscription.mdx b/sdk/react-native/thread-subscription.mdx
index f63f1ced7..9955fb84b 100644
--- a/sdk/react-native/thread-subscription.mdx
+++ b/sdk/react-native/thread-subscription.mdx
@@ -7,6 +7,18 @@ description: "Subscribe and unsubscribe from message threads, read subscription
{/* TL;DR for Agents and Quick Reference */}
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `subscribeToThread()`, `unsubscribeFromThread()`, `getMessageDetails()`, `addMessageListener()` |
+| Key Classes | `BaseMessage`, `MessageThread`, `ThreadsRequest`, `ThreadsRequestBuilder`, `MessageListener` |
+| Prerequisites | SDK initialized via [`CometChat.init()`](/sdk/react-native/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/react-native/authentication-overview) |
+| Primary output | `subscribeToThread()` and `unsubscribeFromThread()` → `Promise`; `ThreadsRequest.fetchNext()` → `Promise` |
+| Constraints | A thread is identified by its parent message ID, passed as a number. Unsubscribing hard-deletes the server row, so a thread inbox must drop that row rather than mark it unfollowed. A message that arrives over the socket carries no subscription flag and reads `false`, which does not mean the user is unsubscribed. `setThreadSubscribed()` only changes the object in memory and sends nothing to the server. `ThreadsRequestBuilder` spells its scope setters `setUid()` and `setGuid()`, unlike `MessagesRequestBuilder`. |
+| Related | [Threaded Messages](/sdk/react-native/threaded-messages) · [Mentions](/sdk/react-native/mentions) · [Real-time Listeners](/sdk/react-native/real-time-listeners) · [Save a Message](/sdk/react-native/save-message) |
+| Full reference | [`BaseMessage`](/sdk/reference/messages#basemessage) · [thread row fields](#reading-a-thread-row) |
+
```javascript
// Subscribe / unsubscribe — a thread is identified by its PARENT message id
await CometChat.subscribeToThread(100);
diff --git a/sdk/react-native/upload-files.mdx b/sdk/react-native/upload-files.mdx
index 3ac362be5..002abe6b6 100644
--- a/sdk/react-native/upload-files.mdx
+++ b/sdk/react-native/upload-files.mdx
@@ -4,6 +4,23 @@ sidebarTitle: "Upload Files"
description: "Upload files directly to storage with per-file progress, remove, and retry through an UploadFileRequest — then send them as one or more media messages with multiple attachments."
---
+{/* TL;DR for Agents and Quick Reference */}
+
+
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-sdk-react-native` |
+| Import | `import { CometChat } from "@cometchat/chat-sdk-react-native";` |
+| Key Methods | `createUploadFileRequest()`, `getMaxAttachmentCount()`, `sendMediaMessage()` |
+| Key Classes | `UploadFileRequest`, `UploadFileListener`, `Attachment`, `MediaMessage` |
+| Prerequisites | SDK initialized via [`CometChat.init()`](/sdk/react-native/setup-sdk) and a logged-in user via [`CometChat.login()`](/sdk/react-native/authentication-overview) |
+| Primary output | `createUploadFileRequest()` → `UploadFileRequest`, returned synchronously; uploads report through `UploadFileListener`; `getAttachments()` → `Attachment[]`; `getMaxAttachmentCount()` → `Promise`; `sendMediaMessage()` → `Promise` |
+| Constraints | One request covers one destination and one batch, so create a separate request per conversation or thread. `receiverId` and `receiverType` must match the message you eventually send, because the upload-authorization endpoint enforces them. You supply `fileId` yourself; the SDK never generates one. `onFileError` means the request was rejected, which is not the same as an upload that failed midway. The attachment getters return uploaded files only. |
+| Related | [Send a Message](/sdk/react-native/send-message) · [Multiple attachments](/sdk/react-native/send-message#multiple-attachments-in-a-media-message) · [Receive Messages](/sdk/react-native/receive-messages) · [Edit a Message](/sdk/react-native/edit-message) |
+| Full reference | [`Attachment`](/sdk/reference/auxiliary#attachment) · [`MediaMessage`](/sdk/reference/messages#mediamessage) |
+
+
+
`CometChat.createUploadFileRequest(receiverId, receiverType)` returns an **`UploadFileRequest`** — the entry point for uploading files **directly to storage** with **per-file progress, success, and failure**. Upload is **decoupled from sending**: each uploaded file yields an [`Attachment`](/sdk/reference/auxiliary#attachment) (carrying a hosted `url`), which you then attach to a [`MediaMessage`](/sdk/reference/messages#mediamessage) and send with [`sendMediaMessage()`](/sdk/react-native/send-message#media-message).
A request object is scoped to **one destination** (`receiverId` / `receiverType`) and **one upload batch**. This is the recommended way to build a **multi-attachment composer**: create a request, upload a batch of files, show a progress bar per file, let the user remove or retry individual files, then send them as a single media message with multiple attachments (or split across several).
diff --git a/ui-kit/react-native/ai-features.mdx b/ui-kit/react-native/ai-features.mdx
index f033a6ee6..a00422e29 100644
--- a/ui-kit/react-native/ai-features.mdx
+++ b/ui-kit/react-native/ai-features.mdx
@@ -11,6 +11,7 @@ description: "Integrate AI-powered conversation starters, smart replies, and con
| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` + AI features enabled in [CometChat Dashboard](/fundamentals/ai-user-copilot/overview) |
| AI features | Conversation Starter, Smart Replies, Conversation Summary |
| Key components | `CometChatMessageList` (Conversation Starter, Smart Replies), `CometChatMessageHeader` + `CometChatConversationSummary` (Conversation Summary) |
+| Standalone components | `CometChatConversationStarter` · `CometChatSmartReplies` · `CometChatConversationSummary` — all exported from the kit root, for custom placement |
| Activation | Enable each AI feature from the CometChat Dashboard, then pass the corresponding prop(s) to the component — Conversation Summary also needs `onConversationSummaryPress` and your own `CometChatConversationSummary` |
@@ -40,6 +41,30 @@ Once you have successfully activated the [Conversation Starter](/fundamentals/ai
+### Rendering the component directly
+
+`CometChatMessageList` renders `CometChatConversationStarter` for you when `showConversationStarters` is set, so most apps never render it themselves. Render it directly when you need the chips somewhere the list does not put them — a custom empty state, or above your own composer.
+
+| Prop | Type | Required | Description |
+| --- | --- | --- | --- |
+| `getConversationStarters` | `() => Promise` | Yes | Returns the suggestions to render. |
+| `onSuggestionClicked` | `(reply: string) => void` | No | Fires with the chip's text when a suggestion is tapped. |
+
+The component has no `style` prop — it takes its colors from the active [theme](/ui-kit/react-native/theme).
+
+```tsx
+import { CometChat } from '@cometchat/chat-sdk-react-native';
+import { CometChatConversationStarter } from '@cometchat/chat-uikit-react-native';
+
+const fetchConversationStarters = () =>
+ CometChat.getConversationStarter(user.getUid(), CometChat.RECEIVER_TYPE.USER);
+
+ sendMessage(text)}
+/>
+```
+
## Smart Replies
Smart Replies are AI-generated responses to messages. They predict what a user might want to say next by analyzing the context of the conversation, allowing for quicker and more convenient responses on mobile devices.
@@ -59,6 +84,39 @@ Once you have successfully activated the [Smart Replies](/fundamentals/ai-user-c
+### Rendering the component directly
+
+As with the conversation starter, `CometChatMessageList` renders `CometChatSmartReplies` for you when `showSmartReplies` is set. Render it directly only for custom placement.
+
+| Prop | Type | Required | Description |
+| --- | --- | --- | --- |
+| `getSmartReplies` | `() => Promise` | Yes | Returns the replies to render. |
+| `onSuggestionClicked` | `(reply: string) => void` | No | Fires with the chip's text when a reply is tapped. |
+| `closeCallback` | `() => void` | No | Fires when the user dismisses the panel with its close button. |
+
+The component has no `style` prop — it takes its colors from the active [theme](/ui-kit/react-native/theme).
+
+
+**`CometChat.getSmartReplies()` does not resolve to an array.**
+
+Its SDK signature is `Promise
+
+```tsx
+import { CometChat } from '@cometchat/chat-sdk-react-native';
+import { CometChatSmartReplies } from '@cometchat/chat-uikit-react-native';
+
+const fetchSmartReplies = () =>
+ CometChat.getSmartReplies(user.getUid(), CometChat.RECEIVER_TYPE.USER)
+ .then((res) => Object.values(res) as string[]);
+
+ sendMessage(text)}
+ closeCallback={() => setShowReplies(false)}
+/>
+```
+
## Conversation Summary
The Conversation Summary feature provides concise summaries of long conversations, allowing users to catch up quickly on missed chats. This feature uses natural language processing to determine the main points in a conversation.
@@ -93,6 +151,13 @@ const fetchConversationSummary = () =>
Place `CometChatConversationSummary` between the message list and the composer so the panel appears above the composer.
+| Prop | Type | Required | Description |
+| --- | --- | --- | --- |
+| `getConversationSummary` | `() => Promise` | Yes | Returns the summary text to display. |
+| `closeCallback` | `() => void` | No | Fires when the user dismisses the panel with its close button. Use it to clear the state that renders the panel. |
+
+Like the other two AI components, it has no `style` prop and is themed through the active [theme](/ui-kit/react-native/theme).
+
diff --git a/ui-kit/react-native/call-buttons.mdx b/ui-kit/react-native/call-buttons.mdx
index 17bc81534..4dae0e982 100644
--- a/ui-kit/react-native/call-buttons.mdx
+++ b/ui-kit/react-native/call-buttons.mdx
@@ -165,28 +165,21 @@ function StylingDemo() {
You can customize the properties of the Outgoing Call component by making use of the `outgoingCallConfiguration` prop:
```tsx lines
-import {
- CometChatCallButtons,
- OutgoingCallConfiguration,
-} from "@cometchat/chat-uikit-react-native";
+import { CometChatCallButtons } from "@cometchat/chat-uikit-react-native";
function OutgoingCallConfigDemo() {
- const getOutgoingCallConfig = () => {
- return new OutgoingCallConfiguration({
- disableSoundForCalls: true,
- });
- };
-
return (
);
}
```
-All exposed properties of `OutgoingCallConfiguration` can be found under [Outgoing Call](/ui-kit/react-native/outgoing-call).
+All properties accepted by `outgoingCallConfiguration` can be found under [Outgoing Call](/ui-kit/react-native/outgoing-call).
---
diff --git a/ui-kit/react-native/compact-message-composer.mdx b/ui-kit/react-native/compact-message-composer.mdx
index b5d14c6a2..dbfca6e4f 100644
--- a/ui-kit/react-native/compact-message-composer.mdx
+++ b/ui-kit/react-native/compact-message-composer.mdx
@@ -233,18 +233,18 @@ On React Native, the `showTextSelectionMenuItems` prop controls whether Bold, It
The `enterKeyBehavior` prop controls what happens when the Enter key is pressed on Android. On iOS, Enter always inserts a new line.
```tsx lines
-import { CometChatCompactMessageComposer, EnterKeyBehavior } from "@cometchat/chat-uikit-react-native";
+import { CometChatCompactMessageComposer, CometChatUiKitConstants } from "@cometchat/chat-uikit-react-native";
// Send message on Enter (Android)
// New line on Enter (default)
```
@@ -647,7 +647,7 @@ Using the `style` prop you can customize the look and feel of the component in y
| `enableRichTextEditor` | Enable/disable rich text formatting | `enableRichTextEditor={true}` |
| `hideRichTextFormattingOptions` | Always-visible toolbar mode | `hideRichTextFormattingOptions={true}` |
| `showTextSelectionMenuItems` | Formatting in native text selection menu | `showTextSelectionMenuItems={true}` |
-| `enterKeyBehavior` | Android Enter key behavior | `enterKeyBehavior={EnterKeyBehavior.SendMessage}` |
+| `enterKeyBehavior` | Android Enter key behavior | `enterKeyBehavior={CometChatUiKitConstants.EnterKeyBehavior.SendMessage}` |
| `maxLines` | Maximum lines before scrolling | `maxLines={3}` |
| `minInputHeight` | Minimum input height in pixels | `minInputHeight={36}` |
| `maxInputHeight` | Maximum input height in pixels | `maxInputHeight={120}` |
@@ -655,24 +655,6 @@ Using the `style` prop you can customize the look and feel of the component in y
---
-## Configuration
-
-`SingleLineMessageComposerConfiguration` can be used to pass configuration when embedding the CompactMessageComposer inside other components:
-
-```tsx lines
-import { SingleLineMessageComposerConfiguration } from "@cometchat/chat-uikit-react-native";
-
-const config = new SingleLineMessageComposerConfiguration({
- disableTypingEvents: true,
- hideVoiceRecording: true,
- disableMentions: false,
- maxLines: 3,
- placeHolderText: "Write something...",
-});
-```
-
----
-
## Next Steps
diff --git a/ui-kit/react-native/component-styling.mdx b/ui-kit/react-native/component-styling.mdx
index 2865331f8..a3e13ebde 100644
--- a/ui-kit/react-native/component-styling.mdx
+++ b/ui-kit/react-native/component-styling.mdx
@@ -1374,7 +1374,7 @@ To learn more about such attributes, refer to the [theme interface](https://gith
### Receipts
-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.
+Message receipts indicate delivery and read statuses using intuitive icons. The theme's `receiptStyles` controls their icon size, tint, and alignment wherever a component renders receipts without its own style — for example the last-message receipt in `CometChatConversations`, shown below. Message bubbles in `CometChatMessageList` apply their own receipt styles, so this top-level override does not change them.
@@ -1382,7 +1382,7 @@ The `CometChatReceipts` component indicates message delivery and read statuses u
```javascript
import {
- CometChatReceipt,
+ CometChatConversations,
CometChatThemeProvider,
} from "@cometchat/chat-uikit-react-native";
import { SafeAreaView } from "react-native-safe-area-context";
@@ -1403,11 +1403,7 @@ return (
},
}}
>
- {loggedIn && (
-
- )}
+ {loggedIn && }
);
diff --git a/ui-kit/react-native/components-overview.mdx b/ui-kit/react-native/components-overview.mdx
index d2cffa3fd..a26948898 100644
--- a/ui-kit/react-native/components-overview.mdx
+++ b/ui-kit/react-native/components-overview.mdx
@@ -58,6 +58,9 @@ All components are imported from `@cometchat/chat-uikit-react-native`.
| CometChatMessageComposer | Rich text input with attachments, mentions, voice notes | `user`, `group`, `onSendButtonPress`, `placeholderText` | [Message Composer](/ui-kit/react-native/message-composer) |
| CometChatCompactMessageComposer | Compact message input with rich text formatting, auto-expanding input, and attachments | `user`, `group`, `onSendButtonPress`, `enableRichTextEditor` | [Compact Message Composer](/ui-kit/react-native/compact-message-composer) |
| CometChatThreadHeader | Parent message bubble and reply count for threaded view | `parentMessage`, `onClose` | [Thread Header](/ui-kit/react-native/threaded-messages-header) |
+| CometChatReactions | Row of reaction pills under a message bubble | `messageObject`, `onReactionPress`, `alignment` | [Message List](/ui-kit/react-native/message-list#reaction-components) |
+| CometChatQuickReactions | Quick reaction bar shown on long press | `quickReactions`, `onReactionPress`, `onAddReactionPress` | [Message List](/ui-kit/react-native/message-list#reaction-components) |
+| CometChatReactionList | Tabbed sheet listing who reacted with what | `message`, `onPress`, `selectedReaction` | [Message List](/ui-kit/react-native/message-list#reaction-components) |
### Calling
@@ -66,6 +69,7 @@ All components are imported from `@cometchat/chat-uikit-react-native`.
| CometChatCallButtons | Voice and video call initiation buttons | `user`, `group`, `onVoiceCallPress`, `onVideoCallPress` | [Call Buttons](/ui-kit/react-native/call-buttons) |
| CometChatIncomingCall | Incoming call notification with accept/decline | `call`, `onAccept`, `onDecline` | [Incoming Call](/ui-kit/react-native/incoming-call) |
| CometChatOutgoingCall | Outgoing call screen with cancel control | `call`, `onClosePress` | [Outgoing Call](/ui-kit/react-native/outgoing-call) |
+| CometChatOngoingCall | In-call screen for an active voice or video call | `sessionID`, `callSettingsBuilder` | [Ongoing Call](/ui-kit/react-native/ongoing-call) |
| CometChatCallLogs | Scrollable list of call history | `callLogsRequestBuilder`, `onItemPress` | [Call Logs](/ui-kit/react-native/call-logs) |
### AI
@@ -73,6 +77,9 @@ All components are imported from `@cometchat/chat-uikit-react-native`.
| Component | Purpose | Key Props | Page |
| --- | --- | --- | --- |
| CometChatAIAssistantChatHistory | AI assistant conversation history | `user`, `onMessageClicked`, `onNewChatButtonClick` | [AI Assistant Chat History](/ui-kit/react-native/ai-assistant-chat-history) |
+| CometChatConversationStarter | AI-generated opening lines as tappable chips | `getConversationStarters`, `onSuggestionClicked` | [Smart Chat Features](/ui-kit/react-native/ai-features#conversation-starter) |
+| CometChatSmartReplies | AI-generated reply suggestions as tappable chips | `getSmartReplies`, `onSuggestionClicked`, `closeCallback` | [Smart Chat Features](/ui-kit/react-native/ai-features#smart-replies) |
+| CometChatConversationSummary | AI-generated summary of a conversation | `getConversationSummary`, `closeCallback` | [Smart Chat Features](/ui-kit/react-native/ai-features#conversation-summary) |
---
diff --git a/ui-kit/react-native/custom-message-types.mdx b/ui-kit/react-native/custom-message-types.mdx
new file mode 100644
index 000000000..115f90688
--- /dev/null
+++ b/ui-kit/react-native/custom-message-types.mdx
@@ -0,0 +1,275 @@
+---
+title: "Custom Message Types"
+sidebarTitle: "Custom Message Types"
+description: "Register a custom message type in the CometChat React Native UI Kit using DataSourceDecorator, ChatConfigurator and ExtensionsDataSource — the five required overrides, and the registration timing that makes them stick."
+---
+
+
+
+| Field | Value |
+| --- | --- |
+| Package | `@cometchat/chat-uikit-react-native` |
+| Import | `import { ChatConfigurator, DataSourceDecorator, ExtensionsDataSource } from "@cometchat/chat-uikit-react-native";` |
+| Key classes | `DataSourceDecorator` · `ChatConfigurator` · `ExtensionsDataSource` · `MessageDataSource` |
+| Required overrides | **Five** — `getAllMessageTemplates` · `getMessageTemplate` · `getAllMessageTypes` · `getAllMessageCategories` · `getId` |
+| Register with | `ChatConfigurator.enable(source => new MyDataSource(source))` |
+| Prerequisites | `CometChatUIKit.init()` completed **and** `CometChatUIKit.login()` resolved — [details](#when-to-register) |
+| Constraints | `getId` must not call `super` and must be unique · registration before `login()` is discarded · an `ExtensionsDataSource` must override `enable()` |
+| Primary output | The custom type renders in `CometChatMessageList` **and** survives a reload |
+| Related | [Message List](/ui-kit/react-native/message-list) · [Message Composer](/ui-kit/react-native/message-composer) · [Methods](/ui-kit/react-native/methods) |
+
+
+
+The UI Kit has no plugin API. It customises through a **decorator chain**: you wrap the active data source in your own `DataSourceDecorator`, override the methods you need, and register the result with `ChatConfigurator`.
+
+```mermaid
+graph LR
+ CC["ChatConfigurator.dataSource"] --> D["Your DataSourceDecorator"]
+ D --> M["MessageDataSource (default)"]
+```
+
+`MessageDataSource` is the default implementation `ChatConfigurator` starts from. Every decorator you register wraps whatever is currently active, so calling `enable()` more than once layers decorators rather than replacing them.
+
+---
+
+## The five required overrides
+
+A custom message type has to be declared twice — once so the list knows how to **render** it, and once so the list knows to **fetch** it — plus an identity so `ChatConfigurator` can tell your decorator apart from the others.
+
+| Half | Methods | Why |
+| --- | --- | --- |
+| Render | `getAllMessageTemplates` · `getMessageTemplate` | Maps the type to a bubble |
+| **Fetch** | **`getAllMessageTypes`** · **`getAllMessageCategories`** | `CometChatMessageList` builds `setTypes`/`setCategories` from these |
+| **Identity** | **`getId`** | `ChatConfigurator.enable()` dedupes on it |
+
+Miss the fetch half and the bubble renders optimistically when the message is sent, then disappears on reload — the type is filtered out **server-side**, with no error in the console, on the listener, or in the network response. See [Filtering Messages](/ui-kit/react-native/message-list#filtering-messages).
+
+The four template and type methods must call `super` and extend the result. Returning your own list wholesale drops every built-in type.
+
+
+**`getId` is the exception — it must not call `super`.**
+
+The base implementation on `DataSourceDecorator` throws, it does not delegate:
+
+```ts
+getId(): string {
+ throw new Error("Method not implemented.");
+}
+```
+
+Both ways of getting it wrong fail quietly or confusingly:
+
+| Mistake | What happens |
+| --- | --- |
+| No `getId` override | Crashes at `ChatConfigurator.enable()` with `Method not implemented.` — a message naming neither `getId` nor your decorator. The class is **not** `abstract`, so TypeScript does not catch it. |
+| `return super.getId()` or the wrapped source's id | `enable()` finds the id already in its `names` list, decides the decorator is registered, and **skips it silently**. Nothing renders and nothing errors. |
+
+Return a string unique to your decorator.
+
+
+---
+
+## When to register
+
+
+**Register after `CometChatUIKit.login()` resolves — not after `init()`.**
+
+`login()` calls `enableExtensions()`, whose first statement re-initialises the data source:
+
+```ts
+private static enableExtensions() {
+ ChatConfigurator.init(); // re-initialize data source
+```
+
+`ChatConfigurator.init()` replaces `dataSource` and resets the `names` dedup list:
+
+```ts
+static init(initialSource?: DataSource) {
+ this.dataSource = initialSource ?? new MessageDataSource();
+ this.names = ["message_utils"];
+ this.names.push(this.dataSource.getId());
+}
+```
+
+`enableExtensions()` runs from every entry point that establishes or changes the session — `init()`, `login()` and `getLoggedInUser()` among them. Anything registered at module scope, or straight after `init()`, is gone by the time the user is logged in.
+
+
+```tsx lines
+import { CometChatUIKit, ChatConfigurator } from "@cometchat/chat-uikit-react-native";
+
+await CometChatUIKit.init(uiKitSettings);
+await CometChatUIKit.login({ uid: "cometchat-uid-1" });
+
+// Only now does the registration survive.
+ChatConfigurator.enable((source) => new PollDataSource(source));
+```
+
+---
+
+## Example: a poll message type
+
+```tsx lines
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+import {
+ ChatConfigurator,
+ CometChatMessageTemplate,
+ CometChatTheme,
+ DataSource,
+ DataSourceDecorator,
+} from "@cometchat/chat-uikit-react-native";
+import { Text } from "react-native";
+
+const POLL_TYPE = "poll";
+
+class PollDataSource extends DataSourceDecorator {
+ // Required. Must be unique and must not delegate to the wrapped source.
+ getId(): string {
+ return "poll_data_source";
+ }
+
+ // Fetch half — without these the bubble vanishes on reload.
+ getAllMessageTypes(): string[] {
+ return [...super.getAllMessageTypes(), POLL_TYPE];
+ }
+
+ getAllMessageCategories(): string[] {
+ return [...super.getAllMessageCategories(), CometChat.CATEGORY_CUSTOM];
+ }
+
+ // Render half.
+ getAllMessageTemplates(
+ theme: CometChatTheme,
+ additionalParams?: any
+ ): CometChatMessageTemplate[] {
+ return [
+ ...super.getAllMessageTemplates(theme, additionalParams),
+ this.getPollTemplate(),
+ ];
+ }
+
+ getMessageTemplate(
+ messageType: string,
+ messageCategory: string,
+ theme: CometChatTheme,
+ additionalParams?: any,
+ message?: CometChat.BaseMessage
+ ): CometChatMessageTemplate | null {
+ if (
+ messageType === POLL_TYPE &&
+ messageCategory === CometChat.CATEGORY_CUSTOM
+ ) {
+ return this.getPollTemplate();
+ }
+ return super.getMessageTemplate(
+ messageType,
+ messageCategory,
+ theme,
+ additionalParams,
+ message
+ );
+ }
+
+ private getPollTemplate(): CometChatMessageTemplate {
+ return new CometChatMessageTemplate({
+ type: POLL_TYPE,
+ category: CometChat.CATEGORY_CUSTOM,
+ ContentView: (message: CometChat.BaseMessage) => {
+ const data = (message as CometChat.CustomMessage).getCustomData() as {
+ question?: string;
+ };
+ return {data?.question ?? "Poll"};
+ },
+ });
+ }
+}
+
+export function registerPollType(source: DataSource) {
+ return new PollDataSource(source);
+}
+```
+
+Register it after login:
+
+```tsx lines
+ChatConfigurator.enable(registerPollType);
+```
+
+---
+
+## Registering through `uiKitSettings.extensions`
+
+`enableExtensions()` re-applies `uiKitSettings.extensions` *after* the reset, so an `ExtensionsDataSource` passed in settings is the one registration route that survives `login()`. It has its own trap.
+
+`ExtensionsDataSource` is abstract. It requires `addExtension()` and `getExtensionId()`, and ships a concrete `enable()`:
+
+```ts
+abstract class ExtensionsDataSource {
+ abstract addExtension(): void;
+ abstract getExtensionId(): string;
+
+ enable(): void {
+ CometChat.isExtensionEnabled(this.getExtensionId()).then((enabled) => {
+ if (enabled) this.addExtension();
+ });
+ }
+}
+```
+
+
+**A custom message type is not a dashboard extension.**
+
+`isExtensionEnabled("poll")` resolves `false` for any type you invented, so the inherited `enable()` never calls `addExtension()` and your decorator is never registered — silently. Override `enable()` as well, and the dashboard check is bypassed.
+
+Both steps or neither: passing the settings without overriding `enable()` fails exactly as quietly as registering before `login()`.
+
+
+```tsx lines
+import {
+ ChatConfigurator,
+ ExtensionsDataSource,
+} from "@cometchat/chat-uikit-react-native";
+
+class PollExtension extends ExtensionsDataSource {
+ getExtensionId(): string {
+ return "poll";
+ }
+
+ addExtension(): void {
+ ChatConfigurator.enable((source) => new PollDataSource(source));
+ }
+
+ // Required: the inherited enable() gates on a dashboard check that is
+ // false for a custom type, so addExtension() would never run.
+ override enable(): void {
+ this.addExtension();
+ }
+}
+
+CometChatUIKit.init({
+ appId: "APP_ID",
+ region: "REGION",
+ authKey: "AUTH_KEY",
+ extensions: [new PollExtension()],
+});
+```
+
+Passed this way, the type is re-registered automatically on every `login()`, so you do not have to sequence the call yourself.
+
+---
+
+## Choosing a route
+
+| Route | Survives `login()` | Extra requirement |
+| --- | --- | --- |
+| `ChatConfigurator.enable()` after `login()` resolves | Yes, until the next `login()` / `getLoggedInUser()` | Sequence the call yourself |
+| `ExtensionsDataSource` in `uiKitSettings.extensions` | Yes, re-applied on every session change | Must override `enable()` |
+
+Use the settings route for a type your app always needs. Use the direct call for a type you register conditionally after the user is known.
+
+---
+
+## Related
+
+- [Message List → Filtering Messages](/ui-kit/react-native/message-list#filtering-messages) — why the fetch half matters.
+- [Message Composer](/ui-kit/react-native/message-composer) — sending a custom message.
+- [Methods](/ui-kit/react-native/methods) — `CometChatUIKit.init` and `login`.
diff --git a/ui-kit/react-native/events.mdx b/ui-kit/react-native/events.mdx
index 1db317b8e..3ec0baefc 100644
--- a/ui-kit/react-native/events.mdx
+++ b/ui-kit/react-native/events.mdx
@@ -10,11 +10,11 @@ description: "Listen to UI Kit events for conversations, users, groups, messages
| Package | `@cometchat/chat-uikit-react-native` |
| Import | `import { CometChatUIEventHandler } from "@cometchat/chat-uikit-react-native";` |
| Conversation events | `ccConversationDeleted`, `ccUpdateConversation` |
-| User events | `ccUserBlocked`, `ccUserUnblocked` |
-| Group events | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnbanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` |
-| Message events | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccLiveReaction`, plus SDK listener events |
-| Call events | `onIncomingCallAccepted`, `onIncomingCallRejected`, `onCallEnded`, `onCallInitiated`, `onOutgoingCallAccepted`, `onOutgoingCallRejected` |
-| UI events | `ccActiveChatChanged`, `ccCardActionClicked` |
+| User events | `ccUserBlocked`, `ccUserUnBlocked` |
+| Group events | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnBanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` |
+| Message events | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccActiveChatChanged`, plus SDK listener events |
+| Call events | `ccCallAccepted`, `ccCallRejected`, `ccCallEnded`, `ccOutgoingCall` |
+| UI events | `ccCardActionClicked` |
| Purpose | Decoupled communication between UI Kit components — subscribe to events to react to changes without direct component references |
@@ -41,7 +41,7 @@ It consists of the following events:
| 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. |
+| ccUserUnBlocked | This event is triggered when the user successfully unblocks another user. |
### CometChatGroupsEvents
@@ -57,7 +57,7 @@ It consists of the following events:
| 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 |
+| 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 |
@@ -74,7 +74,7 @@ It consists of the following events:
| ccMessageEdited | This event is triggered when the user successfully edits the 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. |
+| ccActiveChatChanged | This event is triggered when the user navigates to a particular chat window. |
| 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. |
@@ -97,16 +97,35 @@ It consists of the following events:
It consists of the following events:
-| Name | Description |
-| ------------------------------------------- | ------------------------------------------------------- |
-| **func** onIncomingCallAccepted(call: Call) | Triggers whenever incoming call is accepted by the user |
-| **func** onIncomingCallRejected(call: Call) | Triggers whenever incoming call is rejected by the user |
-| **func** onCallEnded(call: Call) | Triggers whenever the call is ended |
-| **func** onCallInitiated(call: Call) | Triggers whenever the call is getting initiated |
-| **func** onOutgoingCallAccepted(call: Call) | Triggers whenever outgoing call is accepted by the user |
-| **func** onOutgoingCallRejected(call: Call) | Triggers whenever outgoing call is rejected by the user |
+| Name | Description |
+| -------------- | ------------------------------------------------------------------------------------------------------------------------ |
+| ccCallAccepted | Triggers when the user accepts an incoming call. Payload: `{ call }`. |
+| ccCallRejected | Triggers when the user rejects an incoming call, or cancels an outgoing call before it is answered. Payload: `{ call }`. |
+| ccCallEnded | Triggers when a call ends. Payload: `{ call }`; `call` can be undefined. |
+| ccOutgoingCall | Triggers when the user places a call. Payload: `{ call }`. |
-### CometChatUIEventListener
+Outgoing-call **accepted** and **rejected** are not UI Kit events — the UI Kit never emits them. Listen for them on the Chat SDK's call listener instead:
+
+```tsx lines
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+
+CometChat.addCallListener(
+ "OUTGOING_CALL_LISTENER",
+ new CometChat.CallListener({
+ onOutgoingCallAccepted: (call: CometChat.Call) => {
+ // the callee accepted
+ },
+ onOutgoingCallRejected: (call: CometChat.Call) => {
+ // the callee rejected
+ },
+ })
+);
+
+// Remove it when you no longer need it, e.g. when the screen unmounts
+CometChat.removeCallListener("OUTGOING_CALL_LISTENER");
+```
+
+### UI Events
UI events refer to actions or interactions performed by a user within the CometChat 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.
@@ -114,7 +133,6 @@ It consists of the following events:
| Name | Description |
| ------------------- | ---------------------------------------------------------------------------- |
-| ccActiveChatChanged | This event is triggered when the user navigates to a particular chat window. |
| ccCardActionClicked | This event is triggered when the user clicks an action on a card message bubble. The event payload contains the `message` and the clicked `action`. |
diff --git a/ui-kit/react-native/expo-integration.mdx b/ui-kit/react-native/expo-integration.mdx
index 7cab22bc9..37d8b222b 100644
--- a/ui-kit/react-native/expo-integration.mdx
+++ b/ui-kit/react-native/expo-integration.mdx
@@ -124,8 +124,6 @@ Add required permissions for camera and microphone:
"android.permission.MODIFY_AUDIO_SETTINGS",
"android.permission.RECORD_AUDIO",
"android.permission.ACCESS_NETWORK_STATE",
- "android.permission.WRITE_EXTERNAL_STORAGE",
- "android.permission.READ_EXTERNAL_STORAGE",
"android.permission.VIBRATE"
]
}
@@ -133,6 +131,8 @@ Add required permissions for camera and microphone:
}
```
+The UI Kit declares `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` in its own Android manifest, so you do not need to add them yourself.
+
### Optional: Install Calling SDK
To enable voice/video calling:
diff --git a/ui-kit/react-native/guide-group-chat.mdx b/ui-kit/react-native/guide-group-chat.mdx
index 2f7568856..6fc243b5c 100644
--- a/ui-kit/react-native/guide-group-chat.mdx
+++ b/ui-kit/react-native/guide-group-chat.mdx
@@ -278,7 +278,7 @@ const AddMemberScreen: React.FC = ({ group, onBack }) => {
### 4. View and Manage Group Members
-Use `CometChatGroupMembers` to display members with options for scope changes and removal.
+Use `CometChatGroupMembers` to display members. Owners, admins and moderators get options to change a member's scope, remove them, or ban them.
```tsx
import React from 'react';
@@ -311,6 +311,8 @@ const ViewMembersScreen: React.FC = ({ group }) => {
};
```
+The UI Kit has no screen for listing banned members or unbanning them. To undo a ban from your app, use the Chat SDK: fetch banned members with [`BannedMembersRequestBuilder`](/sdk/react-native/group-kick-ban-members#get-list-of-banned-members-for-a-group), then unban with [`CometChat.unbanGroupMember()`](/sdk/react-native/group-kick-ban-members#unban-a-group-member). To remove the Ban option instead, set [`hideBanMemberOption`](/ui-kit/react-native/group-members).
+
---
### 5. Transfer Ownership
@@ -384,6 +386,8 @@ const TransferOwnershipScreen: React.FC = ({ group, onCl
| Add members | `CometChat.addMembersToGroup()` |
| Remove member | `CometChat.kickGroupMember()` |
| Ban member | `CometChat.banGroupMember()` |
+| Unban member | `CometChat.unbanGroupMember()` |
+| List banned members | `CometChat.BannedMembersRequestBuilder` |
| Change scope | `CometChat.updateGroupMemberScope()` |
| Transfer ownership | `CometChat.transferGroupOwnership()` |
| Group events | `CometChatGroupsEvents` |
diff --git a/ui-kit/react-native/llms-react-native-v5.mdx b/ui-kit/react-native/llms-react-native-v5.mdx
index 0e0233d05..93d95e3a9 100644
--- a/ui-kit/react-native/llms-react-native-v5.mdx
+++ b/ui-kit/react-native/llms-react-native-v5.mdx
@@ -52,7 +52,8 @@ This kit renders **native views**, not DOM. Code that works in the React UI Kit
integration page below; the install/native-config steps differ.
- **No plugin API.** React v7's `CometChatMessagePlugin` and `CometChatPluginRegistry` **do not
exist in this kit** — emitting them will not compile. RN customises through a **decorator
- chain**: extend `DataSourceDecorator`, override what you need calling `super` each time, and
+ chain**: extend `DataSourceDecorator`, override what you need calling `super` each time —
+ **except `getId`, which is mandatory and must not call `super`** — and
register with `ChatConfigurator.enable(...)` **after `CometChatUIKit.login()`** (login re-runs
`ChatConfigurator.init()`, discarding anything registered earlier). See *Customization &
extensibility* below.
@@ -117,11 +118,13 @@ components, theming tokens, or feature enablement.
The decorator chain — RN's equivalent of React's plugin system. Entries name the **API**, not just
the page, because the intent ("add a custom message type") does not match any page title.
- **Custom message type** — `DataSourceDecorator` · `ChatConfigurator.enable` ·
- `CometChatMessageTemplate` → [Message List → Filtering Messages](/ui-kit/react-native/message-list).
- Needs **four** overrides: `getAllMessageTemplates` · `getMessageTemplate` (render) **and**
+ `CometChatMessageTemplate` → [Custom Message Types](/ui-kit/react-native/custom-message-types).
+ Needs **five** overrides: `getAllMessageTemplates` · `getMessageTemplate` (render),
`getAllMessageTypes` · `getAllMessageCategories` (fetch — the list builds `setTypes`/`setCategories`
- from them). Shipping only the render pair gives a bubble that appears on send and **vanishes on
- reload, with no error**. Register after `login()`.
+ from them) **and** `getId` (identity — `enable()` dedupes on it). Shipping only the render pair
+ gives a bubble that appears on send and **vanishes on reload, with no error**; omitting `getId`
+ throws `Method not implemented.` at registration, and delegating it makes `enable()` skip the
+ decorator **silently**. Register after `login()`.
- **Long-press menu / composer actions** — `getMessageOptions` · `getAuxiliaryOptions` on the same
decorator → [Message List](/ui-kit/react-native/message-list) · [Message Composer](/ui-kit/react-native/message-composer)
- **Custom bubble rendering** — view slots on each component → the component's own page
@@ -129,8 +132,9 @@ the page, because the intent ("add a custom message type") does not match any pa
- **Kit methods** — [Methods](/ui-kit/react-native/methods)
-`DataSourceDecorator` / `MessageDataSource` / `ExtensionsDataSource` have **no dedicated RN page**
-yet — the custom-message-type contract is documented on Message List. Tracked as a docs gap.
+`DataSourceDecorator` / `MessageDataSource` / `ExtensionsDataSource` are documented on
+[Custom Message Types](/ui-kit/react-native/custom-message-types), together with the
+`ExtensionsDataSource` route through `uiKitSettings.extensions` and the `enable()` override it needs.
## Text formatters
diff --git a/ui-kit/react-native/localize.mdx b/ui-kit/react-native/localize.mdx
index 6bc7aed5e..380ef6cd9 100644
--- a/ui-kit/react-native/localize.mdx
+++ b/ui-kit/react-native/localize.mdx
@@ -13,10 +13,10 @@ description: "Configure multi-language localization, custom translations, and au
| Import | `import { CometChatI18nProvider } from "@cometchat/chat-uikit-react-native";` |
| Auto-detect | `` |
| Set language | `selectedLanguage="fr"` — manually set language code |
-| Override strings | `translations={{ "en-US": { CHATS: "My Chats" } }}` |
+| Override strings | `translations={{ "en": { CHATS: "My Chats" } }}` — key on the language code the kit resolves to |
| Add language | `translations={{ "custom": { CHATS: "Welcome" } }}` with `selectedLanguage="custom"` |
| Use in components | `const { t } = useCometChatTranslation(); t("CHATS")` |
-| Supported languages | 19: en-US, en-GB, zh, zh-TW, es, hi, ru, pt, ms, fr, de, sv, lt, hu, it, ko, ja, nl, tr |
+| Supported languages | 18: en, zh, zh-tw, es, hi, ru, pt, ms, fr, de, sv, lt, hu, it, ko, ja, nl, tr (plus `en-US`, `en-GB`, `en-IN` aliases of `en`) |
| Dependency | Requires `react-native-localize` package for auto-detection |
@@ -36,10 +36,9 @@ Prerequisites:
| Language | Code |
| --- | --- |
-| English (United States) | `en-US` |
-| English (United Kingdom) | `en-GB` |
-| Chinese | `zh` |
-| Chinese (Traditional) | `zh-TW` |
+| English | `en` |
+| Chinese (Simplified) | `zh` |
+| Chinese (Traditional) | `zh-tw` |
| Spanish | `es` |
| Hindi | `hi` |
| Russian | `ru` |
@@ -56,16 +55,40 @@ Prerequisites:
| Dutch | `nl` |
| Turkish | `tr` |
+`en-US`, `en-GB` and `en-IN` are also accepted, but all three resolve to the same English strings as `en`.
+
+
+Use the casing shown above. `zh-tw` is lowercase, while the English variants use an
+uppercase region. On **v5.5.0 and earlier** codes are matched exactly, so
+`selectedLanguage="zh-TW"` is not recognised and the fallback language is used
+instead.
+
+
+
+On **v5.5.0 and earlier**, automatic detection reduces the device locale to the
+bare **language** code: a device set to `en-US` resolves to `en`, and a device set
+to Chinese (Traditional) resolves to `zh` and is served Simplified Chinese.
+
+Two consequences on those versions:
+
+* Key your `translations` overrides on `en`. An override keyed on `en-US` is not
+ applied unless you also pass `selectedLanguage="en-US"`.
+* Pass `selectedLanguage="zh-tw"` explicitly to serve Traditional Chinese.
+
+Keying overrides on `en` and selecting `zh-tw` is correct on every version, so
+following the examples on this page needs no change when you upgrade.
+
+
---
## Provider Props
| Prop | Type | Description |
| --- | --- | --- |
-| `selectedLanguage` | `string` | Language code to use. Defaults to device language or English |
-| `autoDetectLanguage` | `boolean` | Auto-detect device language. Default: `true` |
-| `translations` | `object` | Custom translation overrides per language |
-| `fallbackLanguage` | `string` | Fallback language if selected is unavailable |
+| `selectedLanguage` | `string` | Language code to use. Overrides automatic detection. If the code is not recognised, `fallbackLanguage` is used |
+| `autoDetectLanguage` | `boolean` | Auto-detect the device language. Default: `true`. Ignored when `selectedLanguage` is set |
+| `translations` | `object` | Custom translation overrides, keyed by language code. Keys must match the resolved language code |
+| `fallbackLanguage` | `string` | Language used when the selected language, or an individual key, is unavailable. Default: `en` |
---
@@ -126,13 +149,12 @@ import {
const App = () => {
const translations = {
- // Overridden translations
- "en-US": {
+ // Overrides the built-in English strings. Key on "en": a device set to
+ // en-US, en-GB or en-IN resolves to "en" under automatic detection.
+ en: {
CHATS: "Welcome to the CometChat App",
},
- "en-GB": {
- CHATS: "Welcome to CometChat",
- },
+ // A language the UI Kit does not ship. Requires selectedLanguage="custom".
custom: {
CHATS: "Welcome",
},
@@ -212,7 +234,7 @@ const translatedText = t("CHATS"); // Returns localized string
Below are the things which the developer can customize:
-* **Set a supported language** (`selectedLanguage`): The developer can set a language out of the 19 supported languages.
+* **Set a supported language** (`selectedLanguage`): The developer can set a language out of the 18 supported languages.
* **Customize default localization strings** (`translations`): The developer can customize default localization strings for a particular language.
* **Add custom strings** (`translations`): A developer can add custom strings in the localization for a particular language.
* **Add a new language** (`translations`): The developer can add completely new languages.
diff --git a/ui-kit/react-native/message-composer.mdx b/ui-kit/react-native/message-composer.mdx
index 96e1f7ddd..46e8d7c38 100644
--- a/ui-kit/react-native/message-composer.mdx
+++ b/ui-kit/react-native/message-composer.mdx
@@ -81,6 +81,91 @@ On send, staged files are grouped by media kind and sent as **one media message
Set `enableMultipleAttachments={false}` to revert to legacy single-select, send-immediately behavior — each attachment option sends one file straight away, with no staging tray. Pass the same value to [`CometChatMessageList`](/ui-kit/react-native/message-list) so rendering matches.
+### The tray components
+
+The tray is built from exported components, so you can render your own version of it. Two of them are exported under a second name, and both names point at the same component:
+
+| Component | Also exported as | What it renders |
+| --- | --- | --- |
+| `CometChatAttachmentTray` | `CometChatAttachmentPreview` | The horizontal strip of staged files: one tile per file, plus a combined progress bar that disappears once every file has uploaded, failed or been rejected |
+| `CometChatAttachmentTile` | `CometChatAttachmentPreviewItem` | One staged file, as a media thumbnail, a file card or an audio card, with its remove and retry controls |
+| `CometChatAttachmentViewer` | — | A full-screen pager for the attachments of a message that has already been sent |
+
+
+These components exist only in the React Native UI Kit. The React UI Kit has no equivalent.
+
+For the attachments of a sent message, use [`CometChatMediaViewer`](#cometchatmediaviewer). It supersedes `CometChatAttachmentViewer` and is what the composer and the image and video bubbles use; `CometChatAttachmentViewer` is still exported, but the kit no longer renders it.
+
+
+#### CometChatAttachmentTray
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `attachments` | `SelectedAttachment[]` | Required. The tray renders nothing while this is empty. |
+| `onRemove` | `(fileId: string) => void` | Required. Called with the file the user removed. |
+| `onRetry` | `(fileId: string) => void` | Required. Called for a file whose upload failed. |
+| `onPressTile` | `(fileId: string) => void` | Called when a tile's thumbnail is tapped. |
+| `style` | theme `attachmentTrayStyles` | `containerStyle`, `progressTrackStyle` and `progressFillStyle`, merged over the theme. |
+
+```tsx lines
+import React from "react";
+import { CometChatAttachmentTray } from "@cometchat/chat-uikit-react-native";
+
+type StagedFile = React.ComponentProps["attachments"][number];
+
+function CustomTray({
+ staged,
+ onRemove,
+ onRetry,
+}: {
+ staged: StagedFile[];
+ onRemove: (fileId: string) => void;
+ onRetry: (fileId: string) => void;
+}) {
+ return ;
+}
+```
+
+#### CometChatAttachmentTile
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `attachment` | `SelectedAttachment` | Required. The file this tile shows. |
+| `onRemove` | `(fileId: string) => void` | Required. |
+| `onRetry` | `(fileId: string) => void` | Required. |
+| `onPress` | `(fileId: string) => void` | Called when the thumbnail is tapped. |
+| `testID` | `string` | The tile also derives `${testID}.remove`, `${testID}.retry` and `${testID}.uploading`. |
+| `style` | theme `attachmentTileStyles` | Styles the file card, media tile and audio card variants. |
+
+#### CometChatAttachmentViewer
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `attachments` | `CometChat.Attachment[]` | Required. |
+| `initialIndex` | `number` | Required. The attachment to open on. |
+| `message` | `CometChat.BaseMessage` | Required. |
+| `onClose` | `() => void` | Required. |
+| `visible` | `boolean` | Controls the modal. Defaults to `true`. |
+
+#### CometChatMediaViewer
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `mediaItems` | `CometChat.Attachment[]` | Required. Items to page through. |
+| `startIndex` | `number` | Required. Zero-based index to open on. |
+| `visible` | `boolean` | Required. |
+| `onClose` | `() => void` | Required. |
+| `message` | `CometChat.BaseMessage` | Used for the sender and timestamp in the header. |
+| `canPreview` | `(attachment: CometChat.Attachment) => boolean` | Which items get a real preview; the rest show a "No preview available" page. Defaults to images and videos. |
+
+
+`SelectedAttachment` is the composer's staging model, and the kit does not export the type. In TypeScript, derive it from the component instead:
+
+```tsx
+type StagedFile = React.ComponentProps["attachments"][number];
+```
+
+
---
## Actions and Events
diff --git a/ui-kit/react-native/message-list.mdx b/ui-kit/react-native/message-list.mdx
index 57db017ba..c440b7031 100644
--- a/ui-kit/react-native/message-list.mdx
+++ b/ui-kit/react-native/message-list.mdx
@@ -78,7 +78,7 @@ description: "Display sent and received messages with text, media, reactions, re
"ai": {
"suggestedMessages": { "type": "string[]", "note": "Predefined prompts for AI assistant chats" },
"aiAssistantTools": { "type": "CometChatAIAssistantTools", "note": "Tool actions for AI assistant" },
- "quickReactionList": { "type": "string[]", "default": "predefined reactions" },
+ "quickReactionList": { "type": "[string, string?, string?, string?, string?]", "default": "👍 ❤️ 😂 😢 🙏", "note": "Tuple capped at 5 — not string[]" },
"streamingSpeed": { "type": "number", "default": "undefined", "note": "AI response streaming speed in ms" }
},
"viewSlots": {
@@ -238,15 +238,23 @@ A type missing from those two filters is excluded **server-side**, so overriding
message is sent, then disappears on reload — with no error in the console, on the listener,
or in the network response.
-When you add a custom message type in a `DataSourceDecorator`, override **four** methods:
+When you add a custom message type in a `DataSourceDecorator`, override **five** methods:
| Half | Methods |
| --- | --- |
| Render | `getAllMessageTemplates` · `getMessageTemplate` |
| **Fetch** | **`getAllMessageTypes`** · **`getAllMessageCategories`** |
+| **Identity** | **`getId`** |
-Each must call `super` and extend the result — returning your own list wholesale drops every
-built-in type.
+The four template and type methods must call `super` and extend the result — returning your own
+list wholesale drops every built-in type.
+
+`getId` is the exception: it must **not** call `super`. The base implementation throws
+`Method not implemented.`, so omitting the override crashes at `ChatConfigurator.enable()` with a
+message that names neither `getId` nor your decorator. Returning the wrapped source's id is worse —
+`enable()` dedupes on the id, finds it already registered, and skips your decorator **silently**.
+Return an id unique to your decorator. See
+[Custom Message Types](/ui-kit/react-native/custom-message-types) for the full contract.
Register the decorator **after `CometChatUIKit.login()`**, not merely after `init()`.
`login()` calls `enableExtensions()`, whose first statement is `ChatConfigurator.init()` —
@@ -713,6 +721,86 @@ See [CometChatMentionsFormatter](/ui-kit/react-native/mentions-formatter-guide)
---
+## Reaction Components
+
+Reactions are on by default and the list renders them for you, so most apps only need the props above. The three pieces the list is built from are also exported, for hosts composing their own bubbles or their own reaction bar.
+
+| Component | What it renders |
+| --- | --- |
+| `CometChatReactions` | The row of reaction pills under a message bubble |
+| `CometChatQuickReactions` | The quick reaction bar shown on long press, with its "add reaction" button |
+| `CometChatReactionList` | The tabbed sheet listing who reacted with what |
+
+
+The two required props are named differently: `CometChatReactions` takes **`messageObject`**, while `CometChatReactionList` takes **`message`**. Both are a `CometChat.BaseMessage`.
+
+
+### CometChatReactions
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `messageObject` | `CometChat.BaseMessage` | Required. The message whose reactions are shown. |
+| `onReactionPress` | `(reaction: CometChat.ReactionCount, messageObject: CometChat.BaseMessage) => void` | Called when a pill is tapped. |
+| `onReactionLongPress` | `(reaction: CometChat.ReactionCount, messageObject: CometChat.BaseMessage) => void` | Called when a pill is long pressed — the list uses this to open `CometChatReactionList`. |
+| `alignment` | `"left" \| "right" \| "center"` | Which edge the row hugs. Defaults to left. |
+| `maxContentWidth` | `number` | Width budget in px. Without it the row shows at most 3 pills; with it, as many as fit. |
+| `style` | theme `messageBubbleReactionStyles` | `DeepPartial`, merged over the theme. |
+
+```tsx lines
+import { CometChatReactions } from "@cometchat/chat-uikit-react-native";
+
+ console.log(reaction.getReaction())}
+/>
+```
+
+### CometChatQuickReactions
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `quickReactions` | `[string, string?, string?, string?, string?]` | Tuple capped at five. Defaults to `["👍", "❤️", "😂", "😢", "🙏"]`. Same shape as [`quickReactionList`](#quickreactionlist). |
+| `onReactionPress` | `(emoji: string) => void` | Called with the emoji that was tapped. |
+| `onAddReactionPress` | `() => void` | Called when the trailing "add reaction" button is tapped. |
+| `addReactionUrl` | `ImageSourcePropType` | Replaces the "add reaction" button's icon. |
+| `style` | theme `quickReactionStyle` | Merged over the theme. |
+
+
+Its props type, `CometChatQuickReactionsProps`, is **not** exported from the package root — unlike `CometChatReactionsInterface` and `CometChatReactionListInterface`, which are. Derive it instead:
+
+```ts
+type QuickReactionsProps = React.ComponentProps;
+```
+
+
+### CometChatReactionList
+
+| Prop | Type | Notes |
+| --- | --- | --- |
+| `message` | `CometChat.BaseMessage` | Required. Note the name — not `messageObject`. |
+| `onPress` | `(messageReaction: CometChat.Reaction, message: CometChat.BaseMessage) => void` | Called when a row is tapped. |
+| `reactionsRequestBuilder` | `CometChat.ReactionsRequestBuilder` | Controls how reactions are fetched. |
+| `selectedReaction` | `string` | Which tab opens first — `"All"`, or a specific emoji. |
+| `onListEmpty` | `() => void` | Fires when the last reaction is removed, so you can close the sheet. |
+| `LoadingStateView` | `() => JSX.Element` | Replaces the skeleton shown while fetching. |
+| `ErrorStateView` | `() => JSX.Element` | Replaces the error state. |
+| `errorStateText` | `string` | Overrides the default error copy. |
+
+```tsx lines
+import { CometChatReactionList } from "@cometchat/chat-uikit-react-native";
+
+ setSheetOpen(false)}
+/>
+```
+
+Styling for all three is covered on [Component Styling](/ui-kit/react-native/component-styling).
+
+---
+
## Common Patterns
### Threaded message list
@@ -1397,12 +1485,18 @@ Displays threaded conversation for the specified parent message.
### quickReactionList
-Custom list of quick reactions.
+Custom list of quick reactions shown on the long-press reaction bar.
| | |
| --- | --- |
-| Type | `string[]` |
-| Default | Predefined reactions |
+| Type | `[string, string?, string?, string?, string?]` |
+| Default | `["👍", "❤️", "😂", "😢", "🙏"]` |
+
+
+This is a **tuple capped at five**, not a `string[]`. A sixth emoji does not compile, and a value
+typed as `string[]` is rejected with TS2322 even when it holds five items — annotate the constant
+with the tuple type, or pass the array inline so it is contextually typed.
+
---
diff --git a/ui-kit/react-native/ongoing-call.mdx b/ui-kit/react-native/ongoing-call.mdx
new file mode 100644
index 000000000..a5a8a3bb9
--- /dev/null
+++ b/ui-kit/react-native/ongoing-call.mdx
@@ -0,0 +1,347 @@
+---
+title: "Ongoing Call"
+description: "Display the React Native UI Kit in-call screen for voice and video calls with CometChatOngoingCall, configured through the Calls SDK call settings builder."
+---
+
+The `CometChatOngoingCall` component shows the screen users see during a voice or video call. It requests a call token for the session, then renders the Calls SDK call view, with video tiles and call controls such as mute, pause video, switch camera, and end call. Until the token arrives, it shows a loading spinner.
+
+
+
+| Field | Value |
+| --- | --- |
+| Component | `CometChatOngoingCall` |
+| Package | `@cometchat/chat-uikit-react-native` |
+| Import | `import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native";` |
+| Purpose | In-call screen for an active voice or video call. Gets a call token for the session and renders the Calls SDK call view. |
+| Data props | `sessionID` · `callSettingsBuilder` (both required) |
+| Primary output | None on the component — call events arrive on the `OngoingCallListener` set on `callSettingsBuilder` |
+| Other actions | `onError` — [details](#actions) |
+| View slots | None |
+| UI events | None of its own — [details](#events) |
+| Styling | No `style` prop — [details](#style) |
+| Prerequisites | `CometChatUIKit.init()` completed and a user logged in · `@cometchat/calls-sdk-react-native` installed (**not** a kit peer dependency) |
+
+
+
+---
+
+## Usage
+
+### Integration
+
+`CometChatIncomingCall` and `CometChatOutgoingCall` render `CometChatOngoingCall` for you once a call connects, so most apps never render it directly. Render it yourself when you build your own call flow.
+
+Pass the call's session ID and a `CometChatCalls.CallSettingsBuilder`. Set an `OngoingCallListener` on the builder so your app knows when the call ends.
+
+```tsx lines
+import { useMemo } from "react";
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+import { CometChatCalls } from "@cometchat/calls-sdk-react-native";
+import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native";
+
+function OngoingCallScreen({ call, onCallEnd }: { call: CometChat.Call; onCallEnd: () => void }) {
+ const callSettingsBuilder = useMemo(
+ () =>
+ new CometChatCalls.CallSettingsBuilder()
+ .enableDefaultLayout(true)
+ .setIsAudioOnlyCall(call.getType() === "audio")
+ .setCallEventListener(
+ new CometChatCalls.OngoingCallListener({
+ onCallEndButtonPressed: () => {
+ CometChat.endCall(call.getSessionId()).catch(console.log);
+ },
+ onCallEnded: () => {
+ CometChatCalls.endSession();
+ CometChat.clearActiveCall();
+ onCallEnd();
+ },
+ })
+ ),
+ [call]
+ );
+
+ return (
+
+ );
+}
+```
+
+This listener takes the same steps as `CometChatIncomingCall` when a call ends.
+
+
+The component fills its parent, so render it full screen, for example inside a React Native `Modal` as `CometChatOutgoingCall` does.
+
+
+### Actions
+
+[Actions](/ui-kit/react-native/components-overview#actions) dictate how a component functions. `CometChatOngoingCall` has one user-defined action.
+
+#### 1. onError
+
+Fires when the component cannot get a call token: no user is logged in, or `CometChat.getLoggedinUser()` or `CometChatCalls.generateToken()` fails. A plain JavaScript `Error`, such as the one for no logged-in user, arrives as a `CometChatException` with the code `TOKEN_GENERATION_FAILED`.
+
+```tsx lines
+import { useCallback } from "react";
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native";
+
+function OngoingCallWithError() {
+ const handleError = useCallback((error: CometChat.CometChatException) => {
+ console.error("OngoingCall error:", error);
+ }, []);
+
+ return (
+
+ );
+}
+```
+
+Errors during the call are not sent to this prop. They go to the `onError` handler of the `OngoingCallListener` on your builder.
+
+`CometChatOngoingCall` has no call-ended action. To act when the call ends, set `onCallEnded` on the builder's `OngoingCallListener`, as shown in [Integration](#integration).
+
+---
+
+### Filters
+
+[Filters](/ui-kit/react-native/components-overview#filters) narrow the data a component shows. `CometChatOngoingCall` shows no list. Instead, `callSettingsBuilder` controls the call itself.
+
+#### 1. CallSettingsBuilder
+
+`CometChatCalls.CallSettingsBuilder` from `@cometchat/calls-sdk-react-native` offers these methods:
+
+| Methods | Description | Code |
+| --- | --- | --- |
+| **enableDefaultLayout** | Show or hide the default button layout. Default: `true` | `.enableDefaultLayout(boolean)` |
+| **setIsAudioOnlyCall** | Make the call audio-only. Default: `false` | `.setIsAudioOnlyCall(boolean)` |
+| **setCallEventListener** | Set the `OngoingCallListener` that receives call events | `.setCallEventListener(OngoingCallListener)` |
+| **setMode** | Set the call mode: `DEFAULT` or `SPOTLIGHT` from `CometChatCalls.CALL_MODE` | `.setMode(mode)` |
+| **setDefaultAudioMode** | Set the default audio mode: `SPEAKER`, `EARPIECE`, `BLUETOOTH` or `HEADPHONES` from `CometChatCalls.AUDIO_MODE` | `.setDefaultAudioMode(audioMode)` |
+| **showEndCallButton** | Show or hide the end call button. Default: `true` | `.showEndCallButton(boolean)` |
+| **showMuteAudioButton** | Show or hide the mute audio button. Default: `true` | `.showMuteAudioButton(boolean)` |
+| **showPauseVideoButton** | Show or hide the pause video button. Default: `true` | `.showPauseVideoButton(boolean)` |
+| **showSwitchCameraButton** | Show or hide the switch camera button. Default: `true` | `.showSwitchCameraButton(boolean)` |
+| **showAudioModeButton** | Show or hide the audio mode button. Default: `true` | `.showAudioModeButton(boolean)` |
+| **showRecordingButton** | Show or hide the recording button. Default: `false` | `.showRecordingButton(boolean)` |
+| **startWithAudioMuted** | Start the call with audio muted. Default: `false` | `.startWithAudioMuted(boolean)` |
+| **startWithVideoMuted** | Start the call with video muted. Has no effect on audio calls. Default: `false` | `.startWithVideoMuted(boolean)` |
+| **startRecordingOnCallStart** | Start recording as soon as the call starts. Default: `false` | `.startRecordingOnCallStart(boolean)` |
+| **setIdleTimeoutPeriod** | When you are the only one in the call, end it after this period. You get the option to extend the call 60 seconds before it ends. Default: 180 seconds | `.setIdleTimeoutPeriod(number)` |
+| **enableVideoTileClick** | Allow tapping video tiles in Spotlight mode. Default: allowed | `.enableVideoTileClick(boolean)` |
+| **enableVideoTileDrag** | Allow dragging video tiles in Spotlight mode. Default: allowed | `.enableVideoTileDrag(boolean)` |
+
+#### Example
+
+In the example below, the call shows the recording button and starts with audio muted:
+
+```tsx lines
+import { CometChatCalls } from "@cometchat/calls-sdk-react-native";
+import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native";
+
+const callSettingsBuilder = new CometChatCalls.CallSettingsBuilder()
+ .enableDefaultLayout(true)
+ .setIsAudioOnlyCall(false)
+ .showRecordingButton(true)
+ .startWithAudioMuted(true)
+ .setCallEventListener(callListener); // the OngoingCallListener from Integration
+
+;
+```
+
+
+Voice and video calls need microphone and camera permissions on iOS and Android. Add them as described in [Add Permissions](/ui-kit/react-native/calling-integration#add-permissions).
+
+
+---
+
+### Events
+
+[Events](/ui-kit/react-native/components-overview#events) are emitted by a component. `CometChatOngoingCall` emits no events of its own. When `CometChatIncomingCall` or `CometChatOutgoingCall` render it for you, they emit this event when the call ends:
+
+| Event | Description |
+| --- | --- |
+| **ccCallEnded** | Triggers when a call shown by `CometChatIncomingCall` or `CometChatOutgoingCall` ends. Payload: `{ call }`; `call` can be undefined. |
+
+```tsx lines
+import { useEffect } from "react";
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+import { CometChatUIEventHandler } from "@cometchat/chat-uikit-react-native";
+
+function useCallEndedEvent() {
+ useEffect(() => {
+ const listenerId = "ONGOING_CALL_EVENTS_" + Date.now();
+
+ // Add the listener
+ CometChatUIEventHandler.addCallListener(listenerId, {
+ ccCallEnded: ({ call }: { call?: CometChat.Call }) => {
+ console.log("Call ended:", call);
+ },
+ });
+
+ // Remove the listener on cleanup
+ return () => {
+ CometChatUIEventHandler.removeCallListener(listenerId);
+ };
+ }, []);
+}
+```
+
+If you render `CometChatOngoingCall` yourself, nothing emits this event. Use `onCallEnded` on your builder's `OngoingCallListener` instead.
+
+---
+
+## Customization
+
+To fit your app's requirements, you can customize how the call behaves through the component's props and `callSettingsBuilder`.
+
+### Style
+
+`CometChatOngoingCall` has no `style` prop. The Calls SDK draws the call screen. The only UI Kit element is the loading spinner, which uses the theme's primary color.
+
+---
+
+### Functionality
+
+| Property | Description | Code |
+| --- | --- | --- |
+| **sessionID** | Session ID of the call. Required. | `sessionID: string` |
+| **callSettingsBuilder** | Settings for the call. Required. | `callSettingsBuilder: CometChatCalls.CallSettingsBuilder` |
+| **onError** | Called when the component cannot get a call token | `onError?: (e: CometChat.CometChatException) => void` |
+
+
+- `callSettingsBuilder` must be a `CometChatCalls.CallSettingsBuilder` instance, because the component calls its `build()` method. A plain settings object does not work.
+- The call uses the settings built on the component's first render. Passing a different builder later has no effect.
+
+
+### Advanced
+
+For advanced customization, UI Kit components accept custom views for parts of their UI. `CometChatOngoingCall` has no view slots, so it offers no customization beyond `callSettingsBuilder`.
+
+---
+
+## Common Patterns
+
+### Show the Ongoing Call After Accepting a Call
+
+Accept the call with the Chat SDK, then render the call screen for the accepted call. This mirrors what `CometChatIncomingCall` does by default.
+
+```tsx lines
+import { useState } from "react";
+import { Button } from "react-native";
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+
+function AcceptCall({ incomingCall }: { incomingCall: CometChat.Call }) {
+ const [activeCall, setActiveCall] = useState();
+
+ const accept = () => {
+ CometChat.acceptCall(incomingCall.getSessionId())
+ .then((accepted) => setActiveCall(accepted))
+ .catch(console.log);
+ };
+
+ if (activeCall) {
+ // OngoingCallScreen is the component from Integration
+ return setActiveCall(undefined)} />;
+ }
+
+ return ;
+}
+```
+
+### Configure Call Settings for a Video Call
+
+When you render `CometChatOngoingCall` yourself, also set the `OngoingCallListener` from [Integration](#integration).
+
+```tsx lines
+import { CometChatCalls } from "@cometchat/calls-sdk-react-native";
+
+const videoCallSettings = new CometChatCalls.CallSettingsBuilder()
+ .enableDefaultLayout(true)
+ .setIsAudioOnlyCall(false)
+ .setMode(CometChatCalls.CALL_MODE.SPOTLIGHT)
+ .showSwitchCameraButton(true)
+ .startWithVideoMuted(false);
+```
+
+### Audio-Only Call Configuration
+
+When you render `CometChatOngoingCall` yourself, also set the `OngoingCallListener` from [Integration](#integration).
+
+```tsx lines
+import { CometChatCalls } from "@cometchat/calls-sdk-react-native";
+
+const audioCallSettings = new CometChatCalls.CallSettingsBuilder()
+ .enableDefaultLayout(true)
+ .setIsAudioOnlyCall(true)
+ .setDefaultAudioMode(CometChatCalls.AUDIO_MODE.SPEAKER)
+ .showMuteAudioButton(true)
+ .showEndCallButton(true);
+```
+
+### Listen for Call End Events
+
+How you learn that a call ended depends on what renders the call screen:
+
+- **You render `CometChatOngoingCall`:** set `onCallEnded` on the builder's `OngoingCallListener`, as in [Integration](#integration).
+- **`CometChatIncomingCall` or `CometChatOutgoingCall` renders it:** listen for `ccCallEnded`, as in [Events](#events).
+
+### Use Your Own Settings with Incoming Call, Outgoing Call or Call Buttons
+
+These components take a builder for the call screen they open:
+
+| Component | Prop | Value |
+| --- | --- | --- |
+| `CometChatIncomingCall` | `callSettingsBuilder` | A `CometChatCalls.CallSettingsBuilder` instance |
+| `CometChatOutgoingCall` | `callSettingsBuilder` | A `CometChatCalls.CallSettingsBuilder` instance |
+| `CometChatCallButtons` | `callSettingsBuilder` | A function `(user, group, isAudioOnly)` that returns a builder, used for the outgoing call screen it opens |
+
+Two things differ from rendering `CometChatOngoingCall` yourself:
+
+- These components set their own `OngoingCallListener` on your builder, which replaces any listener you set. React to the call through their callbacks and [events](#events) instead.
+- Without a builder, they turn on the default layout and make audio calls audio-only. Your builder is used as it is, so set `enableDefaultLayout(true)` and `setIsAudioOnlyCall(...)` yourself.
+
+```tsx lines
+import { CometChat } from "@cometchat/chat-sdk-react-native";
+import { CometChatCalls } from "@cometchat/calls-sdk-react-native";
+import { CometChatCallButtons } from "@cometchat/chat-uikit-react-native";
+
+function CallButtonsWithSettings({ user }: { user: CometChat.User }) {
+ return (
+
+ new CometChatCalls.CallSettingsBuilder()
+ .enableDefaultLayout(true)
+ .setIsAudioOnlyCall(isAudioOnly ?? false)
+ .startWithAudioMuted(true)
+ }
+ />
+ );
+}
+```
+
+---
+
+## Next Steps
+
+
+
+ Display and handle incoming calls
+
+
+ Display and manage outgoing calls
+
+
+ Add voice and video call buttons to your UI
+
+
+ Overview of all calling features
+
+
diff --git a/ui-kit/react-native/react-native-cli-integration.mdx b/ui-kit/react-native/react-native-cli-integration.mdx
index 7271525c9..11b3dfbcf 100644
--- a/ui-kit/react-native/react-native-cli-integration.mdx
+++ b/ui-kit/react-native/react-native-cli-integration.mdx
@@ -126,14 +126,14 @@ allprojects {
Open `android/app/src/main/AndroidManifest.xml` and add:
```xml
-
-
```
+The UI Kit declares `READ_EXTERNAL_STORAGE` and `WRITE_EXTERNAL_STORAGE` in its own Android manifest, so you do not need to add them yourself.
+
### iOS: Add Modular Headers to the Podfile
diff --git a/ui-kit/react-native/search.mdx b/ui-kit/react-native/search.mdx
index 4c5ccbff8..9ff299524 100644
--- a/ui-kit/react-native/search.mdx
+++ b/ui-kit/react-native/search.mdx
@@ -231,9 +231,8 @@ To customize the appearance, you can pass a custom `style` prop to `CometChatSea
```tsx
import React from "react";
import { CometChatSearch } from "@cometchat/chat-uikit-react-native";
-import { SearchStyle } from "@cometchat/chat-uikit-react-native";
-const customSearchStyle: Partial = {
+const customSearchStyle: React.ComponentProps["style"] = {
containerStyle: {
backgroundColor: "#E8EAF6",
},