@cometchat/skills 4.2.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -12
  3. package/bin/install.js +59 -4
  4. package/package.json +14 -1
  5. package/skills/cometchat/SKILL.md +460 -77
  6. package/skills/cometchat/references/asking-questions.md +48 -0
  7. package/skills/cometchat-a11y/SKILL.md +3 -2
  8. package/skills/cometchat-android-v5/SKILL.md +2 -1
  9. package/skills/cometchat-android-v5-calls/SKILL.md +36 -22
  10. package/skills/cometchat-android-v5-calls/references/README.md +1 -1
  11. package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +7 -5
  12. package/skills/cometchat-android-v5-calls/references/audio-controls.md +4 -4
  13. package/skills/cometchat-android-v5-calls/references/call-layouts.md +33 -25
  14. package/skills/cometchat-android-v5-calls/references/call-session.md +2 -2
  15. package/skills/cometchat-android-v5-calls/references/custom-ui.md +5 -5
  16. package/skills/cometchat-android-v5-calls/references/event-listeners.md +2 -2
  17. package/skills/cometchat-android-v5-calls/references/idle-timeout.md +20 -14
  18. package/skills/cometchat-android-v5-calls/references/in-call-chat.md +1 -1
  19. package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +43 -27
  20. package/skills/cometchat-android-v5-calls/references/participant-management.md +3 -3
  21. package/skills/cometchat-android-v5-calls/references/raise-hand.md +25 -19
  22. package/skills/cometchat-android-v5-calls/references/recording.md +2 -2
  23. package/skills/cometchat-android-v5-calls/references/ringing-integration.md +1 -1
  24. package/skills/cometchat-android-v5-calls/references/screen-sharing.md +5 -9
  25. package/skills/cometchat-android-v5-calls/references/session-settings.md +3 -3
  26. package/skills/cometchat-android-v5-calls/references/setup.md +1 -1
  27. package/skills/cometchat-android-v5-calls/references/share-invite.md +9 -4
  28. package/skills/cometchat-android-v5-calls/references/video-controls.md +4 -4
  29. package/skills/cometchat-android-v5-calls/references/voip-calling.md +2 -2
  30. package/skills/cometchat-android-v5-components/SKILL.md +4 -3
  31. package/skills/cometchat-android-v5-core/SKILL.md +20 -2
  32. package/skills/cometchat-android-v5-customization/SKILL.md +171 -7
  33. package/skills/cometchat-android-v5-extensions/SKILL.md +7 -4
  34. package/skills/cometchat-android-v5-features/SKILL.md +5 -4
  35. package/skills/cometchat-android-v5-placement/SKILL.md +2 -1
  36. package/skills/cometchat-android-v5-production/SKILL.md +2 -1
  37. package/skills/cometchat-android-v5-push/SKILL.md +2 -3
  38. package/skills/cometchat-android-v5-testing/SKILL.md +2 -1
  39. package/skills/cometchat-android-v5-theming/SKILL.md +2 -1
  40. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +3 -2
  41. package/skills/cometchat-android-v6/SKILL.md +2 -1
  42. package/skills/cometchat-android-v6-builder-settings/SKILL.md +11 -7
  43. package/skills/cometchat-android-v6-calls/SKILL.md +79 -18
  44. package/skills/cometchat-android-v6-calls/references/advanced-features.md +87 -0
  45. package/skills/cometchat-android-v6-calls/references/call-layouts.md +24 -15
  46. package/skills/cometchat-android-v6-calls/references/call-session.md +2 -2
  47. package/skills/cometchat-android-v6-calls/references/device-management.md +17 -16
  48. package/skills/cometchat-android-v6-calls/references/idle-timeout.md +7 -4
  49. package/skills/cometchat-android-v6-calls/references/in-call-chat.md +13 -8
  50. package/skills/cometchat-android-v6-calls/references/raise-hand.md +6 -4
  51. package/skills/cometchat-android-v6-compose-components/SKILL.md +52 -29
  52. package/skills/cometchat-android-v6-compose-customization/SKILL.md +156 -1
  53. package/skills/cometchat-android-v6-compose-placement/SKILL.md +129 -40
  54. package/skills/cometchat-android-v6-compose-theming/SKILL.md +27 -1
  55. package/skills/cometchat-android-v6-core/SKILL.md +389 -9
  56. package/skills/cometchat-android-v6-events/SKILL.md +4 -1
  57. package/skills/cometchat-android-v6-extensions/SKILL.md +2 -1
  58. package/skills/cometchat-android-v6-features/SKILL.md +26 -2
  59. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +31 -1
  60. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +172 -1
  61. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +20 -5
  62. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +36 -5
  63. package/skills/cometchat-android-v6-migration/SKILL.md +44 -42
  64. package/skills/cometchat-android-v6-production/SKILL.md +6 -3
  65. package/skills/cometchat-android-v6-push/SKILL.md +43 -2
  66. package/skills/cometchat-android-v6-testing/SKILL.md +11 -8
  67. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +26 -5
  68. package/skills/cometchat-angular-calls/SKILL.md +256 -389
  69. package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +3 -2
  70. package/skills/cometchat-angular-calls/references/call-layouts.md +29 -12
  71. package/skills/cometchat-angular-calls/references/call-session.md +2 -2
  72. package/skills/cometchat-angular-calls/references/custom-ui.md +18 -10
  73. package/skills/cometchat-angular-calls/references/device-management.md +53 -34
  74. package/skills/cometchat-angular-calls/references/group-calls.md +45 -24
  75. package/skills/cometchat-angular-calls/references/idle-timeout.md +31 -15
  76. package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +7 -6
  77. package/skills/cometchat-angular-calls/references/raise-hand.md +9 -4
  78. package/skills/cometchat-angular-calls/references/recording-screen-share.md +32 -39
  79. package/skills/cometchat-angular-calls/references/ringing-integration.md +3 -1
  80. package/skills/cometchat-angular-calls/references/share-invite.md +11 -5
  81. package/skills/cometchat-angular-calls/references/virtual-background.md +29 -0
  82. package/skills/cometchat-angular-components/SKILL.md +149 -620
  83. package/skills/cometchat-angular-core/SKILL.md +235 -293
  84. package/skills/cometchat-angular-customization/SKILL.md +415 -223
  85. package/skills/cometchat-angular-features/SKILL.md +216 -334
  86. package/skills/cometchat-angular-patterns/SKILL.md +168 -359
  87. package/skills/cometchat-angular-placement/SKILL.md +189 -560
  88. package/skills/cometchat-angular-production/SKILL.md +241 -92
  89. package/skills/cometchat-angular-push/SKILL.md +280 -294
  90. package/skills/cometchat-angular-testing/SKILL.md +430 -158
  91. package/skills/cometchat-angular-theming/SKILL.md +190 -265
  92. package/skills/cometchat-angular-troubleshooting/SKILL.md +192 -157
  93. package/skills/cometchat-astro-patterns/SKILL.md +22 -1
  94. package/skills/cometchat-calls/SKILL.md +25 -19
  95. package/skills/cometchat-calls/references/use-case-broadcast.md +15 -10
  96. package/skills/cometchat-calls/references/use-case-marketplace.md +2 -3
  97. package/skills/cometchat-calls/references/use-case-support.md +3 -4
  98. package/skills/cometchat-calls/references/use-case-team.md +23 -12
  99. package/skills/cometchat-calls/references/use-case-telehealth.md +3 -4
  100. package/skills/cometchat-components/SKILL.md +163 -25
  101. package/skills/cometchat-core/SKILL.md +412 -13
  102. package/skills/cometchat-customization/SKILL.md +50 -25
  103. package/skills/cometchat-features/SKILL.md +313 -34
  104. package/skills/cometchat-flutter-v5/SKILL.md +10 -4
  105. package/skills/cometchat-flutter-v5-calls/SKILL.md +188 -158
  106. package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +48 -24
  107. package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +20 -15
  108. package/skills/cometchat-flutter-v5-calls/references/call-session.md +100 -145
  109. package/skills/cometchat-flutter-v5-calls/references/device-management.md +12 -8
  110. package/skills/cometchat-flutter-v5-calls/references/group-calls.md +30 -36
  111. package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +15 -13
  112. package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +12 -9
  113. package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +115 -65
  114. package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +41 -30
  115. package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +17 -14
  116. package/skills/cometchat-flutter-v5-calls/references/share-invite.md +8 -2
  117. package/skills/cometchat-flutter-v5-conversations/SKILL.md +2 -1
  118. package/skills/cometchat-flutter-v5-core/SKILL.md +20 -2
  119. package/skills/cometchat-flutter-v5-customization/SKILL.md +136 -5
  120. package/skills/cometchat-flutter-v5-events/SKILL.md +2 -1
  121. package/skills/cometchat-flutter-v5-messages/SKILL.md +2 -1
  122. package/skills/cometchat-flutter-v5-production/SKILL.md +15 -6
  123. package/skills/cometchat-flutter-v5-push/SKILL.md +2 -1
  124. package/skills/cometchat-flutter-v5-testing/SKILL.md +17 -6
  125. package/skills/cometchat-flutter-v5-theming/SKILL.md +2 -1
  126. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +7 -6
  127. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +3 -2
  128. package/skills/cometchat-flutter-v6/SKILL.md +17 -16
  129. package/skills/cometchat-flutter-v6-calls/SKILL.md +78 -63
  130. package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +8 -6
  131. package/skills/cometchat-flutter-v6-calls/references/advanced-features.md +89 -0
  132. package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +15 -12
  133. package/skills/cometchat-flutter-v6-calls/references/call-session.md +2 -2
  134. package/skills/cometchat-flutter-v6-calls/references/device-management.md +9 -3
  135. package/skills/cometchat-flutter-v6-calls/references/group-calls.md +10 -10
  136. package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +15 -7
  137. package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +6 -3
  138. package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +23 -16
  139. package/skills/cometchat-flutter-v6-components/SKILL.md +32 -11
  140. package/skills/cometchat-flutter-v6-conversations/SKILL.md +39 -11
  141. package/skills/cometchat-flutter-v6-core/SKILL.md +348 -10
  142. package/skills/cometchat-flutter-v6-customization/SKILL.md +97 -25
  143. package/skills/cometchat-flutter-v6-events/SKILL.md +3 -2
  144. package/skills/cometchat-flutter-v6-features/SKILL.md +15 -6
  145. package/skills/cometchat-flutter-v6-messages/SKILL.md +111 -60
  146. package/skills/cometchat-flutter-v6-migration/SKILL.md +18 -25
  147. package/skills/cometchat-flutter-v6-placement/SKILL.md +79 -50
  148. package/skills/cometchat-flutter-v6-production/SKILL.md +13 -12
  149. package/skills/cometchat-flutter-v6-push/SKILL.md +43 -21
  150. package/skills/cometchat-flutter-v6-testing/SKILL.md +6 -6
  151. package/skills/cometchat-flutter-v6-theming/SKILL.md +38 -5
  152. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +182 -17
  153. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +12 -4
  154. package/skills/cometchat-i18n/SKILL.md +139 -78
  155. package/skills/cometchat-ios/SKILL.md +4 -2
  156. package/skills/cometchat-ios-calls/SKILL.md +225 -95
  157. package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +11 -9
  158. package/skills/cometchat-ios-calls/references/audio-modes-and-controls.md +45 -0
  159. package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +6 -7
  160. package/skills/cometchat-ios-calls/references/call-layouts.md +31 -91
  161. package/skills/cometchat-ios-calls/references/call-session.md +51 -54
  162. package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +33 -29
  163. package/skills/cometchat-ios-calls/references/custom-ui.md +38 -38
  164. package/skills/cometchat-ios-calls/references/group-calls.md +33 -70
  165. package/skills/cometchat-ios-calls/references/idle-timeout.md +24 -25
  166. package/skills/cometchat-ios-calls/references/in-call-chat.md +19 -23
  167. package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +128 -70
  168. package/skills/cometchat-ios-calls/references/picture-in-picture.md +20 -20
  169. package/skills/cometchat-ios-calls/references/raise-hand.md +14 -227
  170. package/skills/cometchat-ios-calls/references/recording-screen-share.md +35 -122
  171. package/skills/cometchat-ios-calls/references/ringing-integration.md +17 -16
  172. package/skills/cometchat-ios-calls/references/share-invite.md +8 -12
  173. package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +4 -4
  174. package/skills/cometchat-ios-components/SKILL.md +200 -12
  175. package/skills/cometchat-ios-core/SKILL.md +281 -11
  176. package/skills/cometchat-ios-customization/SKILL.md +276 -110
  177. package/skills/cometchat-ios-features/SKILL.md +64 -36
  178. package/skills/cometchat-ios-placement/SKILL.md +15 -12
  179. package/skills/cometchat-ios-production/SKILL.md +12 -4
  180. package/skills/cometchat-ios-push/SKILL.md +53 -19
  181. package/skills/cometchat-ios-testing/SKILL.md +14 -9
  182. package/skills/cometchat-ios-theming/SKILL.md +39 -3
  183. package/skills/cometchat-ios-troubleshooting/SKILL.md +41 -21
  184. package/skills/cometchat-native-bare-patterns/SKILL.md +56 -18
  185. package/skills/cometchat-native-calls/SKILL.md +89 -19
  186. package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +2 -2
  187. package/skills/cometchat-native-calls/references/call-layouts.md +15 -14
  188. package/skills/cometchat-native-calls/references/call-session.md +2 -2
  189. package/skills/cometchat-native-calls/references/custom-ui.md +12 -8
  190. package/skills/cometchat-native-calls/references/device-management.md +53 -30
  191. package/skills/cometchat-native-calls/references/group-calls.md +35 -30
  192. package/skills/cometchat-native-calls/references/idle-timeout.md +6 -6
  193. package/skills/cometchat-native-calls/references/in-call-chat.md +10 -8
  194. package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +2 -2
  195. package/skills/cometchat-native-calls/references/raise-hand.md +15 -13
  196. package/skills/cometchat-native-calls/references/recording-screen-share.md +49 -170
  197. package/skills/cometchat-native-calls/references/share-invite.md +7 -5
  198. package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +4 -2
  199. package/skills/cometchat-native-components/SKILL.md +91 -57
  200. package/skills/cometchat-native-core/SKILL.md +281 -9
  201. package/skills/cometchat-native-customization/SKILL.md +150 -28
  202. package/skills/cometchat-native-expo-patterns/SKILL.md +77 -27
  203. package/skills/cometchat-native-features/SKILL.md +79 -49
  204. package/skills/cometchat-native-placement/SKILL.md +19 -10
  205. package/skills/cometchat-native-production/SKILL.md +9 -3
  206. package/skills/cometchat-native-push/SKILL.md +2 -1
  207. package/skills/cometchat-native-testing/SKILL.md +1 -2
  208. package/skills/cometchat-native-theming/SKILL.md +54 -29
  209. package/skills/cometchat-native-troubleshooting/SKILL.md +71 -3
  210. package/skills/cometchat-nextjs-patterns/SKILL.md +48 -6
  211. package/skills/cometchat-placement/SKILL.md +42 -3
  212. package/skills/cometchat-production/SKILL.md +12 -5
  213. package/skills/cometchat-react-calls/SKILL.md +220 -10
  214. package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +4 -3
  215. package/skills/cometchat-react-calls/references/call-layouts.md +5 -6
  216. package/skills/cometchat-react-calls/references/call-session.md +1 -1
  217. package/skills/cometchat-react-calls/references/custom-ui.md +61 -15
  218. package/skills/cometchat-react-calls/references/device-management.md +55 -51
  219. package/skills/cometchat-react-calls/references/group-calls.md +18 -23
  220. package/skills/cometchat-react-calls/references/idle-timeout.md +25 -12
  221. package/skills/cometchat-react-calls/references/in-call-chat.md +7 -7
  222. package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +9 -11
  223. package/skills/cometchat-react-calls/references/raise-hand.md +14 -14
  224. package/skills/cometchat-react-calls/references/recording-screen-share.md +39 -38
  225. package/skills/cometchat-react-calls/references/ringing-integration.md +2 -2
  226. package/skills/cometchat-react-calls/references/share-invite.md +4 -5
  227. package/skills/cometchat-react-calls/references/testing-calls-on-web.md +20 -2
  228. package/skills/cometchat-react-calls/references/virtual-background.md +32 -0
  229. package/skills/cometchat-react-patterns/SKILL.md +57 -4
  230. package/skills/cometchat-react-push/SKILL.md +258 -72
  231. package/skills/cometchat-react-router-patterns/SKILL.md +43 -4
  232. package/skills/cometchat-react-testing/SKILL.md +14 -5
  233. package/skills/cometchat-theming/SKILL.md +181 -18
  234. package/skills/cometchat-troubleshooting/SKILL.md +40 -20
