Repository navigation
docs(calls/javascript): ringing with the Calls SDK 5.1 #572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jitvarpatil
wants to merge
2
commits into
main
Choose a base branch
from
docs/javascript-ringing-calls-sdk
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+869
−246
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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
|
||
| --- | ||
|
|
||
| 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. | ||
|
|
||
| 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 | ||
| 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. | ||
|
|
||
| ## 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 | | ||
| | `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
|
||
| | `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); | ||
|
|
||
| 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 | ||
|
|
||
| | 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 | | ||
|
|
||
| <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 | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: the
isPeerCalltypings add an exception to "ends for both": the session ends for both unlessforceLeaveis passed when leaving. It may be worth mentioning here or in Session Settings.