Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions calls/javascript/actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
description: "Use CometChat Calls SDK v5 actions on JavaScript to control calls, manage audio/video state, share screens, and handle in-call behavior."
---

Use call actions to create your own custom controls or trigger call functionality dynamically based on your use case. All actions are called on the `CometChatCalls` class during an active call session.
Use call actions to create your own custom controls or trigger call functionality dynamically based on your use case. All actions are called on the `CometChatCalls` class during an active call session. The session object that `CometChatCalls.initiateCall`, `connect` and `getActiveSession()` return has every action as a method too (`session.muteAudio()`, `session.setLayout(...)`, and so on); on the session object an action called while no session is live is ignored with a console warning.

## Audio Controls

Expand All @@ -17,9 +17,9 @@
CometChatCalls.muteAudio();
```

### Unmute Audio

Check warning on line 20 in calls/javascript/actions.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/actions.mdx#L20

Did you really mean 'Unmute'?

Unmutes your local microphone, resuming audio transmission.

Check warning on line 22 in calls/javascript/actions.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/actions.mdx#L22

Did you really mean 'Unmutes'?

```javascript
CometChatCalls.unmuteAudio();
Expand Down Expand Up @@ -202,16 +202,39 @@

### Leave Session

Ends your participation and disconnects gracefully. The call continues for other participants.
Ends your participation and disconnects gracefully. In a 1:1 call this is the hang-up: the other side receives `onParticipantLeft`, and a session joined as a peer call (`isPeerCall: true`) ends for both. In a group call the session continues for the other participants. Leaving also cancels a session that is only prepared: `onConnectionClosed` fires instead of `onSessionLeft`. A prepared peer session is already in the room, so leaving it ends the room for everyone in it, as a hang-up would.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the isPeerCall typings add an exception to "ends for both": the session ends for both unless forceLeave is passed when leaving. It may be worth mentioning here or in Session Settings.


```javascript
CometChatCalls.leaveSession();

// Or on the session object:
await CometChatCalls.getActiveSession()?.leave();
```