@@ -34,7 +34,8 @@ In your auth service, after `CometChat.login`:
34
34
  ```ts
35
35
  const user = await CometChat.login(uid, env.AUTH_KEY);
36
36
  const authToken = user.getAuthToken();
37
- await CometChatCalls.login(authToken);
37
+ // CometChatCalls.login(uid, authKey?) takes a UID; to authenticate with a token use loginWithAuthToken:
38
+ await CometChatCalls.loginWithAuthToken(authToken);
38
39
  ```
39
40
 
40
41
  ---
@@ -81,7 +82,7 @@ export class CallEventsService {
81
82
 
82
83
  - [ ] `@cometchat/calls-sdk-javascript@^5` in package.json
83
84
  - [ ] Calls SDK init runs after chat SDK init in `AppInitService`
84
- - [ ] `CometChatCalls.login(authToken)` after `CometChat.login`
85
+ - [ ] `CometChatCalls.loginWithAuthToken(authToken)` after `CometChat.login` (NOT `CometChatCalls.login`, which expects a UID)
85
86
  - [ ] `<cometchat-incoming-call>` rendered at app root (sibling of `router-outlet`)
86
87
  - [ ] All custom `addEventListener` callbacks wrapped in `NgZone.run`
87
88
  - [ ] Run `cometchat verify --calls` — should pass
@@ -10,26 +10,33 @@ Same SDK API as web. Angular wraps layout state in a service so multiple compone
10
10
  ## Layout service
11
11
 
12
12
  ```ts
13
- import { Injectable, NgZone } from "@angular/core";
13
+ import { Injectable, NgZone, OnDestroy } from "@angular/core";
14
14
  import { BehaviorSubject } from "rxjs";
15
15
  import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
16
16
 
17
17
  export type CallLayout = "TILE" | "SIDEBAR" | "SPOTLIGHT";
18
18
 
19
19
  @Injectable({ providedIn: "root" })
20
- export class CallLayoutService {
20
+ export class CallLayoutService implements OnDestroy {
21
21
  readonly layout$ = new BehaviorSubject<CallLayout>("TILE");
22
22
 
23
+ // addEventListener returns an unsubscribe fn — there is NO CometChatCalls.removeEventListener.
24
+ private off: () => void;
25
+
23
26
  constructor(private zone: NgZone) {
24
- CometChatCalls.addEventListener("onCallLayoutChanged", (next: string) => {
27
+ this.off = CometChatCalls.addEventListener("onCallLayoutChanged", (next: string) => {
25
28
  this.zone.run(() => this.layout$.next(next as CallLayout));
26
29
  });
27
30
  }
28
31
 
29
32
  set(layout: CallLayout): void {
30
- CometChatCalls.setLayout(layout);
33
+ CometChatCalls.setLayout(layout); // static runtime layout switch — valid
31
34
  this.layout$.next(layout);
32
35
  }
36
+
37
+ ngOnDestroy(): void {
38
+ this.off();
39
+ }
33
40
  }
34
41
  ```
35
42
 
@@ -65,17 +72,26 @@ export class LayoutSwitcherComponent {
65
72
 
66
73
  ---
67
74
 
68
- ## Pass initial via call settings
75
+ ## Pass initial via session settings
76
+
77
+ `joinSession` takes a **`SessionSettings` object**, not a builder result. The initial layout and
78
+ the change-layout button visibility are plain object fields (`layout`, `hideChangeLayoutButton`).
79
+ The builder has NO `setLayout` (its layout setter is the deprecated `setMode`) and NO
80
+ `setHideChangeLayoutButton`, and its output (`CallSettings`) is not accepted by `joinSession`.
69
81
 
70
82
  ```ts
71
- const callSettings = new CallSettingsBuilder()
72
- .setLayout("SPOTLIGHT")
73
- .setHideChangeLayoutButton(true) // if you ship LayoutSwitcherComponent
74
- .build();
83
+ const sessionSettings = {
84
+ sessionType: "VIDEO",
85
+ layout: "SPOTLIGHT",
86
+ hideChangeLayoutButton: true, // if you ship LayoutSwitcherComponent
87
+ } as const;
75
88
 
76
- await CometChatCalls.joinSession(callToken, callSettings, container.nativeElement);
89
+ await CometChatCalls.joinSession(callToken, sessionSettings, container.nativeElement);
77
90
  ```
78
91
 
92
+ To switch layout at runtime use the static `CometChatCalls.setLayout(layout)` (as the
93
+ `CallLayoutService.set` above does).
94
+
79
95
  ---
80
96
 
81
97
  ## Anti-patterns
@@ -92,8 +108,9 @@ Web sister rules apply, plus Angular-specific:
92
108
 
93
109
  - [ ] `CallLayoutService` provided in root
94
110
  - [ ] `NgZone.run` wraps the SDK callback
95
- - [ ] `mat-button-toggle-group` `(change)` calls `svc.set`
96
- - [ ] Initial layout via `CallSettingsBuilder.setLayout`
111
+ - [ ] `mat-button-toggle-group` `(change)` calls `svc.set` (which calls static `CometChatCalls.setLayout`)
112
+ - [ ] Initial layout via the `SessionSettings` object `{ layout, hideChangeLayoutButton }` passed to `joinSession` (no `CallSettingsBuilder`)
113
+ - [ ] Listener unsubscribe fn captured + called in `ngOnDestroy` (no `removeEventListener`)
97
114
  - [ ] Browser smoke: 3 tabs, each picks a different layout, no cross-talk
98
115
 
99
116
  ---
@@ -1,6 +1,6 @@
1
1
  # Call session — joinSession with no ringing (Angular)
2
2
 
3
- Same SDK API as web. This file mirrors the upstream Angular sample at `~/Downloads/calls-sdk/calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-angular/src/app/pages/join-session/`. Customer-validated against the v5 SDK as the known-good shape.
3
+ Same SDK API as web. This file mirrors the upstream Angular sample at `calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-angular/src/app/pages/join-session/`. Customer-validated against the v5 SDK as the known-good shape.
4
4
 
5
5
  **Read first:** `cometchat-react-calls/references/call-session.md` — full architecture (sessionId strategies, server-side authorization, token generation), then come back here for Angular specialization.
6
6
 
@@ -163,5 +163,5 @@ Read `sessionId` via `ActivatedRoute.snapshot.paramMap.get('sessionId')` in `ngO
163
163
  - `cometchat-react-calls/references/call-session.md` — full architecture (sessionId strategies, server-side authorization)
164
164
  - `cometchat-angular-calls/SKILL.md` — Angular-specific dual-SDK init pattern
165
165
  - `references/ngzone-and-async-callbacks.md` — why NgZone.run matters for SDK events
166
- - Upstream Angular sample — `~/Downloads/calls-sdk/calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-angular/src/app/pages/join-session/`
166
+ - Upstream Angular sample — `calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-angular/src/app/pages/join-session/`
167
167
  - Canonical docs: https://www.cometchat.com/docs/calls/javascript/join-session
@@ -7,7 +7,7 @@ Same architecture as React + RN custom UI; Angular-specific because of NgZone, C
7
7
  ## Two paths
8
8
 
9
9
  1. **Style the kit's selectors** — pass Angular `[input]` props + content projection (`<ng-content select="...">`). Cheapest.
10
- 2. **Build your own component on the SDK** — direct `CometChatCalls.joinSession(token, settings, container)` with your own `<video>` elements wrapped in Angular components. (`startSession` is a deprecated v4 shim use `joinSession`.)
10
+ 2. **Build your own component on the SDK** with your own `<video>` elements wrapped in Angular components. ⚠️ Two join APIs by settings type: **hybrid (hide-chrome)** → `SessionSettings` object + `joinSession`; **fully-custom (`enableDefaultLayout(false)`, own tiles)** `CallSettingsBuilder` + the deprecated `startSession` (joinSession does NOT accept builder output). This reference shows the fully-custom path.
11
11
 
12
12
  This reference covers path 2.
13
13
 
@@ -54,6 +54,8 @@ export class OngoingCallComponent implements OnInit, OnDestroy {
54
54
  constructor(private zone: NgZone) {}
55
55
 
56
56
  async ngOnInit() {
57
+ // ⚠️ CometChatCalls.OngoingCallListener is @deprecated (use addEventListener).
58
+ // It's only here because enableDefaultLayout(false) + startSession require it.
57
59
  this.listener = new CometChatCalls.OngoingCallListener({
58
60
  onUserListUpdated: (users: unknown) => {
59
61
  this.zone.run(() => { /* update roster */ });
@@ -67,18 +69,23 @@ export class OngoingCallComponent implements OnInit, OnDestroy {
67
69
  },
68
70
  });
69
71
 
72
+ // CallSettingsBuilder method names (verified vs calls-sdk-javascript@5):
73
+ // - NO .setSessionID() on the builder — sessionId flows via generateToken()
74
+ // - .setIsAudioOnlyCall(bool), not .setIsAudioOnly()
75
+ // - .setCallListener(listener), not .setCallEventListener()
70
76
  const settings = new CometChatCalls.CallSettingsBuilder()
71
- .setSessionID(this.sessionId)
72
- .setIsAudioOnly(false)
77
+ .setIsAudioOnlyCall(false)
73
78
  .enableDefaultLayout(false)
74
- .setCallEventListener(this.listener)
79
+ .setCallListener(this.listener)
75
80
  .build();
76
81
 
77
- // v5 — generateToken takes ONLY sessionId. Auth is internal after CometChatCalls.login().
82
+ // generateToken takes ONLY sessionId. Auth is internal after CometChatCalls.login().
78
83
  const tokenRes = await CometChatCalls.generateToken(this.sessionId);
79
- // htmlElement is required pass the call container ref.
80
- // joinSession is the v5 canonical startSession is a deprecated shim.
81
- CometChatCalls.joinSession(tokenRes.token, settings, this.callContainerRef.nativeElement);
84
+ // This fully-custom path uses enableDefaultLayout(false), which builds a CallSettings —
85
+ // consumed ONLY by the deprecated startSession. joinSession takes a SessionSettings
86
+ // OBJECT and will NOT accept CallSettingsBuilder output. startSession is the one place
87
+ // the deprecated call is still required (enableDefaultLayout is builder-only).
88
+ CometChatCalls.startSession(tokenRes.token, settings, this.callContainerRef.nativeElement);
82
89
  }
83
90
 
84
91
  ngOnDestroy() {
@@ -87,12 +94,13 @@ export class OngoingCallComponent implements OnInit, OnDestroy {
87
94
 
88
95
  onToggleMute() {
89
96
  this.muted = !this.muted;
90
- CometChatCalls.muteAudio(this.muted);
97
+ // No-arg methods — muteAudio(bool) ignores the arg. Use the explicit pair.
98
+ this.muted ? CometChatCalls.muteAudio() : CometChatCalls.unmuteAudio();
91
99
  }
92
100
 
93
101
  onToggleCamera() {
94
102
  this.cameraOff = !this.cameraOff;
95
- CometChatCalls.pauseVideo(this.cameraOff);
103
+ this.cameraOff ? CometChatCalls.pauseVideo() : CometChatCalls.resumeVideo();
96
104
  }
97
105
 
98
106
  onSwitchCamera() {
@@ -10,22 +10,34 @@ Same JS SDK as web. Angular wraps device-list state in a service with RxJS obser
10
10
  ## Service-driven device lists
11
11
 
12
12
  ```ts
13
- import { Injectable, NgZone } from "@angular/core";
13
+ import { Injectable, NgZone, OnDestroy } from "@angular/core";
14
14
  import { BehaviorSubject } from "rxjs";
15
15
  import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
16
16
 
17
- interface MediaDevice { id: string; label: string; }
17
+ // SDK returns standard DOM MediaDeviceInfo objects — use `.deviceId`, NOT `.id`.
18
18
 
19
19
  @Injectable({ providedIn: "root" })
20
- export class CallDevicesService {
21
- readonly mics$ = new BehaviorSubject<MediaDevice[]>([]);
22
- readonly cameras$ = new BehaviorSubject<MediaDevice[]>([]);
23
- readonly speakers$ = new BehaviorSubject<MediaDevice[]>([]);
20
+ export class CallDevicesService implements OnDestroy {
21
+ readonly mics$ = new BehaviorSubject<MediaDeviceInfo[]>([]);
22
+ readonly cameras$ = new BehaviorSubject<MediaDeviceInfo[]>([]);
23
+ readonly speakers$ = new BehaviorSubject<MediaDeviceInfo[]>([]);
24
+
25
+ // addEventListener returns an unsubscribe fn — there is NO CometChatCalls.removeEventListener.
26
+ private offs: Array<() => void> = [];
24
27
 
25
28
  constructor(private zone: NgZone) {
26
- CometChatCalls.addEventListener("onAudioModesUpdated", () => {
27
- this.zone.run(() => this.refresh());
28
- });
29
+ // Valid device-change event keys (plural = full updated list):
30
+ this.offs.push(
31
+ CometChatCalls.addEventListener("onAudioInputDevicesChanged", () => {
32
+ this.zone.run(() => this.refresh());
33
+ }),
34
+ CometChatCalls.addEventListener("onAudioOutputDevicesChanged", () => {
35
+ this.zone.run(() => this.refresh());
36
+ }),
37
+ CometChatCalls.addEventListener("onVideoInputDevicesChanged", () => {
38
+ this.zone.run(() => this.refresh());
39
+ }),
40
+ );
29
41
  }
30
42
 
31
43
  async ensurePermission(): Promise<void> {
@@ -37,25 +49,27 @@ export class CallDevicesService {
37
49
  }
38
50
  }
39
51
 
40
- async refresh(): Promise<void> {
41
- const [mics, cameras, speakers] = await Promise.all([
42
- CometChatCalls.getAudioInputDevices(),
43
- CometChatCalls.getVideoInputDevices(),
44
- CometChatCalls.getAudioOutputDevices(),
45
- ]);
46
- this.mics$.next(mics);
47
- this.cameras$.next(cameras);
48
- this.speakers$.next(speakers);
52
+ // Device getters are SYNCHRONOUS — they return arrays, not Promises. No await / Promise.all.
53
+ refresh(): void {
54
+ this.mics$.next(CometChatCalls.getAudioInputDevices());
55
+ this.cameras$.next(CometChatCalls.getVideoInputDevices());
56
+ this.speakers$.next(CometChatCalls.getAudioOutputDevices());
49
57
  }
50
58
 
51
- async selectMic(id: string): Promise<void> {
52
- await CometChatCalls.setAudioInputDevice(id);
59
+ // Setters are SYNCHRONOUS void — no await. They take the deviceId string.
60
+ selectMic(deviceId: string): void {
61
+ CometChatCalls.setAudioInputDevice(deviceId);
62
+ }
63
+ selectCamera(deviceId: string): void {
64
+ CometChatCalls.setVideoInputDevice(deviceId);
53
65
  }
54
- async selectCamera(id: string): Promise<void> {
55
- await CometChatCalls.setVideoInputDevice(id);
66
+ selectSpeaker(deviceId: string): void {
67
+ CometChatCalls.setAudioOutputDevice(deviceId);
56
68
  }
57
- async selectSpeaker(id: string): Promise<void> {
58
- await CometChatCalls.setAudioOutputDevice(id);
69
+
70
+ ngOnDestroy(): void {
71
+ this.offs.forEach(off => off()); // call the captured unsubscribe fns
72
+ this.offs = [];
59
73
  }
60
74
  }
61
75
  ```
@@ -71,8 +85,8 @@ export class CallDevicesService {
71
85
  <form (ngSubmit)="confirm()">
72
86
  <label>Microphone
73
87
  <select [(ngModel)]="selectedMic" name="mic">
74
- <option *ngFor="let d of mics$ | async" [value]="d.id">
75
- {{ d.label || ('Mic ' + d.id.substring(0, 6)) }}
88
+ <option *ngFor="let d of mics$ | async" [value]="d.deviceId">
89
+ {{ d.label || ('Mic ' + d.deviceId.substring(0, 6)) }}
76
90
  </option>
77
91
  </select>
78
92
  </label>
@@ -92,14 +106,14 @@ export class DevicePickerComponent implements OnInit {
92
106
  constructor(private devices: CallDevicesService) {}
93
107
 
94
108
  async ngOnInit() {
95
- await this.devices.ensurePermission();
96
- await this.devices.refresh();
109
+ await this.devices.ensurePermission(); // getUserMedia IS async
110
+ this.devices.refresh(); // device list reads are sync
97
111
  }
98
112
 
99
- async confirm() {
100
- if (this.selectedMic) await this.devices.selectMic(this.selectedMic);
101
- if (this.selectedCamera) await this.devices.selectCamera(this.selectedCamera);
102
- if (this.selectedSpeaker) await this.devices.selectSpeaker(this.selectedSpeaker);
113
+ confirm() {
114
+ if (this.selectedMic) this.devices.selectMic(this.selectedMic);
115
+ if (this.selectedCamera) this.devices.selectCamera(this.selectedCamera);
116
+ if (this.selectedSpeaker) this.devices.selectSpeaker(this.selectedSpeaker);
103
117
  }
104
118
  }
105
119
  ```
@@ -110,16 +124,21 @@ export class DevicePickerComponent implements OnInit {
110
124
 
111
125
  Web sister rules apply, plus Angular-specific:
112
126
 
113
- 1. **No `NgZone.run` wrap on `onAudioModesUpdated`.** BehaviorSubject emits but UI doesn't update with OnPush.
127
+ 1. **No `NgZone.run` wrap on the device-change events.** BehaviorSubject emits but UI doesn't update with OnPush.
114
128
  2. **Service NOT provided in `root`.** Lazy-loaded → device events miss.
115
129
  3. **`async pipe` not used.** Manual `subscribe` without `unsubscribe` leaks.
130
+ 4. **`await`-ing the device getters/setters.** They are synchronous (`getAudioInputDevices()` returns `MediaDeviceInfo[]`; setters return `void`). `await` on them is a no-op that masks the real (sync) signature.
131
+ 5. **Reading `device.id`.** The SDK returns DOM `MediaDeviceInfo` — the identifier is `device.deviceId`.
132
+ 6. **Expecting `CometChatCalls.removeEventListener`.** It does not exist. `addEventListener` returns a `() => void`; capture and call it to clean up.
116
133
 
117
134
  ---
118
135
 
119
136
  ## Verification checklist
120
137
 
121
138
  - [ ] `CallDevicesService` provided in root
122
- - [ ] `NgZone.run` wraps the device-update event
139
+ - [ ] `NgZone.run` wraps the device-update events (`onAudioInputDevicesChanged` / `onAudioOutputDevicesChanged` / `onVideoInputDevicesChanged`)
140
+ - [ ] Listener unsubscribe fns captured and called in `ngOnDestroy` (no `removeEventListener`)
141
+ - [ ] Device getters/setters called WITHOUT `await` (they are sync); options use `device.deviceId`
123
142
  - [ ] Picker uses `async` pipe (not manual subscribe)
124
143
  - [ ] `ensurePermission()` called before `refresh()` (empty-label fix)
125
144
  - [ ] Browser smoke: plug/unplug headphones during call → list updates
@@ -1,6 +1,8 @@
1
1
  # Group calls (meetings) on Angular
2
2
 
3
- Angular wraps the same JS Calls SDK as React/Vue/Svelte; the SDK semantics are identical. The wiring differences are Angular-specific: NgZone for active-speaker updates, `@Input` / `@Output` patterns for participant components, OnPush + `markForCheck` for roster changes.
3
+ Angular wraps the same JS Calls SDK as React/Vue/Svelte; the SDK semantics are identical. The wiring differences are Angular-specific: NgZone for dominant-speaker updates, `@Input` / `@Output` patterns for participant components, OnPush + `markForCheck` for roster changes.
4
+
5
+ > **v5 event note.** `CometChatCalls.OngoingCallListener` is `@deprecated` in calls-sdk-javascript v5 (use `CometChatCalls.addEventListener(...)`). It still works for roster events (`onUserJoined` / `onUserLeft` / `onUserListUpdated` / `onCallEnded` / `onError`), but there is **no `onActiveSpeakerUpdated` callback on the listener** — the dominant-speaker signal is only available as the `addEventListener` event key `onDominantSpeakerChanged`. The examples below use `addEventListener` for dominant speaker and may keep the listener for roster events.
4
6
 
5
7
  For SDK-level semantics — capacity limits, bandwidth scaling, moderator actions — see `cometchat-native-calls/references/group-calls.md`. This reference covers the Angular-specific patterns.
6
8
 
@@ -160,7 +162,10 @@ export class GroupCallComponent implements OnInit, OnDestroy {
160
162
 
161
163
  constructor(private zone: NgZone, private cd: ChangeDetectorRef) {}
162
164
 
165
+ private offSpeaker?: () => void;
166
+
163
167
  ngOnInit() {
168
+ // Roster via the (deprecated but functional) OngoingCallListener:
164
169
  const listener = new CometChatCalls.OngoingCallListener({
165
170
  onUserListUpdated: (users: Participant[]) => {
166
171
  this.zone.run(() => {
@@ -169,14 +174,24 @@ export class GroupCallComponent implements OnInit, OnDestroy {
169
174
  this.cd.markForCheck(); // OnPush — must mark
170
175
  });
171
176
  },
172
- onActiveSpeakerUpdated: (uid: string) => {
177
+ });
178
+
179
+ // Dominant speaker is NOT a listener callback — subscribe via addEventListener.
180
+ // addEventListener returns an unsubscribe fn (there is no removeEventListener).
181
+ this.offSpeaker = CometChatCalls.addEventListener(
182
+ "onDominantSpeakerChanged",
183
+ (participant: { uid: string }) => {
173
184
  this.zone.run(() => {
174
- // Debounce — see "Debouncing active-speaker" below
175
- this.scheduleSpeakerSwap(uid);
185
+ // Debounce — see "Debouncing dominant-speaker" below
186
+ this.scheduleSpeakerSwap(participant.uid);
176
187
  });
177
188
  },
178
- });
179
- // ... build CallSettings, startSession ...
189
+ );
190
+ // ... pass a SessionSettings object + call token to CometChatCalls.joinSession ...
191
+ }
192
+
193
+ ngOnDestroy() {
194
+ this.offSpeaker?.();
180
195
  }
181
196
 
182
197
  trackByUid(_: number, p: Participant) {
@@ -209,9 +224,9 @@ export class GroupCallComponent implements OnInit, OnDestroy {
209
224
 
210
225
  ---
211
226
 
212
- ## Debouncing active-speaker
227
+ ## Debouncing dominant-speaker
213
228
 
214
- Same rule as RN — `onActiveSpeakerUpdated` can fire many times per second in a noisy call. Debounce to 500ms minimum:
229
+ Same rule as RN — `onDominantSpeakerChanged` can fire many times per second in a noisy call. Debounce to 500ms minimum:
215
230
 
216
231
  ```ts
217
232
  private speakerSwapTimeout: ReturnType<typeof setTimeout> | null = null;
@@ -241,9 +256,11 @@ ngOnInit() {
241
256
  this.zone.run(() => { this.activeSpeakerUid = uid; this.recomputeLayout(); this.cd.markForCheck(); });
242
257
  });
243
258
 
244
- const listener = new CometChatCalls.OngoingCallListener({
245
- onActiveSpeakerUpdated: (uid: string) => this.speakerSubject.next(uid),
246
- });
259
+ // Dominant speaker comes from addEventListener, not the listener object:
260
+ this.offSpeaker = CometChatCalls.addEventListener(
261
+ "onDominantSpeakerChanged",
262
+ (participant: { uid: string }) => this.speakerSubject.next(participant.uid),
263
+ );
247
264
  }
248
265
  ```
249
266
 
@@ -251,25 +268,28 @@ ngOnInit() {
251
268
 
252
269
  ## Moderator actions — guarded by group scope
253
270
 
271
+ The v5 SDK exposes **`CometChatCalls.muteParticipant(participantId)`** (sync, void) — there is
272
+ no `muteUser` / `removeUser`. **There is NO kick/remove-participant API in the JS Calls SDK** —
273
+ removal must be done at the chat layer (e.g. `CometChat.kickGroupMember`), not via the Calls SDK.
274
+
254
275
  ```ts
255
276
  // In your component or a CallControlsService
256
- async muteParticipant(uid: string) {
277
+ muteParticipant(participantId: string) {
257
278
  if (!this.canModerate()) return;
258
- await CometChatCalls.muteUser(uid);
279
+ CometChatCalls.muteParticipant(participantId); // sync, void — no await
259
280
  }
260
281
 
261
- async kickParticipant(uid: string) {
262
- if (!this.canModerate()) return;
263
- await CometChatCalls.removeUser(uid);
264
- }
265
-
266
- async muteAll() {
282
+ muteAll() {
267
283
  if (!this.canModerate()) return;
268
284
  for (const p of this.others) {
269
- await CometChatCalls.muteUser(p.uid);
285
+ CometChatCalls.muteParticipant(p.uid);
270
286
  }
271
287
  }
272
288
 
289
+ // NOTE: no kick/remove API exists in @cometchat/calls-sdk-javascript.
290
+ // To eject someone, remove them from the group via the Chat SDK
291
+ // (CometChat.kickGroupMember(...)) — they then lose access to the session.
292
+
273
293
  private canModerate(): boolean {
274
294
  const scope = this.group?.getScope();
275
295
  return scope === "admin" || scope === "moderator";
@@ -281,7 +301,7 @@ Hide the moderator-only buttons in the template:
281
301
  ```html
282
302
  <div *ngIf="canModerate()" class="moderator-controls">
283
303
  <button (click)="muteAll()">Mute all</button>
284
- <button (click)="kickParticipant(p.uid)" *ngFor="let p of others">Kick</button>
304
+ <button (click)="muteParticipant(p.uid)" *ngFor="let p of others">Mute</button>
285
305
  </div>
286
306
  ```
287
307
 
@@ -321,7 +341,7 @@ async observeBattery() {
321
341
  const check = () => {
322
342
  if (battery.level < 0.2 && this.callActive) {
323
343
  this.zone.run(() => {
324
- CometChatCalls.pauseVideo(true);
344
+ CometChatCalls.pauseVideo(); // no-arg in v5 (pauses local video)
325
345
  this.snackBar.open("Video paused — low battery", "Dismiss", { duration: 5000 });
326
346
  });
327
347
  }
@@ -382,8 +402,9 @@ ngOnInit() {
382
402
 
383
403
  1. **Roster updates without `trackByUid`** in `*ngFor`. Tiles re-create; video tracks die.
384
404
  2. **Skipping `markForCheck`** with OnPush. Roster updates don't render.
385
- 3. **No debounce on active-speaker.** Tiles jitter at 5+ Hz.
405
+ 3. **No debounce on dominant-speaker.** Tiles jitter at 5+ Hz.
386
406
  4. **Moderator buttons rendered for non-moderators.** SDK rejects but UI is misleading.
407
+ (Remember: only `muteParticipant` exists — there is no kick/remove in the Calls SDK.)
387
408
  5. **`getBattery()` without feature detect.** Firefox/Safari throws.
388
409
  6. **Leaving the call doesn't unsubscribe RxJS subjects.** Memory leak across multiple call sessions.
389
410
  7. **Group call from a lazy-loaded module.** CallInitService must be eager (cf. `references/lazy-loading-pitfalls.md`).
@@ -394,7 +415,7 @@ ngOnInit() {
394
415
 
395
416
  - [ ] `*ngFor` over participants uses `trackBy: trackByUid`
396
417
  - [ ] OnPush components call `cd.markForCheck()` on roster updates
397
- - [ ] Active-speaker updates debounced ≥500ms
418
+ - [ ] Dominant-speaker updates (via `addEventListener("onDominantSpeakerChanged", …)`) debounced ≥500ms
398
419
  - [ ] All SDK callbacks wrapped in `zone.run`
399
420
  - [ ] Moderator controls hidden for non-moderator scopes
400
421
  - [ ] Capacity error handled (`ERR_CALL_FULL`) with user-facing snackbar
@@ -9,19 +9,37 @@ Same SDK API as web. Angular-specific delta: NgZone wrap on the timeout event +
9
9
 
10
10
  ## SDK API
11
11
 
12
- ```ts
13
- const settings = new CometChatCalls.CallSettingsBuilder()
14
- .setSessionID(sessionId)
15
- .setIdleTimeoutPeriodBeforePrompt(60_000)
16
- .setIdleTimeoutPeriodAfterPrompt(120_000)
17
- .build();
12
+ The idle timeout is configured on the **`SessionSettings` object** passed to
13
+ `joinSession(callToken, sessionSettings, container)`, NOT on the builder.
14
+
15
+ - The builder (`CallSettingsBuilder`) has a single `setIdleTimeoutPeriod(ms)` method — there is
16
+ no `setIdleTimeoutPeriodBeforePrompt` / `setIdleTimeoutPeriodAfterPrompt` on it.
17
+ - The before/after split exists ONLY as `SessionSettings` object fields:
18
+ `idleTimeoutPeriodBeforePrompt` and `idleTimeoutPeriodAfterPrompt`.
19
+ - There is no `setSessionID()` on the builder — the session is identified by the call token
20
+ produced via `CometChatCalls.generateToken(sessionId, authToken)`.
18
21
 
19
- CometChatCalls.addEventListener("onSessionTimedOut", () => {
22
+ ```ts
23
+ // 1. token carries the session id
24
+ const { token } = await CometChatCalls.generateToken(sessionId, authToken);
25
+
26
+ // 2. idle timeout lives on the SessionSettings object
27
+ const sessionSettings = {
28
+ sessionType: "VIDEO",
29
+ idleTimeoutPeriodBeforePrompt: 60_000,
30
+ idleTimeoutPeriodAfterPrompt: 120_000,
31
+ } as const;
32
+
33
+ // addEventListener returns an unsubscribe fn — capture it (there is no removeEventListener).
34
+ const off = CometChatCalls.addEventListener("onSessionTimedOut", () => {
20
35
  this.zone.run(() => {
21
36
  this.router.navigate(["/"]);
22
37
  this.snackBar.open("Call ended due to inactivity", "Dismiss", { duration: 5000 });
23
38
  });
24
39
  });
40
+
41
+ await CometChatCalls.joinSession(token, sessionSettings, container);
42
+ // later: off();
25
43
  ```
26
44
 
27
45
  `NgZone.run` wrap is mandatory — without it, the navigation + snackbar don't fire because the SDK callback is outside Angular's zone.
@@ -39,7 +57,8 @@ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
39
57
 
40
58
  @Injectable({ providedIn: "root" })
41
59
  export class IdleTimeoutService {
42
- private listener?: () => void;
60
+ // addEventListener returns the unsubscribe fn — there is no CometChatCalls.removeEventListener.
61
+ private off?: () => void;
43
62
 
44
63
  constructor(
45
64
  private zone: NgZone,
@@ -48,20 +67,17 @@ export class IdleTimeoutService {
48
67
  ) {}
49
68
 
50
69
  attachToCallSession() {
51
- this.listener = () => {
70
+ this.off = CometChatCalls.addEventListener("onSessionTimedOut", () => {
52
71
  this.zone.run(() => {
53
72
  this.router.navigate(["/"]);
54
73
  this.snackBar.open("Call ended due to inactivity", "Dismiss", { duration: 5000 });
55
74
  });
56
- };
57
- CometChatCalls.addEventListener("onSessionTimedOut", this.listener);
75
+ });
58
76
  }
59
77
 
60
78
  detach() {
61
- if (this.listener) {
62
- CometChatCalls.removeEventListener("onSessionTimedOut", this.listener);
63
- this.listener = undefined;
64
- }
79
+ this.off?.();
80
+ this.off = undefined;
65
81
  }
66
82
  }
67
83
  ```
@@ -56,6 +56,8 @@ All Calls SDK event listeners. The kit's own components handle this internally;
56
56
 
57
57
  Conservative rule: **wrap every callback that mutates UI state** in `zone.run`.
58
58
 
59
+ > `CometChatCalls.OngoingCallListener` is `@deprecated` in calls-sdk-javascript v5 (prefer `CometChatCalls.addEventListener(...)`); the listener pattern below still works and is shown here because this reference is about NgZone-wrapping. Note that the dominant-speaker signal is NOT a listener callback — subscribe to it via `addEventListener("onDominantSpeakerChanged", …)` (also wrap that handler in `zone.run`).
60
+
59
61
  ```ts
60
62
  const listener = new CometChatCalls.OngoingCallListener({
61
63
  onUserListUpdated: (userList) => {
@@ -67,12 +69,11 @@ const listener = new CometChatCalls.OngoingCallListener({
67
69
  onError: (err) => {
68
70
  this.zone.run(() => { this.errorMessage = err.message; });
69
71
  },
70
- onActiveSpeakerUpdated: (uid) => {
71
- this.zone.run(() => { this.activeSpeakerUid = uid; });
72
- },
73
- onMediaDeviceListUpdated: (devices) => {
74
- this.zone.run(() => { this.devices = devices; });
75
- },
72
+ });
73
+
74
+ // Dominant speaker is an addEventListener event key, not a listener callback:
75
+ const offSpeaker = CometChatCalls.addEventListener("onDominantSpeakerChanged", (p) => {
76
+ this.zone.run(() => { this.activeSpeakerUid = p.uid; });
76
77
  });
77
78
  ```
78
79
 
@@ -49,14 +49,19 @@ export class RaiseHandService implements OnDestroy {
49
49
  });
50
50
  };
51
51
 
52
+ // addEventListener returns an unsubscribe fn — there is NO CometChatCalls.removeEventListener.
53
+ private offs: Array<() => void> = [];
54
+
52
55
  constructor(private zone: NgZone) {
53
- CometChatCalls.addEventListener("onParticipantHandRaised", this.onRaised);
54
- CometChatCalls.addEventListener("onParticipantHandLowered", this.onLowered);
56
+ this.offs.push(
57
+ CometChatCalls.addEventListener("onParticipantHandRaised", this.onRaised),
58
+ CometChatCalls.addEventListener("onParticipantHandLowered", this.onLowered),
59
+ );
55
60
  }
56
61
 
57
62
  ngOnDestroy() {
58
- CometChatCalls.removeEventListener("onParticipantHandRaised", this.onRaised);
59
- CometChatCalls.removeEventListener("onParticipantHandLowered", this.onLowered);
63
+ this.offs.forEach(off => off());
64
+ this.offs = [];
60
65
  }
61
66
 
62
67
  raise() { CometChatCalls.raiseHand(); }