From 59bac32276382c6a43f5c1117c2a1cd2b3eb106b Mon Sep 17 00:00:00 2001 From: Suraj Chauhan Date: Wed, 16 Sep 2026 15:48:58 +0530 Subject: [PATCH 01/11] fix(rn): stop four UI Kit pages importing symbols the kit does not export ENG-39166. Five imports on four React Native pages named symbols that @cometchat/chat-uikit-react-native does not export from its package root, so copied snippets failed with TS2305 (and EnterKeyBehavior, used as a value, was undefined at runtime). Each is now fixed with a docs-only change that uses the kit's public API as it ships today. call-buttons OutgoingCallConfiguration is not exported. outgoingCallConfiguration is spread straight into the outgoing call component, so a plain object satisfies it. This is also more correct than the class it replaces: that class's constructor copies only 3 of its 9 fields and silently drops the rest. compact-message-composer - EnterKeyBehavior is not exported by name, but it is public through the exported CometChatUiKitConstants namespace. All four references (two in the example, one in the props table) now use CometChatUiKitConstants.EnterKeyBehavior.*. A plain "sendMessage" string does not work: string enums are nominal, so it fails with TS2322. - Removed the "Configuration" section. It built a SingleLineMessageComposerConfiguration that no v5 component accepts and never used it. Every option it showed is already a direct prop in the props table (hideVoiceRecording is an alias of the documented hideVoiceRecordingButton). Nothing linked to the section. component-styling CometChatReceipt is not exported, and the snippet also used CometChatUiKitConstants without importing it. The theme override is now shown on CometChatConversations. It is deliberately not shown on CometChatMessageList: message bubbles pass their own receipt style, which wins the merge, so a top-level receiptStyles override does not change them. Run against the kit's default light theme and its real deepMerge, the read-receipt tint resolves to the override (#FFAB00) for Conversations and stays at the bubble default (#09C26F) for MessageList. The prose now says exactly that. search SearchStyle was imported only as a type annotation. The type is now derived from the component (React.ComponentProps["style"]), which also corrects Partial<> to the prop's real DeepPartial<>. Verified: every edited code block was extracted from the page and compiled against the published kit; deliberately broken copies (a misspelled theme key, enum member and component name) fail, so the checks are live. MDX fences and tags remain balanced on all four pages. Rendered behaviour was confirmed by the reporter on device before commit. Co-Authored-By: Claude Opus 5 --- ui-kit/react-native/call-buttons.mdx | 17 ++++-------- .../react-native/compact-message-composer.mdx | 26 +++---------------- ui-kit/react-native/component-styling.mdx | 10 +++---- ui-kit/react-native/search.mdx | 3 +-- 4 files changed, 13 insertions(+), 43 deletions(-) diff --git a/ui-kit/react-native/call-buttons.mdx b/ui-kit/react-native/call-buttons.mdx index 17bc81534..4dae0e982 100644 --- a/ui-kit/react-native/call-buttons.mdx +++ b/ui-kit/react-native/call-buttons.mdx @@ -165,28 +165,21 @@ function StylingDemo() { You can customize the properties of the Outgoing Call component by making use of the `outgoingCallConfiguration` prop: ```tsx lines -import { - CometChatCallButtons, - OutgoingCallConfiguration, -} from "@cometchat/chat-uikit-react-native"; +import { CometChatCallButtons } from "@cometchat/chat-uikit-react-native"; function OutgoingCallConfigDemo() { - const getOutgoingCallConfig = () => { - return new OutgoingCallConfiguration({ - disableSoundForCalls: true, - }); - }; - return ( ); } ``` -All exposed properties of `OutgoingCallConfiguration` can be found under [Outgoing Call](/ui-kit/react-native/outgoing-call). +All properties accepted by `outgoingCallConfiguration` can be found under [Outgoing Call](/ui-kit/react-native/outgoing-call). --- diff --git a/ui-kit/react-native/compact-message-composer.mdx b/ui-kit/react-native/compact-message-composer.mdx index b5d14c6a2..dbfca6e4f 100644 --- a/ui-kit/react-native/compact-message-composer.mdx +++ b/ui-kit/react-native/compact-message-composer.mdx @@ -233,18 +233,18 @@ On React Native, the `showTextSelectionMenuItems` prop controls whether Bold, It The `enterKeyBehavior` prop controls what happens when the Enter key is pressed on Android. On iOS, Enter always inserts a new line. ```tsx lines -import { CometChatCompactMessageComposer, EnterKeyBehavior } from "@cometchat/chat-uikit-react-native"; +import { CometChatCompactMessageComposer, CometChatUiKitConstants } from "@cometchat/chat-uikit-react-native"; // Send message on Enter (Android) // New line on Enter (default) ``` @@ -647,7 +647,7 @@ Using the `style` prop you can customize the look and feel of the component in y | `enableRichTextEditor` | Enable/disable rich text formatting | `enableRichTextEditor={true}` | | `hideRichTextFormattingOptions` | Always-visible toolbar mode | `hideRichTextFormattingOptions={true}` | | `showTextSelectionMenuItems` | Formatting in native text selection menu | `showTextSelectionMenuItems={true}` | -| `enterKeyBehavior` | Android Enter key behavior | `enterKeyBehavior={EnterKeyBehavior.SendMessage}` | +| `enterKeyBehavior` | Android Enter key behavior | `enterKeyBehavior={CometChatUiKitConstants.EnterKeyBehavior.SendMessage}` | | `maxLines` | Maximum lines before scrolling | `maxLines={3}` | | `minInputHeight` | Minimum input height in pixels | `minInputHeight={36}` | | `maxInputHeight` | Maximum input height in pixels | `maxInputHeight={120}` | @@ -655,24 +655,6 @@ Using the `style` prop you can customize the look and feel of the component in y --- -## Configuration - -`SingleLineMessageComposerConfiguration` can be used to pass configuration when embedding the CompactMessageComposer inside other components: - -```tsx lines -import { SingleLineMessageComposerConfiguration } from "@cometchat/chat-uikit-react-native"; - -const config = new SingleLineMessageComposerConfiguration({ - disableTypingEvents: true, - hideVoiceRecording: true, - disableMentions: false, - maxLines: 3, - placeHolderText: "Write something...", -}); -``` - ---- - ## Next Steps diff --git a/ui-kit/react-native/component-styling.mdx b/ui-kit/react-native/component-styling.mdx index 2865331f8..a3e13ebde 100644 --- a/ui-kit/react-native/component-styling.mdx +++ b/ui-kit/react-native/component-styling.mdx @@ -1374,7 +1374,7 @@ To learn more about such attributes, refer to the [theme interface](https://gith ### Receipts -The `CometChatReceipts` component indicates message delivery and read statuses using intuitive icons. These can be styled for icon size, tint, and alignment, ensuring they remain clear and consistent with your app's UI. +Message receipts indicate delivery and read statuses using intuitive icons. The theme's `receiptStyles` controls their icon size, tint, and alignment wherever a component renders receipts without its own style — for example the last-message receipt in `CometChatConversations`, shown below. Message bubbles in `CometChatMessageList` apply their own receipt styles, so this top-level override does not change them. @@ -1382,7 +1382,7 @@ The `CometChatReceipts` component indicates message delivery and read statuses u ```javascript import { - CometChatReceipt, + CometChatConversations, CometChatThemeProvider, } from "@cometchat/chat-uikit-react-native"; import { SafeAreaView } from "react-native-safe-area-context"; @@ -1403,11 +1403,7 @@ return ( }, }} > - {loggedIn && ( - - )} + {loggedIn && } ); diff --git a/ui-kit/react-native/search.mdx b/ui-kit/react-native/search.mdx index 4c5ccbff8..9ff299524 100644 --- a/ui-kit/react-native/search.mdx +++ b/ui-kit/react-native/search.mdx @@ -231,9 +231,8 @@ To customize the appearance, you can pass a custom `style` prop to `CometChatSea ```tsx import React from "react"; import { CometChatSearch } from "@cometchat/chat-uikit-react-native"; -import { SearchStyle } from "@cometchat/chat-uikit-react-native"; -const customSearchStyle: Partial = { +const customSearchStyle: React.ComponentProps["style"] = { containerStyle: { backgroundColor: "#E8EAF6", }, From a0aae25a8f83d0509b6b640a57ebe8aa23266359 Mon Sep 17 00:00:00 2001 From: Suraj Chauhan Date: Wed, 16 Sep 2026 16:14:00 +0530 Subject: [PATCH 02/11] fix(rn): correct the events page to names the UI Kit actually emits ENG-39167. The React Native events page listed names the kit never emits, so a listener copied from it silently never fired. Every name on the corrected page was checked against the kit source. Names ccUserUnblocked -> ccUserUnBlocked (kit spelling, capital B) ccGroupMemberUnbanned -> ccGroupMemberUnBanned ccLiveReaction -> removed; no such event exists Call events onIncomingCallAccepted -> ccCallAccepted onIncomingCallRejected -> ccCallRejected onCallEnded -> ccCallEnded onCallInitiated -> ccOutgoingCall. ccCallInitiated is declared but never emitted; ccOutgoingCall is what fires after CometChat.initiateCall() succeeds. onOutgoingCallAccepted/Rejected -> removed. ccOutgoingCallAccepted and ccOutgoingCallRejected are declared but never emitted. The page now points to the Chat SDK's call listener, where these callbacks do exist. Handlers receive { call }, not a bare call. Two descriptions were also wrong: ccCallRejected fires when the user cancels their own outgoing call as well as when they reject an incoming one, and ccCallEnded is emitted with no call when an answered call ends. Structure ccActiveChatChanged moved from UI events to message events: it is declared on the message listener and only fires through addMessageListener. The "CometChatUIEventListener" heading is renamed "UI Events"; no such symbol exists in the kit. Verified - All 39 names on the page type-check on the listener their section belongs to; a known-wrong name fails, so the check is live. - All 39 reach an inline listener through the real CometChatUIEventHandler dispatcher (39/39), and each has at least one emit site in the kit. - The SDK example compiles. CallListener does not key-check its argument, so the callback names were confirmed against the SDK's CallListener class and five shipped kit call sites, including CometChatOutgoingCall. - Rendered in a local Mintlify preview; confirmed by the reporter. Not addressed here: listeners whose handler is a named function never fire even with the correct name, because the dispatcher matches on the function's .name. That is a kit defect, tracked separately as ENG-39300. Co-Authored-By: Claude Opus 5 --- ui-kit/react-native/events.mdx | 54 ++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/ui-kit/react-native/events.mdx b/ui-kit/react-native/events.mdx index 1db317b8e..3ec0baefc 100644 --- a/ui-kit/react-native/events.mdx +++ b/ui-kit/react-native/events.mdx @@ -10,11 +10,11 @@ description: "Listen to UI Kit events for conversations, users, groups, messages | Package | `@cometchat/chat-uikit-react-native` | | Import | `import { CometChatUIEventHandler } from "@cometchat/chat-uikit-react-native";` | | Conversation events | `ccConversationDeleted`, `ccUpdateConversation` | -| User events | `ccUserBlocked`, `ccUserUnblocked` | -| Group events | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnbanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` | -| Message events | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccLiveReaction`, plus SDK listener events | -| Call events | `onIncomingCallAccepted`, `onIncomingCallRejected`, `onCallEnded`, `onCallInitiated`, `onOutgoingCallAccepted`, `onOutgoingCallRejected` | -| UI events | `ccActiveChatChanged`, `ccCardActionClicked` | +| User events | `ccUserBlocked`, `ccUserUnBlocked` | +| Group events | `ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberUnBanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged` | +| Message events | `ccMessageSent`, `ccMessageEdited`, `ccMessageDeleted`, `ccMessageRead`, `ccActiveChatChanged`, plus SDK listener events | +| Call events | `ccCallAccepted`, `ccCallRejected`, `ccCallEnded`, `ccOutgoingCall` | +| UI events | `ccCardActionClicked` | | Purpose | Decoupled communication between UI Kit components — subscribe to events to react to changes without direct component references | @@ -41,7 +41,7 @@ It consists of the following events: | Name | Description | | --------------- | ------------------------------------------------------------------------- | | ccUserBlocked | This event is triggered when the user successfully blocks another user. | -| ccUserUnblocked | This event is triggered when the user successfully unblocks another user. | +| ccUserUnBlocked | This event is triggered when the user successfully unblocks another user. | ### CometChatGroupsEvents @@ -57,7 +57,7 @@ It consists of the following events: | ccGroupMemberScopeChanged | This event is triggered when the group member's scope is updated successfully | | ccGroupMemberKicked | This event is triggered when the group member is kicked | | ccGroupMemberBanned | This event is triggered when the group member is banned | -| ccGroupMemberUnbanned | This event is triggered when the group member is un-banned | +| ccGroupMemberUnBanned | This event is triggered when the group member is un-banned | | ccGroupMemberJoined | This event is triggered when a user joins the group | | ccGroupMemberAdded | This event is triggered when a user is added to the group | | ccOwnershipChanged | This event is triggered when the group ownership is assigned to another group member | @@ -74,7 +74,7 @@ It consists of the following events: | ccMessageEdited | This event is triggered when the user successfully edits the message. | | ccMessageDeleted | This event is triggered when the user successfully deletes the message. | | ccMessageRead | This event is triggered when the sent message is read by the receiver. | -| ccLiveReaction | This event is triggered when the user sends a live reaction. | +| ccActiveChatChanged | This event is triggered when the user navigates to a particular chat window. | | onTextMessageReceived | This event is emitted when the CometChat SDK listener emits a text message. | | onMediaMessageReceived | This event is emitted when the CometChat SDK listener emits a media message. | | onCustomMessageReceived | This event is emitted when the CometChat SDK listener emits a custom message. | @@ -97,16 +97,35 @@ It consists of the following events: It consists of the following events: -| Name | Description | -| ------------------------------------------- | ------------------------------------------------------- | -| **func** onIncomingCallAccepted(call: Call) | Triggers whenever incoming call is accepted by the user | -| **func** onIncomingCallRejected(call: Call) | Triggers whenever incoming call is rejected by the user | -| **func** onCallEnded(call: Call) | Triggers whenever the call is ended | -| **func** onCallInitiated(call: Call) | Triggers whenever the call is getting initiated | -| **func** onOutgoingCallAccepted(call: Call) | Triggers whenever outgoing call is accepted by the user | -| **func** onOutgoingCallRejected(call: Call) | Triggers whenever outgoing call is rejected by the user | +| Name | Description | +| -------------- | ------------------------------------------------------------------------------------------------------------------------ | +| ccCallAccepted | Triggers when the user accepts an incoming call. Payload: `{ call }`. | +| ccCallRejected | Triggers when the user rejects an incoming call, or cancels an outgoing call before it is answered. Payload: `{ call }`. | +| ccCallEnded | Triggers when a call ends. Payload: `{ call }`; `call` can be undefined. | +| ccOutgoingCall | Triggers when the user places a call. Payload: `{ call }`. | -### CometChatUIEventListener +Outgoing-call **accepted** and **rejected** are not UI Kit events — the UI Kit never emits them. Listen for them on the Chat SDK's call listener instead: + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-react-native"; + +CometChat.addCallListener( + "OUTGOING_CALL_LISTENER", + new CometChat.CallListener({ + onOutgoingCallAccepted: (call: CometChat.Call) => { + // the callee accepted + }, + onOutgoingCallRejected: (call: CometChat.Call) => { + // the callee rejected + }, + }) +); + +// Remove it when you no longer need it, e.g. when the screen unmounts +CometChat.removeCallListener("OUTGOING_CALL_LISTENER"); +``` + +### UI Events UI events refer to actions or interactions performed by a user within the CometChat UI Kit. These events are triggered when a user interacts with various UI elements, such as buttons, menus, checkboxes, input fields, or any other interactive components. @@ -114,7 +133,6 @@ It consists of the following events: | Name | Description | | ------------------- | ---------------------------------------------------------------------------- | -| ccActiveChatChanged | This event is triggered when the user navigates to a particular chat window. | | ccCardActionClicked | This event is triggered when the user clicks an action on a card message bubble. The event payload contains the `message` and the clicked `action`. | From aaa21c0f070d9115ad5f61526aceb8510db18bb7 Mon Sep 17 00:00:00 2001 From: Suraj Chauhan Date: Wed, 16 Sep 2026 16:25:37 +0530 Subject: [PATCH 03/11] fix(rn): document how to undo a ban from the group members list ENG-39170 (ban round trip). CometChatGroupMembers gives owners, admins and moderators a Ban option by default, but the UI Kit ships no screen to list banned members or unban them, and the group chat guide never said so. It listed banGroupMember() in its feature matrix with no unban counterpart, and described the members list as offering only "scope changes and removal". A reader following the guide could ban a member and find no documented way back. The round trip is already documented, and correct, on the Chat SDK page sdk/react-native/group-kick-ban-members; the guide simply never pointed to it. guide-group-chat - Section 4 now says what the menu offers and to whom: owners, admins and moderators can change scope, remove, or ban (RolePermissions in CometChatGroupMembers; participants get no actions). - A note after the section 4 example states the UI Kit has no banned-members or unban screen, links to the SDK sections for listing banned members (BannedMembersRequestBuilder) and unbanning (unbanGroupMember), and to hideBanMemberOption for removing the Ban option instead. - The feature matrix gains "Unban member" and "List banned members". Verified - The kit on dev-v5 has no unbanGroupMember or BannedMembersRequestBuilder usage and exports no banned-members component. - The SDK page's ban, unban and banned-members TypeScript examples compile against the Chat SDK; misspelled copies of both APIs fail, so the check is live. - All three new links resolve in a local Mintlify preview: the two SDK anchors exist on the rendered page, and group-members renders the hideBanMemberOption row. Confirmed by the reporter. Not in this change: a details-screen recipe and replacement guidance in the upgrade guide (ENG-39170 items 2 and 3) are left as follow-ups. Co-Authored-By: Claude Opus 5 --- ui-kit/react-native/guide-group-chat.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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` | From af86495031d34cca68846939debb3c0b95388f5a Mon Sep 17 00:00:00 2001 From: Suraj Chauhan Date: Wed, 16 Sep 2026 17:45:38 +0530 Subject: [PATCH 04/11] fix(rn): add the missing Ongoing Call page for CometChatOngoingCall ENG-39171. The kit exports CometChatOngoingCall, the in-call screen, but the React Native v5 docs had no page for it: ui-kit/react-native/ongoing-call has never existed (only the v4 page does), and the live URL redirects to the docs home. iOS and Vue have current Ongoing Call pages; the new page follows the iOS structure (Usage, Customization, Common Patterns), since Vue's is an older props-only page. It uses React Native code and documents only what the RN kit supports. ongoing-call (new) - Integration: render it with a session ID and a CallSettingsBuilder whose OngoingCallListener ends the session, mirroring CometChatIncomingCall. Incoming and Outgoing Call normally render it for you. - Actions: onError is the only callback. It fires when the component cannot get a call token; a plain Error arrives as a CometChatException with code TOKEN_GENERATION_FAILED, and SDK exceptions pass through unchanged. - Filters: the CallSettingsBuilder methods and defaults, taken from the Calls SDK typings; the three methods the SDK marks obsolete are left out. - Events: the component emits none. ccCallEnded comes only from Incoming and Outgoing Call. - Customization: no style prop and no view slots; the loading spinner uses the theme's primary color. The builder must be an instance (its build() is called), and only the settings built on the first render are used. - Common Patterns: accepting a call, video and audio-only settings, call-end handling, and passing a builder to Incoming Call, Outgoing Call or Call Buttons. Given a builder, those components set their own OngoingCallListener on it and skip their default layout and audio-only settings. docs.json Adds the page to the React Native nav after Outgoing Call, as on iOS. components-overview Adds CometChatOngoingCall to the Calling catalog. Verified - The component's source is identical in kit 5.4.0 and 5.5.0, and the builder props on Incoming Call, Outgoing Call and Call Buttons are unchanged. - All 8 code blocks compile against kit 5.4.0, Chat SDK 4.0.28 and Calls SDK 5.0.5 under strict TypeScript. A misspelled copy of each fails, and a control file with a deliberate error confirms the checker ran. - Runtime claims ran in Jest against the real component with the SDKs mocked: spinner then call view, full-size root view, the onError codes, first-render settings kept, a plain settings object throws, and the spinner color. - Rendered in a local Mintlify preview: the section structure matches the iOS page, and all 28 links and anchors resolve. Confirmed by the reporter. Not verified: the end-of-call steps in a live call on a device. Not in this change: an onError function that changes between renders, such as an inline arrow, makes the component request a new call token and fall back to the spinner (reproduced in Jest). That is a kit defect, not documented here as intended behavior. Co-Authored-By: Claude Opus 5 --- docs.json | 1 + ui-kit/react-native/components-overview.mdx | 1 + ui-kit/react-native/ongoing-call.mdx | 347 ++++++++++++++++++++ 3 files changed, 349 insertions(+) create mode 100644 ui-kit/react-native/ongoing-call.mdx diff --git a/docs.json b/docs.json index 035cebab9..0c28032c2 100644 --- a/docs.json +++ b/docs.json @@ -1186,6 +1186,7 @@ "ui-kit/react-native/threaded-messages-header", "ui-kit/react-native/incoming-call", "ui-kit/react-native/outgoing-call", + "ui-kit/react-native/ongoing-call", "ui-kit/react-native/call-buttons", "ui-kit/react-native/call-logs", "ui-kit/react-native/ai-assistant-chat-history", diff --git a/ui-kit/react-native/components-overview.mdx b/ui-kit/react-native/components-overview.mdx index d2cffa3fd..80639b92f 100644 --- a/ui-kit/react-native/components-overview.mdx +++ b/ui-kit/react-native/components-overview.mdx @@ -66,6 +66,7 @@ All components are imported from `@cometchat/chat-uikit-react-native`. | CometChatCallButtons | Voice and video call initiation buttons | `user`, `group`, `onVoiceCallPress`, `onVideoCallPress` | [Call Buttons](/ui-kit/react-native/call-buttons) | | CometChatIncomingCall | Incoming call notification with accept/decline | `call`, `onAccept`, `onDecline` | [Incoming Call](/ui-kit/react-native/incoming-call) | | CometChatOutgoingCall | Outgoing call screen with cancel control | `call`, `onClosePress` | [Outgoing Call](/ui-kit/react-native/outgoing-call) | +| CometChatOngoingCall | In-call screen for an active voice or video call | `sessionID`, `callSettingsBuilder` | [Ongoing Call](/ui-kit/react-native/ongoing-call) | | CometChatCallLogs | Scrollable list of call history | `callLogsRequestBuilder`, `onItemPress` | [Call Logs](/ui-kit/react-native/call-logs) | ### AI diff --git a/ui-kit/react-native/ongoing-call.mdx b/ui-kit/react-native/ongoing-call.mdx new file mode 100644 index 000000000..a5a8a3bb9 --- /dev/null +++ b/ui-kit/react-native/ongoing-call.mdx @@ -0,0 +1,347 @@ +--- +title: "Ongoing Call" +description: "Display the React Native UI Kit in-call screen for voice and video calls with CometChatOngoingCall, configured through the Calls SDK call settings builder." +--- + +The `CometChatOngoingCall` component shows the screen users see during a voice or video call. It requests a call token for the session, then renders the Calls SDK call view, with video tiles and call controls such as mute, pause video, switch camera, and end call. Until the token arrives, it shows a loading spinner. + + + +| Field | Value | +| --- | --- | +| Component | `CometChatOngoingCall` | +| Package | `@cometchat/chat-uikit-react-native` | +| Import | `import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native";` | +| Purpose | In-call screen for an active voice or video call. Gets a call token for the session and renders the Calls SDK call view. | +| Data props | `sessionID` · `callSettingsBuilder` (both required) | +| Primary output | None on the component — call events arrive on the `OngoingCallListener` set on `callSettingsBuilder` | +| Other actions | `onError` — [details](#actions) | +| View slots | None | +| UI events | None of its own — [details](#events) | +| Styling | No `style` prop — [details](#style) | +| Prerequisites | `CometChatUIKit.init()` completed and a user logged in · `@cometchat/calls-sdk-react-native` installed (**not** a kit peer dependency) | + + + +--- + +## Usage + +### Integration + +`CometChatIncomingCall` and `CometChatOutgoingCall` render `CometChatOngoingCall` for you once a call connects, so most apps never render it directly. Render it yourself when you build your own call flow. + +Pass the call's session ID and a `CometChatCalls.CallSettingsBuilder`. Set an `OngoingCallListener` on the builder so your app knows when the call ends. + +```tsx lines +import { useMemo } from "react"; +import { CometChat } from "@cometchat/chat-sdk-react-native"; +import { CometChatCalls } from "@cometchat/calls-sdk-react-native"; +import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native"; + +function OngoingCallScreen({ call, onCallEnd }: { call: CometChat.Call; onCallEnd: () => void }) { + const callSettingsBuilder = useMemo( + () => + new CometChatCalls.CallSettingsBuilder() + .enableDefaultLayout(true) + .setIsAudioOnlyCall(call.getType() === "audio") + .setCallEventListener( + new CometChatCalls.OngoingCallListener({ + onCallEndButtonPressed: () => { + CometChat.endCall(call.getSessionId()).catch(console.log); + }, + onCallEnded: () => { + CometChatCalls.endSession(); + CometChat.clearActiveCall(); + onCallEnd(); + }, + }) + ), + [call] + ); + + return ( + + ); +} +``` + +This listener takes the same steps as `CometChatIncomingCall` when a call ends. + + +The component fills its parent, so render it full screen, for example inside a React Native `Modal` as `CometChatOutgoingCall` does. + + +### Actions + +[Actions](/ui-kit/react-native/components-overview#actions) dictate how a component functions. `CometChatOngoingCall` has one user-defined action. + +#### 1. onError + +Fires when the component cannot get a call token: no user is logged in, or `CometChat.getLoggedinUser()` or `CometChatCalls.generateToken()` fails. A plain JavaScript `Error`, such as the one for no logged-in user, arrives as a `CometChatException` with the code `TOKEN_GENERATION_FAILED`. + +```tsx lines +import { useCallback } from "react"; +import { CometChat } from "@cometchat/chat-sdk-react-native"; +import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native"; + +function OngoingCallWithError() { + const handleError = useCallback((error: CometChat.CometChatException) => { + console.error("OngoingCall error:", error); + }, []); + + return ( + + ); +} +``` + +Errors during the call are not sent to this prop. They go to the `onError` handler of the `OngoingCallListener` on your builder. + +`CometChatOngoingCall` has no call-ended action. To act when the call ends, set `onCallEnded` on the builder's `OngoingCallListener`, as shown in [Integration](#integration). + +--- + +### Filters + +[Filters](/ui-kit/react-native/components-overview#filters) narrow the data a component shows. `CometChatOngoingCall` shows no list. Instead, `callSettingsBuilder` controls the call itself. + +#### 1. CallSettingsBuilder + +`CometChatCalls.CallSettingsBuilder` from `@cometchat/calls-sdk-react-native` offers these methods: + +| Methods | Description | Code | +| --- | --- | --- | +| **enableDefaultLayout** | Show or hide the default button layout. Default: `true` | `.enableDefaultLayout(boolean)` | +| **setIsAudioOnlyCall** | Make the call audio-only. Default: `false` | `.setIsAudioOnlyCall(boolean)` | +| **setCallEventListener** | Set the `OngoingCallListener` that receives call events | `.setCallEventListener(OngoingCallListener)` | +| **setMode** | Set the call mode: `DEFAULT` or `SPOTLIGHT` from `CometChatCalls.CALL_MODE` | `.setMode(mode)` | +| **setDefaultAudioMode** | Set the default audio mode: `SPEAKER`, `EARPIECE`, `BLUETOOTH` or `HEADPHONES` from `CometChatCalls.AUDIO_MODE` | `.setDefaultAudioMode(audioMode)` | +| **showEndCallButton** | Show or hide the end call button. Default: `true` | `.showEndCallButton(boolean)` | +| **showMuteAudioButton** | Show or hide the mute audio button. Default: `true` | `.showMuteAudioButton(boolean)` | +| **showPauseVideoButton** | Show or hide the pause video button. Default: `true` | `.showPauseVideoButton(boolean)` | +| **showSwitchCameraButton** | Show or hide the switch camera button. Default: `true` | `.showSwitchCameraButton(boolean)` | +| **showAudioModeButton** | Show or hide the audio mode button. Default: `true` | `.showAudioModeButton(boolean)` | +| **showRecordingButton** | Show or hide the recording button. Default: `false` | `.showRecordingButton(boolean)` | +| **startWithAudioMuted** | Start the call with audio muted. Default: `false` | `.startWithAudioMuted(boolean)` | +| **startWithVideoMuted** | Start the call with video muted. Has no effect on audio calls. Default: `false` | `.startWithVideoMuted(boolean)` | +| **startRecordingOnCallStart** | Start recording as soon as the call starts. Default: `false` | `.startRecordingOnCallStart(boolean)` | +| **setIdleTimeoutPeriod** | When you are the only one in the call, end it after this period. You get the option to extend the call 60 seconds before it ends. Default: 180 seconds | `.setIdleTimeoutPeriod(number)` | +| **enableVideoTileClick** | Allow tapping video tiles in Spotlight mode. Default: allowed | `.enableVideoTileClick(boolean)` | +| **enableVideoTileDrag** | Allow dragging video tiles in Spotlight mode. Default: allowed | `.enableVideoTileDrag(boolean)` | + +#### Example + +In the example below, the call shows the recording button and starts with audio muted: + +```tsx lines +import { CometChatCalls } from "@cometchat/calls-sdk-react-native"; +import { CometChatOngoingCall } from "@cometchat/chat-uikit-react-native"; + +const callSettingsBuilder = new CometChatCalls.CallSettingsBuilder() + .enableDefaultLayout(true) + .setIsAudioOnlyCall(false) + .showRecordingButton(true) + .startWithAudioMuted(true) + .setCallEventListener(callListener); // the OngoingCallListener from Integration + +; +``` + + +Voice and video calls need microphone and camera permissions on iOS and Android. Add them as described in [Add Permissions](/ui-kit/react-native/calling-integration#add-permissions). + + +--- + +### Events + +[Events](/ui-kit/react-native/components-overview#events) are emitted by a component. `CometChatOngoingCall` emits no events of its own. When `CometChatIncomingCall` or `CometChatOutgoingCall` render it for you, they emit this event when the call ends: + +| Event | Description | +| --- | --- | +| **ccCallEnded** | Triggers when a call shown by `CometChatIncomingCall` or `CometChatOutgoingCall` ends. Payload: `{ call }`; `call` can be undefined. | + +```tsx lines +import { useEffect } from "react"; +import { CometChat } from "@cometchat/chat-sdk-react-native"; +import { CometChatUIEventHandler } from "@cometchat/chat-uikit-react-native"; + +function useCallEndedEvent() { + useEffect(() => { + const listenerId = "ONGOING_CALL_EVENTS_" + Date.now(); + + // Add the listener + CometChatUIEventHandler.addCallListener(listenerId, { + ccCallEnded: ({ call }: { call?: CometChat.Call }) => { + console.log("Call ended:", call); + }, + }); + + // Remove the listener on cleanup + return () => { + CometChatUIEventHandler.removeCallListener(listenerId); + }; + }, []); +} +``` + +If you render `CometChatOngoingCall` yourself, nothing emits this event. Use `onCallEnded` on your builder's `OngoingCallListener` instead. + +--- + +## Customization + +To fit your app's requirements, you can customize how the call behaves through the component's props and `callSettingsBuilder`. + +### Style + +`CometChatOngoingCall` has no `style` prop. The Calls SDK draws the call screen. The only UI Kit element is the loading spinner, which uses the theme's primary color. + +--- + +### Functionality + +| Property | Description | Code | +| --- | --- | --- | +| **sessionID** | Session ID of the call. Required. | `sessionID: string` | +| **callSettingsBuilder** | Settings for the call. Required. | `callSettingsBuilder: CometChatCalls.CallSettingsBuilder` | +| **onError** | Called when the component cannot get a call token | `onError?: (e: CometChat.CometChatException) => void` | + + +- `callSettingsBuilder` must be a `CometChatCalls.CallSettingsBuilder` instance, because the component calls its `build()` method. A plain settings object does not work. +- The call uses the settings built on the component's first render. Passing a different builder later has no effect. + + +### Advanced + +For advanced customization, UI Kit components accept custom views for parts of their UI. `CometChatOngoingCall` has no view slots, so it offers no customization beyond `callSettingsBuilder`. + +--- + +## Common Patterns + +### Show the Ongoing Call After Accepting a Call + +Accept the call with the Chat SDK, then render the call screen for the accepted call. This mirrors what `CometChatIncomingCall` does by default. + +```tsx lines +import { useState } from "react"; +import { Button } from "react-native"; +import { CometChat } from "@cometchat/chat-sdk-react-native"; + +function AcceptCall({ incomingCall }: { incomingCall: CometChat.Call }) { + const [activeCall, setActiveCall] = useState(); + + const accept = () => { + CometChat.acceptCall(incomingCall.getSessionId()) + .then((accepted) => setActiveCall(accepted)) + .catch(console.log); + }; + + if (activeCall) { + // OngoingCallScreen is the component from Integration + return setActiveCall(undefined)} />; + } + + return