<Note>
`leaveSession()` takes no session ID. `CometChatCalls` is a singleton that tracks one active session at a time, so this leaves whichever session is currently in progress. The same applies to every action on this page. See [Single Active Session](/calls/javascript/overview#single-active-session).

<Note>
To end a call that is still ringing, use `CometChatCalls.endCall(sessionId, status)` instead: `"cancelled"` on the caller, `"rejected"` or `"busy"` on the callee, as described in [Ringing](/calls/javascript/ringing). `leaveSession()` alone does not tell the other side why the call ended.

Check warning on line 217 in calls/javascript/actions.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/actions.mdx#L217

Did you really mean 'callee'?
</Note>

### Session State

`session.isSessionActive()` returns `true` while the SDK owns a session: one being prepared or prepared (for example an outgoing call that is still ringing), one being joined, or a joined one. `session.isSessionJoined()` is the narrower "in a call" check: `true` only once the session is joined. `CometChatCalls.getSessionState()` returns `"idle"`, `"preparing"`, `"prepared"`, `"joining"` or `"joined"`.

```javascript
const session = CometChatCalls.getActiveSession(); // null when nothing is live
const isInCall = session?.isSessionJoined() ?? false;
const state = CometChatCalls.getSessionState();
```

### Get Participants

Returns a snapshot of the remote participants of the session, the same list `onParticipantListChanged` receives. The local user is not in it.

```javascript
const participants = CometChatCalls.getParticipants();
```

## UI Controls

### Show Settings Dialog
Expand Down
40 changes: 36 additions & 4 deletions calls/javascript/events.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
description: "Handle CometChat Calls SDK v5 events on JavaScript for call lifecycle, participants, media state, errors, and real-time updates."
---

Handle call session events to build responsive UIs. The SDK provides event listeners to monitor session status, participant activities, media changes, button clicks, and layout changes.

Check warning on line 8 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L8

Did you really mean 'UIs'?

## Adding Event Listeners

Expand All @@ -20,12 +20,34 @@
unsubscribe();
```

Listeners are global: they are not tied to a session, work before any session exists, and stay registered across sessions until you call the function they return. The session object has the same method, `session.addEventListener(eventName, listener)`, with the same behavior. To ask whether there is a session right now, use `CometChatCalls.getActiveSession()`:

```javascript
// null when no session is preparing, prepared or joined
const session = CometChatCalls.getActiveSession();
if (session) {
console.log("Live session", session.sessionId, session.prepareStatus);
}
```

`getActiveSession()` returns the session as soon as it starts **preparing**, before anyone joins: from the moment `CometChatCalls.initiateCall` has created the call on the caller, and from the moment `CometChatCalls.connect` is called on a ringing callee. It returns `null` again once the session ends, its prepare fails or is cancelled, or a prepared session expires after 5 minutes. While a session is only prepared, the SDK reports `onConnected`, `onConnectionFailed` (fatal errors only), `onConnectionClosed` and the roster events (`onParticipantConnected`, `onParticipantJoined`, `onParticipantLeft`, `onParticipantListChanged`); that is what lets a caller see "ringing" and "answered" without joining (see [Ringing](/calls/javascript/ringing)).

Check warning on line 33 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L33

Did you really mean 'callee'?

---

## Session Events

Monitor the call session lifecycle including join/leave events and connection status.

### Connected

Fired when a prepared session has connected: signalling only, no camera or microphone, and other participants do not see you yet. It fires once per prepare (`initiateCall` on the caller, `connect` on the callee); the actual join is `onSessionJoined`.

Check warning on line 43 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L43

Did you really mean 'callee'?

```javascript
CometChatCalls.addEventListener("onConnected", () => {
console.log("Session prepared: the join will be near-instant");
});
```

### Session Joined

Fired when you successfully connect to the session.
Expand All @@ -48,7 +70,7 @@

### Session Timed Out

Fired when the session ends due to inactivity timeout.
Fired when the session ends due to inactivity timeout. It is not used on a prepared session: one that nobody joins within 5 minutes reports `onConnectionClosed` instead.

```javascript
CometChatCalls.addEventListener("onSessionTimedOut", () => {
Expand Down Expand Up @@ -78,7 +100,7 @@

### Connection Closed

Fired when the connection is permanently closed.
Fired when the connection is permanently closed. On a session that was only prepared (an outgoing call still ringing, or an incoming call this tab prepared), it means the call ended before anyone joined: declined, cancelled (in a 1:1 call), the room went away, `leave()` or `endCall` tore it down, or nobody joined within 5 minutes. The event carries no reason.

```javascript
CometChatCalls.addEventListener("onConnectionClosed", () => {
Expand All @@ -92,9 +114,19 @@

Monitor participant activities including join/leave, audio/video state, hand raise, screen sharing, and recording.

### Participant Connected

Fired when a remote participant's device has prepared the session without joining it. On the caller's prepared session, this is the callee's device ringing.

Check warning on line 119 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L119

Did you really mean 'callee's'?

```javascript
CometChatCalls.addEventListener("onParticipantConnected", (participant) => {
console.log("Participant waiting:", participant.uid);
});
```

### Participant Joined

Fired when a participant joins the call.
Fired when a participant joins the call. On the caller's prepared session, this is the callee answering: join with `session.join(container)` now.

Check warning on line 129 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L129

Did you really mean 'callee'?

```javascript
CometChatCalls.addEventListener("onParticipantJoined", (participant) => {
Expand Down Expand Up @@ -132,9 +164,9 @@
});
```

### Participant Audio Unmuted

Check warning on line 167 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L167

Did you really mean 'Unmuted'?

Fired when a participant unmutes their microphone.

Check warning on line 169 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L169

Did you really mean 'unmutes'?

```javascript
CometChatCalls.addEventListener("onParticipantAudioUnmuted", (participant) => {
Expand Down Expand Up @@ -248,9 +280,9 @@
});
```

### Audio Unmuted

Check warning on line 283 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L283

Did you really mean 'Unmuted'?

Fired when your microphone is unmuted.

Check warning on line 285 in calls/javascript/events.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/events.mdx#L285

Did you really mean 'unmuted'?

```javascript
CometChatCalls.addEventListener("onAudioUnMuted", () => {
Expand Down Expand Up @@ -386,7 +418,7 @@

### Leave Session Button Clicked

Fired when the leave button is clicked.
Fired when the leave button is clicked. The SDK leaves the session itself right after, so only clean up here.

```javascript
CometChatCalls.addEventListener("onLeaveSessionButtonClicked", () => {
Expand Down
226 changes: 226 additions & 0 deletions calls/javascript/migrating-from-legacy-ringing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
---
title: "Migrating from Legacy Ringing"
sidebarTitle: "Migrating from Legacy Ringing"
sdk_version: "5.x"
description: "Move a web app from Chat SDK call signalling (CometChat.initiateCall, acceptCall, rejectCall) to ringing with the Calls SDK 5.1: what to add, what to delete, and how each method maps."

Check warning on line 5 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L5

Did you really mean 'acceptCall'?

Check warning on line 5 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L5

Did you really mean 'rejectCall'?
---

Legacy ringing signalled calls through the Chat SDK: `CometChat.initiateCall` created the call, a `CallListener` on the Chat SDK's real-time connection told the callee, and `acceptCall`, `rejectCall` and `endCall` answered, declined and ended it. Ringing now runs on the Calls SDK: it creates the call, prepares and joins the session, and ends the ring. The Chat SDK's calling methods are superseded by the Calls SDK and no longer used. On the web, the Chat SDK's `CallListener` stays: it is still how an incoming call reaches an open tab.

Check warning on line 8 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L8

Did you really mean 'callee'?

This page is the diff. For the full description of the current flow see [Ringing](/calls/javascript/ringing).

## Before you start

Enable the **ringing migration** setting for your app in the CometChat dashboard, then follow the
steps below. This page is for apps that use the SDKs directly. If you use the CometChat UI Kit, its

Check warning on line 15 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L15

Did you really mean 'SDKs'?
support for this flow comes with a coming UI Kit release; keep legacy ringing until then.

{/* TODO(RC): add the setting's exact name and dashboard path and a screenshot once the toggle ships. */}

## Why it changed

| Legacy | Now |
|--------|-----|
| The Chat SDK created the call, and `acceptCall` / `rejectCall` / `endCall` were HTTP calls your app had to sequence with `generateToken` and `joinSession` | The Calls SDK creates the call and prepares its session. Answer = join; decline, busy, cancel and no answer are one `endCall(sessionId, status)` |
| The caller only knew "accepted" or "rejected" | The caller sees "Ringing…" (the callee's device was reached) and "answered" from the Calls SDK. A decline, busy or no answer is read from the call's status while ringing |
| Joining took a token request and a full connect after the answer | The session is prepared while it rings, so the join is near-instant |
| Web and mobile rang through different paths | One call, rung in the callee's open tabs (Chat SDK) and on the callee's phones (Push Notifications SDK) |

## Before and after

```mermaid
sequenceDiagram
participant A as Caller
participant Chat as Chat SDK
participant B as Callee

rect rgb(240,240,240)
Note over A,B: Legacy ringing
A->>Chat: CometChat.initiateCall(call)
Chat-->>B: CallListener.onIncomingCallReceived
B->>Chat: CometChat.acceptCall(sessionId)
Chat-->>A: onOutgoingCallAccepted
A->>A: generateToken + joinSession
B->>B: generateToken + joinSession
A->>Chat: CometChat.endCall(sessionId)
Chat-->>B: onCallEndedMessageReceived
end
```

```mermaid
sequenceDiagram
participant A as Caller · Calls SDK
participant BE as Backend
participant Chat as Callee · Chat SDK
participant C as Callee · Calls SDK

rect rgb(232,244,236)
Note over A,C: Ringing now
A->>BE: CometChatCalls.initiateCall(receiver, options)
BE-->>Chat: call message (initiated)
Chat-->>C: onIncomingCallReceived → CometChatCalls.connect(sessionId)
C-->>A: onParticipantConnected ("Ringing…")
C->>C: Answer → session.join(container)
C-->>A: onParticipantJoined → data.session.join(container)
A->>A: session.leave() to hang up
end
```

## Step 1: Update dependencies

```bash
npm install @cometchat/calls-sdk-javascript@5.1.0
# @cometchat/chat-sdk-javascript stays: chat, and incoming calls on the web
```

Keep both SDKs initialized and logged in as the same user: the Calls SDK for `initiateCall`, `connect` and `endCall`, the Chat SDK for the incoming call message.

Check warning on line 76 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L76

Did you really mean 'SDKs'?

## Step 2: Rewrite the caller

| Legacy | Now | Notes |
|--------|-----|-------|
| `CometChat.initiateCall(new CometChat.Call(receiverId, callType, receiverType))` | `CometChatCalls.initiateCall(receiver, { type, receiverType, sessionSettings })` → `{ data, error }` | `data.session` is the caller's session, already preparing. Set `sessionType` in `sessionSettings`, and `isPeerCall: true` for a 1:1 call |
| `CometChat.initiateCall(call, timeout)` | No timeout parameter | Run your own timer on the caller and end the call with `endCall(sessionId, "unanswered")` after 45 s, before a phone's 60-second ring runs out |
| `onOutgoingCallAccepted(call)` | `CometChatCalls.addEventListener("onParticipantJoined", ...)` on the prepared session, then `data.session.join(container)` | New in-between event: `onParticipantConnected` = the callee's device is ringing |

Check warning on line 84 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L84

Did you really mean 'callee's'?
| `onOutgoingCallRejected(call)` | Read the call's status every 3 s while ringing; `onConnectionClosed` when the prepared session closes | Not reliably reported: a busy decline, or a decline before the callee's device connected, closes nothing. `onOutgoingCallRejected` may still arrive; keep it as an extra signal, and check `getCallInitiator()`: a 1:1 decline reaches the callee's other tabs too |

Check warning on line 85 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L85

Did you really mean 'callee's'?

Check warning on line 85 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L85

Did you really mean 'callee's'?
| `CometChat.rejectCall(sessionId, CometChat.CALL_STATUS.CANCELLED)` | `CometChatCalls.endCall(sessionId, "cancelled")` | Tears the caller's prepared session down first |
| `generateToken` + `joinSession` after the answer | `data.session.join(container)` | Takes no settings: the ones passed to `initiateCall` apply |

<Tabs>
<Tab title="Before">
```javascript
const call = new CometChat.Call(receiverId, CometChat.CALL_TYPE.VIDEO, CometChat.RECEIVER_TYPE.USER);
const outgoingCall = await CometChat.initiateCall(call);

Check warning on line 93 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L93

Did you really mean 'outgoingCall'?

CometChat.addCallListener("caller", new CometChat.CallListener({
onOutgoingCallAccepted: async (accepted) => {
const { token } = await CometChatCalls.generateToken(accepted.getSessionId());
await CometChatCalls.joinSession(token, { sessionType: "VIDEO" }, container);
},
onOutgoingCallRejected: () => closeOutgoingScreen(),
}));

function cancel() {
CometChat.rejectCall(outgoingCall.getSessionId(), CometChat.CALL_STATUS.CANCELLED);
}
```
</Tab>
<Tab title="After">
```javascript
const { data: call, error } = await CometChatCalls.initiateCall(receiverId, {
type: "video",
sessionSettings: { sessionType: "VIDEO", isPeerCall: true },
});
if (error) throw new Error(`Could not start the call: ${error.message}`);

const offConnected = CometChatCalls.addEventListener("onParticipantConnected", () => setStatus("Ringing…"));
const offJoined = CometChatCalls.addEventListener("onParticipantJoined", () => {
stopWatching();
call.session.join(container);
});
const offClosed = CometChatCalls.addEventListener("onConnectionClosed", () => closeOutgoingScreen());
const stopWatching = () => { offConnected(); offJoined(); offClosed(); };
// Plus: poll the call's status every 3 s and a 45 s ring timer (see Ringing).

function cancel() {
stopWatching();
CometChatCalls.endCall(call.sessionId, "cancelled");
}
```
</Tab>
</Tabs>

## Step 3: Rewrite the callee

Check warning on line 133 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L133

Did you really mean 'callee'?

| Legacy | Now | Notes |
|--------|-----|-------|
| `CallListener.onIncomingCallReceived(call)` | Unchanged: the call still arrives on the Chat SDK's `CallListener`. Then prepare it with `CometChatCalls.connect(call.getSessionId(), settings)` | The caller's own tabs receive their 1:1 call as "incoming" too: skip calls whose `getCallInitiator()` is the logged-in user |
| `CometChat.acceptCall(sessionId)` then `generateToken` + `joinSession` | `session.join(container)` on the session `connect` prepared. Nothing else to send | If the prepare failed, `generateToken` + `joinSession` as before |
| `CometChat.rejectCall(sessionId, CometChat.CALL_STATUS.REJECTED)` | `CometChatCalls.endCall(sessionId, "rejected")` | `"busy"` when the user is in another call. A group call's decline is local: `session.leave()` |
| `onIncomingCallCancelled(call)` | Still fires (also when the caller gives up as `unanswered`); also `onConnectionClosed` on a prepared 1:1 session, and the call's status read while ringing | The status is the backstop: a cancel does not always reach a ringing tab as a message |
| — | Your own ring timer on the callee | Stop ringing after 60 s, a little after the caller gives up at 45 s |

Check warning on line 141 in calls/javascript/migrating-from-legacy-ringing.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

calls/javascript/migrating-from-legacy-ringing.mdx#L141

Did you really mean 'callee'?

<Tabs>
<Tab title="Before">
```javascript
CometChat.addCallListener("callee", new CometChat.CallListener({
onIncomingCallReceived: (call) => showIncomingScreen(call),
onIncomingCallCancelled: () => closeIncomingScreen(),
}));

async function answer(call) {
await CometChat.acceptCall(call.getSessionId());
const { token } = await CometChatCalls.generateToken(call.getSessionId());
await CometChatCalls.joinSession(token, { sessionType: "VIDEO" }, container);
}

function decline(call) {
CometChat.rejectCall(call.getSessionId(), CometChat.CALL_STATUS.REJECTED);
}
```
</Tab>
<Tab title="After">
```javascript
// Settings for an incoming 1:1 call: the type comes from the call, or an audio call opens the camera.
const settingsFor = (call) => ({
sessionType: call.getType() === "audio" ? "VOICE" : "VIDEO",
isPeerCall: true,
});

CometChat.addCallListener("callee", new CometChat.CallListener({
onIncomingCallReceived: (call) => {
if (call.getCallInitiator()?.getUid() === CometChatCalls.getLoggedInUser()?.uid) return;
showIncomingScreen(call);
CometChatCalls.connect(call.getSessionId(), settingsFor(call))
.catch(() => {}); // answer falls back to a direct join
},
onIncomingCallCancelled: () => closeIncomingScreen(),
}));

async function answer(call) {
const session = CometChatCalls.getActiveSession();
if (session?.sessionId === call.getSessionId()) {
await session.join(container);
} else {
const { token } = await CometChatCalls.generateToken(call.getSessionId());
await CometChatCalls.joinSession(token, settingsFor(call), container);
}
}

function decline(call) {
CometChatCalls.endCall(call.getSessionId(), "rejected");
}
```
</Tab>
</Tabs>

## Step 4: Replace the remaining calls

| Legacy | Now | Notes |
|--------|-----|-------|
| `CometChat.endCall(sessionId)` after a call | `session.leave()` or `CometChatCalls.leaveSession()` | No status to send; with `isPeerCall` the call ends for both |
| `CometChat.getActiveCall()` | `CometChatCalls.getActiveSession()` | `null` when no session is preparing, prepared or joined. `session.sessionId` names the call for a session from `initiateCall` or `connect` (it is `null` after a direct `joinSession`) |
| `CometChat.clearActiveCall()` | Nothing | The Calls SDK clears its session when it ends |
| `onCallEndedMessageReceived(call)` | `onSessionLeft` / `onConnectionClosed` on the joined session | |
| `CometChat.startCall(...)`, Chat SDK `CallSettings` | `joinSession` + the 5.x events (see the [v5 migration guide](/calls/javascript/migration-guide-v5)) | |
| `CometChat.CALL_STATUS.*` values for a decline or cancel | `"rejected"`, `"busy"`, `"cancelled"`, `"unanswered"` strings passed to `endCall` | The `Call` message model and `CometChat.CALL_STATUS` still describe call messages in a conversation's history |

## What users will notice

- The caller sees "Ringing…" once the callee's tab or phone is reached, and the call screen closes when the call is declined, busy or missed (from the call's status, or the ring timer).
- Answering joins almost at once, because the session was prepared while it rang.
- Calls ring between web and mobile users in both directions.
- The browser asks for the camera and microphone when the call is joined, not while it rings.

## Checklist

- [ ] `@cometchat/calls-sdk-javascript` 5.1; the Chat SDK stays, initialized and logged in as the same user
- [ ] **Ringing migration** enabled for the app in the dashboard
- [ ] `initiateCall` passes `sessionSettings` with `sessionType`, and `isPeerCall: true` for a 1:1 call
- [ ] Caller listens for `onParticipantConnected` / `onParticipantJoined` / `onConnectionClosed` and joins only on `onParticipantJoined` with `data.session.join(container)`
- [ ] Caller polls the call's status every 3 s while ringing and runs a ring timer that ends the call as `unanswered`
- [ ] Callee skips its own outgoing calls, prepares with `connect`, and answers with `session.join(container)`
- [ ] Callee stops ringing on `onIncomingCallCancelled`, `onConnectionClosed`, its ring timer and the status poll
- [ ] Decline, busy and cancel use `CometChatCalls.endCall`; no `CometChat.acceptCall`, `rejectCall` or `endCall` left
- [ ] Hang-up uses `session.leave()` or `CometChatCalls.leaveSession()`
- [ ] Tested: web to web, web to phone and phone to web; decline, busy, cancel, no answer; two open tabs
Loading
Loading