diff --git a/docs.json b/docs.json index 96952f214..2deaaeef0 100644 --- a/docs.json +++ b/docs.json @@ -1119,6 +1119,7 @@ "ui-kit/react-native/message-information", "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", @@ -1147,6 +1148,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..2b5c47f27 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()`, `getSystemPinMessageLimit()`, `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..45c3f3e6e 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()`, `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 | `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..64ef26030 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,35 @@ 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)} +/> +``` + + +The component fetches once, on mount. To fetch again (for example when the user opens another chat), give it a `key` that changes, such as the chat's UID or GUID. + + ## 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 +89,44 @@ 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`, but the component's `getSmartReplies` prop expects `Promise`. Map the result with `Object.values()` or no chips render. `CometChat.getConversationStarter()` needs no such mapping — it already returns `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)} +/> +``` + + +The component fetches once, on mount. To fetch again (for example when the user opens another chat), give it a `key` that changes, such as the chat's UID or GUID. + + ## 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 +161,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..b42d690de 100644 --- a/ui-kit/react-native/call-buttons.mdx +++ b/ui-kit/react-native/call-buttons.mdx @@ -22,7 +22,7 @@ description: "Add voice and video call buttons with CometChatCallButtons compone ## Where It Fits -`CometChatCallButtons` is a [Component](/ui-kit/react-native/components-overview#components) that 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. +`CometChatCallButtons` is a [Component](/ui-kit/react-native/components-overview#component-catalog) that 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. @@ -73,7 +73,7 @@ function CallButtonsWithError() { | Event | Fires when | Payload | | --- | --- | --- | -| `ccCallRejected` | Initiated call is rejected by the receiver | `{ call }` | +| `ccCallRejected` | The local user cancels the outgoing call before it is answered (not when the receiver rejects) | `{ call }` | | `ccCallFailed` | Error occurs during the initiated call | `{ call }` | | `ccOutgoingCall` | User initiates a voice/video call | `{ call }` | @@ -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 f9acd34d2..6e8929198 100644 --- a/ui-kit/react-native/compact-message-composer.mdx +++ b/ui-kit/react-native/compact-message-composer.mdx @@ -237,18 +237,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) ``` @@ -698,7 +698,7 @@ Using the `style` prop you can customize the look and feel of the component in y | `initialComposertext` | Set predefined text | `initialComposertext="Your custom text"` | | `placeHolderText` | Placeholder text for the input | `placeHolderText="Type a message..."` | | `customSoundForOutgoingMessage` | Custom sound for outgoing messages | `customSoundForOutgoingMessage="your-sound"` | -| `hideVoiceRecordingButton` | Hide voice recording option | `hideVoiceRecordingButton={true}` | +| `hideVoiceRecording` | Hide voice recording option | `hideVoiceRecording={true}` | | `hideCameraOption` | Hide camera option from attachments | `hideCameraOption={true}` | | `hideImageAttachmentOption` | Hide image attachment option | `hideImageAttachmentOption={true}` | | `hideVideoAttachmentOption` | Hide video attachment option | `hideVideoAttachmentOption={true}` | @@ -719,7 +719,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` | Hide the formatting toolbar; formatting stays available from the text selection menu | `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}` | @@ -727,24 +727,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..59d12322e 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 icons and icon styles (size, tint) 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..0df41931a 100644 --- a/ui-kit/react-native/components-overview.mdx +++ b/ui-kit/react-native/components-overview.mdx @@ -58,21 +58,28 @@ 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 | Component | Purpose | Key Props | Page | | --- | --- | --- | --- | -| CometChatCallButtons | Voice and video call initiation buttons | `user`, `group`, `onVoiceCallPress`, `onVideoCallPress` | [Call Buttons](/ui-kit/react-native/call-buttons) | +| CometChatCallButtons | Voice and video call initiation buttons | `user`, `group`, `hideVoiceCallButton`, `hideVideoCallButton` | [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) | -| CometChatCallLogs | Scrollable list of call history | `callLogsRequestBuilder`, `onItemPress` | [Call Logs](/ui-kit/react-native/call-logs) | +| CometChatOutgoingCall | Outgoing call screen with cancel control | `call`, `onEndCallButtonPressed` | [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 | `callLogRequestBuilder`, `onItemPress` | [Call Logs](/ui-kit/react-native/call-logs) | ### AI | 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/core-features.mdx b/ui-kit/react-native/core-features.mdx index d2ddfb96d..d227e757c 100644 --- a/ui-kit/react-native/core-features.mdx +++ b/ui-kit/react-native/core-features.mdx @@ -139,7 +139,7 @@ CometChat's Reactions feature adds a layer of expressiveness to your chat applic ## Mentions -Mentions is a feature that enhances the interactivity and clarity of group or 1-on-1 chats by allowing users to directly address or refer to specific individuals in a conversation. +Mentions is a feature that enhances the interactivity and clarity of group or 1-on-1 chats by allowing users to directly address or refer to specific individuals in a conversation. In group chats, users can also mention everyone at once with `@all` (the label can be changed with `mentionAllLabel` on the [Message Composer](/ui-kit/react-native/message-composer)). @@ -242,6 +242,8 @@ After implementing moderation rules, users can report messages they find inappro The Report Message feature allows users to report inappropriate or harmful messages within the chat. Users can choose from predefined reasons and provide additional remarks for detailed context. This feature helps maintain a safe and respectful chat environment. +The Report option appears only on messages sent by **other** users, never on your own, and is always hidden in conversations with an AI agent. It is also hidden when `hideFlagMessageOption` is set on the [Message List](/ui-kit/react-native/message-list), and the [Pinned Messages](/ui-kit/react-native/pinned-messages) panel does not currently offer it. To test it, long-press a message someone else sent. + Learn more about how flagged messages are handled, reviewed, and moderated in the [Flagged Messages](/moderation/flagged-messages) documentation. 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..5aab848ba --- /dev/null +++ b/ui-kit/react-native/custom-message-types.mdx @@ -0,0 +1,282 @@ +--- +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, or `return super.getId()` | 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 this.dataSource.getId()` (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, + CometChatUIKit, + ExtensionsDataSource, +} from "@cometchat/chat-uikit-react-native"; +// PollDataSource is the decorator from the example above. + +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", + // Spread the defaults: `extensions` replaces them, it does not add to them. + extensions: [...CometChatUIKit.defaultExtensions, new PollExtension()], +}); +``` + + +`extensions` **replaces** the built-in list. Passing only `[new PollExtension()]` turns off stickers, link preview, translation, polls, collaborative document and whiteboard, and thumbnail generation. Always spread `CometChatUIKit.defaultExtensions` first. + + +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..a8d3118a4 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`, `ccCallFailed` | +| 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,11 @@ 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. | +| ccMessageError | Triggers when the collaborative document or whiteboard extension fails to create its message, or when fetching stickers fails. Payload: the `CometChatException`. | +| ccMessagePinned / ccMessageUnpinned | Triggers when the user pins or unpins a message from the message list or the Pinned Messages panel. Payload: `{ message }`. | +| ccMessageSaved / ccMessageUnsaved | Triggers when the user saves or unsaves a message from the message list, Pinned Messages or Saved Messages. Payload: `{ message }`. | +| ccThreadSubscriptionChanged | Triggers when the user subscribes to or unsubscribes from a thread: on the optimistic change, on the server reply, and on a revert. Payload: `{ parentMessageId, subscribed, inProgress }`. | | 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 +101,36 @@ 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 | - -### CometChatUIEventListener +| 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 }`. | +| ccCallFailed | Triggers when a call cannot start or fails. Payload: `{ call }` from Call Buttons and Call Logs (call could not be placed); `{ error }` from Incoming Call and Outgoing Call (the call session failed). | + +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,8 +138,8 @@ 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`. | +| openChat | Triggers when the user picks "Message privately" on a group message. Emitted with `emitUIEvent`. Payload: `{ user }`. | --- 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/groups.mdx b/ui-kit/react-native/groups.mdx index c7a645b21..5518feb5a 100644 --- a/ui-kit/react-native/groups.mdx +++ b/ui-kit/react-native/groups.mdx @@ -14,7 +14,7 @@ description: "Searchable, scrollable list of all available groups with icon, nam | Primary output | `onItemPress(group)` — opens the selected group chat | | Other actions | `onItemLongPress` · `onBack` · `onSelection` · `onSubmit` · `onError` · `onEmpty` · `onLoad` — [details](#actions-and-events) | | View slots | `ItemView` · `LeadingView` · `TitleView` · `SubtitleView` · `TrailingView` · `LoadingView` · +3 more — [details](#custom-view-slots) | -| UI events | `ccGroupCreated` · `ccGroupDeleted` · `ccGroupLeft` · `ccGroupMemberScopeChanged` · `ccGroupMemberBanned` · `ccGroupMemberKicked` · `ccGroupMemberUnbanned` · `ccGroupMemberJoined` · `ccGroupMemberAdded` · `ccOwnershipChanged` | +| UI events | `ccGroupCreated` · `ccGroupDeleted` · `ccGroupLeft` · `ccGroupMemberScopeChanged` · `ccGroupMemberBanned` · `ccGroupMemberKicked` · `ccGroupMemberUnBanned` · `ccGroupMemberJoined` · `ccGroupMemberAdded` · `ccOwnershipChanged` | | Styling | `style` prop — [tokens and overrides](#styling) | | Prerequisites | `CometChatUIKit.init()` completed and a user logged in | | Stitching | onItemPress emits CometChat.Group -> pass to MessageHeader, MessageList, MessageComposer (with `CometChatMessageHeader` · `CometChatMessageList` · `CometChatMessageComposer`) | @@ -256,7 +256,7 @@ function GroupsWithLoadHandler() { | `ccGroupMemberScopeChanged` | The logged-in user changes scope of another member | `IGroupMemberScopeChanged` | | `ccGroupMemberBanned` | The logged-in user bans a group member | `IGroupMemberKickedBanned` | | `ccGroupMemberKicked` | The logged-in user kicks a group member | `IGroupMemberKickedBanned` | -| `ccGroupMemberUnbanned` | The logged-in user unbans a group member | `IGroupMemberUnBanned` | +| `ccGroupMemberUnBanned` | The logged-in user unbans a group member | `IGroupMemberUnBanned` | | `ccGroupMemberJoined` | The logged-in user joins a group | `IGroupMemberJoined` | | `ccGroupMemberAdded` | The logged-in user adds members to a group | `IGroupMemberAdded` | | `ccOwnershipChanged` | The logged-in user transfers group ownership | `IOwnershipChanged` | 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/guide-overview.mdx b/ui-kit/react-native/guide-overview.mdx index 33463da18..eed37a1ce 100644 --- a/ui-kit/react-native/guide-overview.mdx +++ b/ui-kit/react-native/guide-overview.mdx @@ -12,7 +12,7 @@ description: "Browse React Native UI Kit feature guides for chat layouts, Expo s | Purpose | Index of task-oriented feature guides for the React Native UI Kit | | Sample app | [GitHub](https://github.com/cometchat/cometchat-uikit-react-native/tree/v5/examples/SampleApp) | | Components | [Components Overview](/ui-kit/react-native/components-overview) | -| Guides | [AI Agent](/ui-kit/react-native/guide-ai-agent) · [New Chat](/ui-kit/react-native/guide-new-chat) · [Group Chat](/ui-kit/react-native/guide-group-chat) · [Threaded Messages](/ui-kit/react-native/guide-threaded-messages) · [Search Messages](/ui-kit/react-native/guide-search-messages) · [Block/Unblock](/ui-kit/react-native/guide-block-unblock-user) | +| Guides | [AI Agent](/ui-kit/react-native/guide-ai-agent) · [New Chat](/ui-kit/react-native/guide-new-chat) · [Group Chat](/ui-kit/react-native/guide-group-chat) · [Threaded Messages](/ui-kit/react-native/guide-threaded-messages) · [Search Messages](/ui-kit/react-native/guide-search-messages) · [Block/Unblock](/ui-kit/react-native/guide-block-unblock-user) · [Custom Message Types](/ui-kit/react-native/custom-message-types) | @@ -32,6 +32,7 @@ Use these guides after completing the base [Getting Started](/ui-kit/react-nativ | [Threaded Messages](/ui-kit/react-native/guide-threaded-messages) | Threaded replies: open parent context, list replies, compose within focused thread. | | [Search Messages](/ui-kit/react-native/guide-search-messages) | Add full‑text message search across conversations with result routing into context. | | [Block/Unblock User](/ui-kit/react-native/guide-block-unblock-user) | Let users block or unblock others in 1:1 chats; hides composer and shows an unblock prompt. | +| [Custom Message Types](/ui-kit/react-native/custom-message-types) | Render your own message type: a `DataSourceDecorator` with five overrides, registered after `login()` or through `uiKitSettings.extensions`. | | [Text Color](/ui-kit/react-native/guide-text-color) | Add a color button to the composer toolbar that colors selected text, rendered in the sent message. | | [Custom Text Formatter](/ui-kit/react-native/guide-custom-text-formatter) | Define your own color marker, write it from a toolbar button, and render it everywhere the message appears. | | [Text Formatters](/ui-kit/react-native/custom-text-formatter-guide) | Extend the base formatter to implement custom inline patterns (hashtags, keywords) with regex + callbacks. | diff --git a/ui-kit/react-native/llms-react-native-v5.mdx b/ui-kit/react-native/llms-react-native-v5.mdx index 0e0233d05..08f121abe 100644 --- a/ui-kit/react-native/llms-react-native-v5.mdx +++ b/ui-kit/react-native/llms-react-native-v5.mdx @@ -36,15 +36,14 @@ This kit renders **native views**, not DOM. Code that works in the React UI Kit - **No CSS, no `className`, no `
`/``, no `document.*`/`window.*`.** Styling is `StyleSheet` objects and the theme API — see [Theming](/ui-kit/react-native/theme). - **Native peer deps are required**, not optional. Verified against - `@cometchat/chat-uikit-react-native@5.4.0`: `@cometchat/chat-sdk-react-native`, - `@react-native-clipboard/clipboard`, `@react-native-community/datetimepicker`, - `react-native-gesture-handler`, `react-native-svg`, `react-native-video`, - `react-native-localize`, `react-native-safe-area-context`, - `@react-native-async-storage/async-storage`, `dayjs` (+ `punycode` on Expo). Install and + `@cometchat/chat-uikit-react-native@5.5.2`: `@cometchat/chat-sdk-react-native`, + `@react-native-clipboard/clipboard`, `react-native-gesture-handler`, `react-native-svg`, + `react-native-video`, `react-native-localize`, `react-native-safe-area-context` + (+ `punycode` on Expo). Install and pod-install them before first render; a missing native module fails at mount, not at build. Take the exact list from the integration page — do not infer it. - **Android + async-storage v3 needs an extra Gradle line.** `@react-native-async-storage/async-storage` - v3 ships a local Maven artifact; without the `local_repo` entry in `android/build.gradle` the + is required by the Chat SDK (not a UI Kit peer as of 5.5.2). Its v3 ships a local Maven artifact; without the `local_repo` entry in `android/build.gradle` the Android build fails. See the integration page. - **One screen per route.** Use a stack navigator and a real hardware/gesture back button — do not stack components on a single screen the way a web layout would. @@ -52,7 +51,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 +117,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` + or calling `super.getId()` throws `Method not implemented.` at registration, while returning + `this.dataSource.getId()` 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 +131,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..12ce4544a 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 @@ -522,8 +607,8 @@ Using Style you can customize the look and feel of the component in your app. Th | `hideSendButton` | Hide send button | `hideSendButton={true}` | | `hideAuxiliaryButtons` | Hide auxiliary buttons | `hideAuxiliaryButtons={true}` | | `disableMentions` | Disable mentions functionality | `disableMentions={true}` | -| `disableMentionAll` | Disable @all mention | `disableMentionAll={true}` | -| `mentionAllLabel` | Custom label for @all mention | `mentionAllLabel="everyone"` | +| `disableMentionAll` | Hide the @all suggestion. @all is offered only in group conversations; no effect when `disableMentions` is true | `disableMentionAll={true}` | +| `mentionAllLabel` | Custom label for @all, without the leading `@` (default `all`). Group conversations only; no effect when `disableMentions` is true | `mentionAllLabel="everyone"` | | `imageQuality` | Image quality for camera (1-100) | `imageQuality={50}` | | `auxiliaryButtonsAlignment` | Alignment of auxiliary buttons | `auxiliaryButtonsAlignment="right"` | diff --git a/ui-kit/react-native/message-list.mdx b/ui-kit/react-native/message-list.mdx index ccfe01e7a..7e874a3cb 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": { @@ -103,12 +103,11 @@ description: "Display sent and received messages with text, media, reactions, re } }, "events": [ - { "name": "openChat", "payload": "{ user, group }", "description": "User opens a chat" }, + { "name": "openChat", "payload": "{ user }", "description": "User picks \"Message privately\" on a group message" }, { "name": "ccMessageEdited", "payload": "{ message }", "description": "Message edited by logged-in user" }, { "name": "ccMessageDeleted", "payload": "{ message }", "description": "Message deleted by logged-in user" }, { "name": "ccActiveChatChanged", "payload": "chat details", "description": "User navigates to a different chat" }, - { "name": "ccMessageRead", "payload": "{ message }", "description": "Message read by logged-in user" }, - { "name": "ccMessageDelivered", "payload": "{ message }", "description": "Messages marked as delivered" } + { "name": "ccMessageRead", "payload": "{ message }", "description": "Message read by logged-in user" } ], "sdkListeners": [ "onTextMessageReceived", "onMediaMessageReceived", "onCustomMessageReceived", @@ -238,15 +237,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()` — @@ -378,12 +385,11 @@ function MessageListWithLoadHandler() { | Event | Fires when | Payload | | --- | --- | --- | -| `openChat` | User opens a user or group chat | `{ user, group }` | +| `openChat` | User picks "Message privately" on a group message | `{ user }` | | `ccMessageEdited` | Message edited by logged-in user | `{ message }` | | `ccMessageDeleted` | Message deleted by logged-in user | `{ message }` | | `ccActiveChatChanged` | User navigates to a different chat | `chat details` | | `ccMessageRead` | Message read by logged-in user | `{ message }` | -| `ccMessageDelivered` | Messages marked as delivered | `{ message }` | ```tsx lines import { useEffect } from "react"; @@ -395,8 +401,8 @@ function useMessageListEvents() { const messageListenerId = "MESSAGE_LISTENER_" + Date.now(); CometChatUIEventHandler.addUIListener(uiListenerId, { - openChat: ({ user, group }) => { - console.log("Chat opened:", user || group); + openChat: ({ user }) => { + console.log("Message privately:", user.getName()); }, }); @@ -705,6 +711,116 @@ 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` | `DeepPartial` | **Not** merged over the theme: the component reads `style` directly, so without it the pills render unstyled. Pass the same styles the message list uses, `theme.messageListStyles.outgoingMessageBubbleStyles.reactionStyles` (or `incomingMessageBubbleStyles.reactionStyles`), spreading your overrides over it. The root `theme.messageBubbleReactionStyles` is not set by the default theme. | + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-react-native"; +import { CometChatReactions, useTheme } from "@cometchat/chat-uikit-react-native"; + +function MyReactions({ message }: { message: CometChat.BaseMessage }) { + const theme = useTheme(); + return ( + 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)} +/> +``` + +Where each one is styled: + +| Component | Theme key | Where it is documented | +| --- | --- | --- | +| `CometChatReactions` (pills under a bubble) | `reactionStyles` on `incomingMessageBubbleStyles` / `outgoingMessageBubbleStyles` | [Message Bubble Styling](/ui-kit/react-native/message-bubble-styling) | +| `CometChatQuickReactions` (row in the long-press sheet) | `quickReactionStyle`: `containerStyle`, `emojiContainerStyle` | Below | +| `CometChatReactionList` (who reacted) | `reactionListStyles` | [Component Styling](/ui-kit/react-native/component-styling) | + +`quickReactionStyle` is set on the theme like any other key, and a component's `style` prop is merged over it: + +```tsx lines + + {/* your app */} + +``` + +--- + ## Common Patterns ### Threaded message list @@ -1389,12 +1505,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..d80a47cc7 --- /dev/null +++ b/ui-kit/react-native/ongoing-call.mdx @@ -0,0 +1,359 @@ +--- +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.leaveSession(); // Calls SDK 4.x: 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 ( + + ); +} +``` + + +Keep `onError` stable (wrap it in `useCallback`, as above). The token request re-runs whenever `sessionID` or `onError` changes, and its cleanup clears the built call settings. A new `onError` function on every render therefore restarts the request and leaves the loading spinner on screen for good. React StrictMode in development runs that cleanup once on mount, which shows the same spinner. + + +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( + new CometChatCalls.OngoingCallListener({ + onCallEnded: () => { + CometChatCalls.leaveSession(); // Calls SDK 4.x: endSession() + }, + }) + ); + +; +``` + + +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 UI Kit wraps it in a safe-area container (top and bottom edges) filled with the theme's `background1` color, and shows a loading spinner in the theme's primary color until the call is ready. + +--- + +### 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