@cometchat/skills 4.0.0 → 4.2.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 (258) hide show
  1. package/README.md +42 -2
  2. package/bin/install.js +448 -57
  3. package/package.json +1 -1
  4. package/skills/cometchat/SKILL.md +337 -80
  5. package/skills/cometchat-a11y/SKILL.md +476 -0
  6. package/skills/cometchat-android-v5/SKILL.md +1 -1
  7. package/skills/cometchat-android-v5-calls/SKILL.md +413 -0
  8. package/skills/cometchat-android-v5-calls/references/README.md +53 -0
  9. package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +195 -0
  10. package/skills/cometchat-android-v5-calls/references/audio-controls.md +91 -0
  11. package/skills/cometchat-android-v5-calls/references/background-handling.md +168 -0
  12. package/skills/cometchat-android-v5-calls/references/call-layouts.md +123 -0
  13. package/skills/cometchat-android-v5-calls/references/call-logs.md +113 -0
  14. package/skills/cometchat-android-v5-calls/references/call-session.md +274 -0
  15. package/skills/cometchat-android-v5-calls/references/custom-ui.md +150 -0
  16. package/skills/cometchat-android-v5-calls/references/event-listeners.md +123 -0
  17. package/skills/cometchat-android-v5-calls/references/group-calls.md +205 -0
  18. package/skills/cometchat-android-v5-calls/references/idle-timeout.md +111 -0
  19. package/skills/cometchat-android-v5-calls/references/in-call-chat.md +134 -0
  20. package/skills/cometchat-android-v5-calls/references/join-session.md +120 -0
  21. package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +206 -0
  22. package/skills/cometchat-android-v5-calls/references/participant-management.md +110 -0
  23. package/skills/cometchat-android-v5-calls/references/picture-in-picture.md +106 -0
  24. package/skills/cometchat-android-v5-calls/references/raise-hand.md +242 -0
  25. package/skills/cometchat-android-v5-calls/references/recording.md +101 -0
  26. package/skills/cometchat-android-v5-calls/references/ringing-integration.md +152 -0
  27. package/skills/cometchat-android-v5-calls/references/screen-sharing.md +82 -0
  28. package/skills/cometchat-android-v5-calls/references/server-fcm-voip.md +215 -0
  29. package/skills/cometchat-android-v5-calls/references/session-settings.md +121 -0
  30. package/skills/cometchat-android-v5-calls/references/setup.md +137 -0
  31. package/skills/cometchat-android-v5-calls/references/share-invite.md +151 -0
  32. package/skills/cometchat-android-v5-calls/references/video-controls.md +87 -0
  33. package/skills/cometchat-android-v5-calls/references/voip-calling.md +526 -0
  34. package/skills/cometchat-android-v5-components/SKILL.md +1 -1
  35. package/skills/cometchat-android-v5-core/SKILL.md +1 -1
  36. package/skills/cometchat-android-v5-customization/SKILL.md +1 -1
  37. package/skills/cometchat-android-v5-extensions/SKILL.md +1 -1
  38. package/skills/cometchat-android-v5-features/SKILL.md +1 -1
  39. package/skills/cometchat-android-v5-placement/SKILL.md +1 -1
  40. package/skills/cometchat-android-v5-production/SKILL.md +1 -1
  41. package/skills/cometchat-android-v5-push/SKILL.md +1 -1
  42. package/skills/cometchat-android-v5-testing/SKILL.md +1 -1
  43. package/skills/cometchat-android-v5-theming/SKILL.md +1 -1
  44. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +1 -1
  45. package/skills/cometchat-android-v6/SKILL.md +1 -1
  46. package/skills/cometchat-android-v6-builder-settings/SKILL.md +1 -1
  47. package/skills/cometchat-android-v6-calls/SKILL.md +375 -0
  48. package/skills/cometchat-android-v6-calls/references/add-calls-to-existing-chat.md +97 -0
  49. package/skills/cometchat-android-v6-calls/references/call-layouts.md +91 -0
  50. package/skills/cometchat-android-v6-calls/references/call-session.md +163 -0
  51. package/skills/cometchat-android-v6-calls/references/device-management.md +171 -0
  52. package/skills/cometchat-android-v6-calls/references/group-calls.md +191 -0
  53. package/skills/cometchat-android-v6-calls/references/idle-timeout.md +107 -0
  54. package/skills/cometchat-android-v6-calls/references/in-call-chat.md +136 -0
  55. package/skills/cometchat-android-v6-calls/references/raise-hand.md +186 -0
  56. package/skills/cometchat-android-v6-calls/references/ringing-integration.md +176 -0
  57. package/skills/cometchat-android-v6-calls/references/server-fcm-voip.md +127 -0
  58. package/skills/cometchat-android-v6-calls/references/share-invite.md +105 -0
  59. package/skills/cometchat-android-v6-compose-components/SKILL.md +2 -2
  60. package/skills/cometchat-android-v6-compose-customization/SKILL.md +1 -1
  61. package/skills/cometchat-android-v6-compose-placement/SKILL.md +1 -1
  62. package/skills/cometchat-android-v6-compose-theming/SKILL.md +1 -1
  63. package/skills/cometchat-android-v6-core/SKILL.md +1 -1
  64. package/skills/cometchat-android-v6-events/SKILL.md +1 -1
  65. package/skills/cometchat-android-v6-extensions/SKILL.md +1 -1
  66. package/skills/cometchat-android-v6-features/SKILL.md +1 -1
  67. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +1 -1
  68. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +1 -1
  69. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +1 -1
  70. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +1 -1
  71. package/skills/cometchat-android-v6-migration/SKILL.md +398 -0
  72. package/skills/cometchat-android-v6-production/SKILL.md +1 -1
  73. package/skills/cometchat-android-v6-push/SKILL.md +1 -1
  74. package/skills/cometchat-android-v6-testing/SKILL.md +1 -1
  75. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +1 -1
  76. package/skills/cometchat-angular-calls/SKILL.md +511 -0
  77. package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +95 -0
  78. package/skills/cometchat-angular-calls/references/call-layouts.md +106 -0
  79. package/skills/cometchat-angular-calls/references/call-session.md +167 -0
  80. package/skills/cometchat-angular-calls/references/custom-ui.md +231 -0
  81. package/skills/cometchat-angular-calls/references/device-management.md +135 -0
  82. package/skills/cometchat-angular-calls/references/group-calls.md +412 -0
  83. package/skills/cometchat-angular-calls/references/idle-timeout.md +145 -0
  84. package/skills/cometchat-angular-calls/references/in-call-chat.md +148 -0
  85. package/skills/cometchat-angular-calls/references/lazy-loading-pitfalls.md +205 -0
  86. package/skills/cometchat-angular-calls/references/migration-v4-to-v5.md +53 -0
  87. package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +183 -0
  88. package/skills/cometchat-angular-calls/references/picture-in-picture.md +285 -0
  89. package/skills/cometchat-angular-calls/references/raise-hand.md +167 -0
  90. package/skills/cometchat-angular-calls/references/recording-screen-share.md +267 -0
  91. package/skills/cometchat-angular-calls/references/ringing-integration.md +131 -0
  92. package/skills/cometchat-angular-calls/references/server-web-push-vapid.md +100 -0
  93. package/skills/cometchat-angular-calls/references/share-invite.md +116 -0
  94. package/skills/cometchat-angular-components/SKILL.md +1 -1
  95. package/skills/cometchat-angular-core/SKILL.md +1 -1
  96. package/skills/cometchat-angular-customization/SKILL.md +1 -1
  97. package/skills/cometchat-angular-features/SKILL.md +1 -1
  98. package/skills/cometchat-angular-patterns/SKILL.md +1 -1
  99. package/skills/cometchat-angular-placement/SKILL.md +1 -1
  100. package/skills/cometchat-angular-production/SKILL.md +1 -1
  101. package/skills/cometchat-angular-push/SKILL.md +403 -0
  102. package/skills/cometchat-angular-testing/SKILL.md +333 -0
  103. package/skills/cometchat-angular-theming/SKILL.md +1 -1
  104. package/skills/cometchat-angular-troubleshooting/SKILL.md +1 -1
  105. package/skills/cometchat-astro-patterns/SKILL.md +1 -1
  106. package/skills/cometchat-calls/SKILL.md +358 -0
  107. package/skills/cometchat-calls/references/use-case-broadcast.md +194 -0
  108. package/skills/cometchat-calls/references/use-case-marketplace.md +158 -0
  109. package/skills/cometchat-calls/references/use-case-support.md +190 -0
  110. package/skills/cometchat-calls/references/use-case-team.md +169 -0
  111. package/skills/cometchat-calls/references/use-case-telehealth.md +154 -0
  112. package/skills/cometchat-components/SKILL.md +1 -1
  113. package/skills/cometchat-core/SKILL.md +1 -1
  114. package/skills/cometchat-customization/SKILL.md +2 -2
  115. package/skills/cometchat-features/SKILL.md +2 -2
  116. package/skills/cometchat-flutter-v5/SKILL.md +1 -1
  117. package/skills/cometchat-flutter-v5-calls/SKILL.md +325 -94
  118. package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +169 -0
  119. package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +98 -0
  120. package/skills/cometchat-flutter-v5-calls/references/call-session.md +330 -0
  121. package/skills/cometchat-flutter-v5-calls/references/device-management.md +120 -0
  122. package/skills/cometchat-flutter-v5-calls/references/group-calls.md +187 -0
  123. package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +97 -0
  124. package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +132 -0
  125. package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +160 -0
  126. package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +244 -0
  127. package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +193 -0
  128. package/skills/cometchat-flutter-v5-calls/references/server-push-bridge.md +101 -0
  129. package/skills/cometchat-flutter-v5-calls/references/share-invite.md +142 -0
  130. package/skills/cometchat-flutter-v5-conversations/SKILL.md +1 -1
  131. package/skills/cometchat-flutter-v5-core/SKILL.md +1 -1
  132. package/skills/cometchat-flutter-v5-customization/SKILL.md +1 -1
  133. package/skills/cometchat-flutter-v5-events/SKILL.md +1 -1
  134. package/skills/cometchat-flutter-v5-messages/SKILL.md +1 -1
  135. package/skills/cometchat-flutter-v5-production/SKILL.md +1 -1
  136. package/skills/cometchat-flutter-v5-push/SKILL.md +1 -1
  137. package/skills/cometchat-flutter-v5-testing/SKILL.md +390 -0
  138. package/skills/cometchat-flutter-v5-theming/SKILL.md +1 -1
  139. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +1 -1
  140. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +1 -1
  141. package/skills/cometchat-flutter-v6/SKILL.md +1 -1
  142. package/skills/cometchat-flutter-v6-calls/SKILL.md +308 -243
  143. package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +134 -0
  144. package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +102 -0
  145. package/skills/cometchat-flutter-v6-calls/references/call-session.md +229 -0
  146. package/skills/cometchat-flutter-v6-calls/references/device-management.md +99 -0
  147. package/skills/cometchat-flutter-v6-calls/references/group-calls.md +190 -0
  148. package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +80 -0
  149. package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +122 -0
  150. package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +268 -0
  151. package/skills/cometchat-flutter-v6-calls/references/ringing-integration.md +171 -0
  152. package/skills/cometchat-flutter-v6-calls/references/server-push-bridge.md +93 -0
  153. package/skills/cometchat-flutter-v6-calls/references/share-invite.md +102 -0
  154. package/skills/cometchat-flutter-v6-components/SKILL.md +1 -1
  155. package/skills/cometchat-flutter-v6-conversations/SKILL.md +1 -1
  156. package/skills/cometchat-flutter-v6-core/SKILL.md +1 -1
  157. package/skills/cometchat-flutter-v6-customization/SKILL.md +1 -1
  158. package/skills/cometchat-flutter-v6-events/SKILL.md +1 -1
  159. package/skills/cometchat-flutter-v6-features/SKILL.md +1 -1
  160. package/skills/cometchat-flutter-v6-messages/SKILL.md +1 -1
  161. package/skills/cometchat-flutter-v6-migration/SKILL.md +1 -1
  162. package/skills/cometchat-flutter-v6-placement/SKILL.md +1 -1
  163. package/skills/cometchat-flutter-v6-production/SKILL.md +1 -1
  164. package/skills/cometchat-flutter-v6-push/SKILL.md +452 -0
  165. package/skills/cometchat-flutter-v6-testing/SKILL.md +319 -0
  166. package/skills/cometchat-flutter-v6-theming/SKILL.md +1 -1
  167. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +1 -1
  168. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +1 -1
  169. package/skills/cometchat-i18n/SKILL.md +358 -0
  170. package/skills/cometchat-ios/SKILL.md +5 -5
  171. package/skills/cometchat-ios-calls/SKILL.md +409 -0
  172. package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +172 -0
  173. package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +189 -0
  174. package/skills/cometchat-ios-calls/references/call-layouts.md +136 -0
  175. package/skills/cometchat-ios-calls/references/call-session.md +221 -0
  176. package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +353 -0
  177. package/skills/cometchat-ios-calls/references/custom-ui.md +322 -0
  178. package/skills/cometchat-ios-calls/references/device-management.md +171 -0
  179. package/skills/cometchat-ios-calls/references/group-calls.md +396 -0
  180. package/skills/cometchat-ios-calls/references/idle-timeout.md +185 -0
  181. package/skills/cometchat-ios-calls/references/in-call-chat.md +183 -0
  182. package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +138 -0
  183. package/skills/cometchat-ios-calls/references/picture-in-picture.md +246 -0
  184. package/skills/cometchat-ios-calls/references/raise-hand.md +239 -0
  185. package/skills/cometchat-ios-calls/references/recording-screen-share.md +339 -0
  186. package/skills/cometchat-ios-calls/references/ringing-integration.md +142 -0
  187. package/skills/cometchat-ios-calls/references/server-apns-pushkit.md +267 -0
  188. package/skills/cometchat-ios-calls/references/share-invite.md +152 -0
  189. package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +246 -0
  190. package/skills/cometchat-ios-calls/references/voip-cert-setup.md +166 -0
  191. package/skills/cometchat-ios-components/SKILL.md +1 -1
  192. package/skills/cometchat-ios-core/SKILL.md +1 -1
  193. package/skills/cometchat-ios-customization/SKILL.md +1 -1
  194. package/skills/cometchat-ios-features/SKILL.md +1 -1
  195. package/skills/cometchat-ios-placement/SKILL.md +1 -1
  196. package/skills/cometchat-ios-production/SKILL.md +1 -1
  197. package/skills/cometchat-ios-push/SKILL.md +1 -1
  198. package/skills/cometchat-ios-testing/SKILL.md +371 -0
  199. package/skills/cometchat-ios-theming/SKILL.md +1 -1
  200. package/skills/cometchat-ios-troubleshooting/SKILL.md +1 -1
  201. package/skills/cometchat-native-bare-patterns/SKILL.md +45 -3
  202. package/skills/cometchat-native-calls/SKILL.md +599 -0
  203. package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +203 -0
  204. package/skills/cometchat-native-calls/references/call-layouts.md +124 -0
  205. package/skills/cometchat-native-calls/references/call-session.md +182 -0
  206. package/skills/cometchat-native-calls/references/custom-ui.md +250 -0
  207. package/skills/cometchat-native-calls/references/device-management.md +135 -0
  208. package/skills/cometchat-native-calls/references/expo-vs-bare.md +179 -0
  209. package/skills/cometchat-native-calls/references/group-calls.md +291 -0
  210. package/skills/cometchat-native-calls/references/idle-timeout.md +128 -0
  211. package/skills/cometchat-native-calls/references/in-call-chat.md +143 -0
  212. package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +72 -0
  213. package/skills/cometchat-native-calls/references/picture-in-picture.md +276 -0
  214. package/skills/cometchat-native-calls/references/raise-hand.md +203 -0
  215. package/skills/cometchat-native-calls/references/recording-screen-share.md +290 -0
  216. package/skills/cometchat-native-calls/references/ringing-integration.md +118 -0
  217. package/skills/cometchat-native-calls/references/server-push-bridge.md +135 -0
  218. package/skills/cometchat-native-calls/references/server-push-payloads.md +193 -0
  219. package/skills/cometchat-native-calls/references/share-invite.md +144 -0
  220. package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +317 -0
  221. package/skills/cometchat-native-components/SKILL.md +1 -1
  222. package/skills/cometchat-native-core/SKILL.md +1 -1
  223. package/skills/cometchat-native-customization/SKILL.md +1 -1
  224. package/skills/cometchat-native-expo-patterns/SKILL.md +18 -1
  225. package/skills/cometchat-native-features/SKILL.md +1 -1
  226. package/skills/cometchat-native-placement/SKILL.md +1 -1
  227. package/skills/cometchat-native-production/SKILL.md +1 -1
  228. package/skills/cometchat-native-push/SKILL.md +1 -1
  229. package/skills/cometchat-native-testing/SKILL.md +1 -1
  230. package/skills/cometchat-native-theming/SKILL.md +1 -1
  231. package/skills/cometchat-native-troubleshooting/SKILL.md +1 -1
  232. package/skills/cometchat-nextjs-patterns/SKILL.md +1 -1
  233. package/skills/cometchat-placement/SKILL.md +29 -1
  234. package/skills/cometchat-production/SKILL.md +1 -1
  235. package/skills/cometchat-react-calls/SKILL.md +539 -0
  236. package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +145 -0
  237. package/skills/cometchat-react-calls/references/call-layouts.md +161 -0
  238. package/skills/cometchat-react-calls/references/call-session.md +235 -0
  239. package/skills/cometchat-react-calls/references/custom-ui.md +201 -0
  240. package/skills/cometchat-react-calls/references/device-management.md +206 -0
  241. package/skills/cometchat-react-calls/references/group-calls.md +262 -0
  242. package/skills/cometchat-react-calls/references/idle-timeout.md +175 -0
  243. package/skills/cometchat-react-calls/references/in-call-chat.md +212 -0
  244. package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +172 -0
  245. package/skills/cometchat-react-calls/references/picture-in-picture.md +245 -0
  246. package/skills/cometchat-react-calls/references/raise-hand.md +238 -0
  247. package/skills/cometchat-react-calls/references/recording-screen-share.md +143 -0
  248. package/skills/cometchat-react-calls/references/ringing-integration.md +255 -0
  249. package/skills/cometchat-react-calls/references/server-web-push-vapid.md +241 -0
  250. package/skills/cometchat-react-calls/references/share-invite.md +176 -0
  251. package/skills/cometchat-react-calls/references/testing-calls-on-web.md +198 -0
  252. package/skills/cometchat-react-calls/references/voip-and-web-push.md +165 -0
  253. package/skills/cometchat-react-patterns/SKILL.md +56 -8
  254. package/skills/cometchat-react-push/SKILL.md +448 -0
  255. package/skills/cometchat-react-router-patterns/SKILL.md +1 -1
  256. package/skills/cometchat-react-testing/SKILL.md +404 -0
  257. package/skills/cometchat-theming/SKILL.md +3 -3
  258. package/skills/cometchat-troubleshooting/SKILL.md +2 -2
@@ -0,0 +1,285 @@
1
+ # Picture-in-Picture on Angular
2
+
3
+ Same browser APIs as React (Video PiP + Document PiP) — the SDK and underlying primitives are identical because Angular wraps the JS Calls SDK. For API-level details, browser support, and the Document PiP path, read `cometchat-react-calls/references/picture-in-picture.md` first. This reference covers Angular-specific wiring.
4
+
5
+ ---
6
+
7
+ ## Video PiP — Angular component pattern
8
+
9
+ ```ts
10
+ // components/pip-button/pip-button.component.ts
11
+ @Component({
12
+ selector: "app-pip-button",
13
+ template: `
14
+ <button (click)="togglePip()" [disabled]="!supported" *ngIf="supported">
15
+ {{ inPip ? "Exit PiP" : "Enter PiP" }}
16
+ </button>
17
+ `,
18
+ changeDetection: ChangeDetectionStrategy.OnPush,
19
+ })
20
+ export class PipButtonComponent implements OnInit, OnDestroy {
21
+ @Input() videoRef!: ElementRef<HTMLVideoElement>;
22
+ inPip = false;
23
+ supported = typeof document !== "undefined" && document.pictureInPictureEnabled;
24
+
25
+ private enterListener?: () => void;
26
+ private leaveListener?: () => void;
27
+
28
+ constructor(private zone: NgZone, private cd: ChangeDetectorRef) {}
29
+
30
+ ngOnInit() {
31
+ if (!this.videoRef?.nativeElement) return;
32
+ const video = this.videoRef.nativeElement;
33
+
34
+ this.enterListener = () => this.zone.run(() => { this.inPip = true; this.cd.markForCheck(); });
35
+ this.leaveListener = () => this.zone.run(() => { this.inPip = false; this.cd.markForCheck(); });
36
+
37
+ video.addEventListener("enterpictureinpicture", this.enterListener);
38
+ video.addEventListener("leavepictureinpicture", this.leaveListener);
39
+ }
40
+
41
+ ngOnDestroy() {
42
+ const video = this.videoRef?.nativeElement;
43
+ if (!video) return;
44
+ if (this.enterListener) video.removeEventListener("enterpictureinpicture", this.enterListener);
45
+ if (this.leaveListener) video.removeEventListener("leavepictureinpicture", this.leaveListener);
46
+ if (document.pictureInPictureElement) {
47
+ document.exitPictureInPicture().catch(() => {});
48
+ }
49
+ }
50
+
51
+ async togglePip() {
52
+ if (!this.videoRef?.nativeElement) return;
53
+ if (this.inPip) {
54
+ await document.exitPictureInPicture();
55
+ } else {
56
+ try {
57
+ await this.videoRef.nativeElement.requestPictureInPicture();
58
+ } catch (err) {
59
+ console.warn("PiP request failed:", err);
60
+ }
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ The `@Input() videoRef` is the parent's `<video>` element via `@ViewChild`. NgZone wraps the events so OnPush components re-render correctly.
67
+
68
+ Usage in the call screen:
69
+
70
+ ```ts
71
+ @Component({
72
+ selector: "app-ongoing-call",
73
+ template: `
74
+ <video #remoteVideo autoplay playsinline [class.hidden]="inPip"></video>
75
+ <app-pip-button [videoRef]="remoteVideo"></app-pip-button>
76
+ `,
77
+ styles: [`
78
+ .hidden { visibility: hidden; }
79
+ `],
80
+ })
81
+ export class OngoingCallComponent {
82
+ @ViewChild("remoteVideo") remoteVideo!: ElementRef<HTMLVideoElement>;
83
+ inPip = false;
84
+ }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Document PiP — Angular host element transfer
90
+
91
+ Document PiP lets you put arbitrary HTML in a floating window, including a full Angular component subtree. The challenge: detaching + re-attaching a DOM node mid-Angular-lifecycle.
92
+
93
+ ```ts
94
+ // services/document-pip.service.ts
95
+ import { Injectable, NgZone, RendererFactory2, Renderer2 } from "@angular/core";
96
+
97
+ @Injectable({ providedIn: "root" })
98
+ export class DocumentPipService {
99
+ private pipWindow: Window | null = null;
100
+ private renderer: Renderer2;
101
+
102
+ constructor(private zone: NgZone, private rendererFactory: RendererFactory2) {
103
+ this.renderer = rendererFactory.createRenderer(null, null);
104
+ }
105
+
106
+ get supported(): boolean {
107
+ return typeof window !== "undefined" && "documentPictureInPicture" in window;
108
+ }
109
+
110
+ async openWindow(content: HTMLElement, options: { width?: number; height?: number } = {}): Promise<Window | null> {
111
+ if (!this.supported) return null;
112
+
113
+ this.pipWindow = await (window as unknown as {
114
+ documentPictureInPicture: { requestWindow: (o: object) => Promise<Window> };
115
+ }).documentPictureInPicture.requestWindow({
116
+ width: options.width ?? 360,
117
+ height: options.height ?? 480,
118
+ });
119
+
120
+ // Copy stylesheets so kit + Angular Material styles work in the PiP window
121
+ for (const sheet of Array.from(document.styleSheets)) {
122
+ try {
123
+ const cssText = Array.from(sheet.cssRules ?? []).map(r => r.cssText).join("\n");
124
+ const style = this.pipWindow.document.createElement("style");
125
+ style.textContent = cssText;
126
+ this.pipWindow.document.head.appendChild(style);
127
+ } catch {
128
+ if (sheet.href) {
129
+ const link = this.pipWindow.document.createElement("link");
130
+ link.rel = "stylesheet";
131
+ link.href = sheet.href;
132
+ this.pipWindow.document.head.appendChild(link);
133
+ }
134
+ }
135
+ }
136
+
137
+ this.pipWindow.document.body.appendChild(content);
138
+
139
+ return this.pipWindow;
140
+ }
141
+
142
+ closeWindow() {
143
+ if (this.pipWindow) {
144
+ this.pipWindow.close();
145
+ this.pipWindow = null;
146
+ }
147
+ }
148
+ }
149
+ ```
150
+
151
+ Then in the call component:
152
+
153
+ ```ts
154
+ @Component({
155
+ // ...
156
+ template: `
157
+ <div #callRoot class="call-root">
158
+ <video #remoteVideo autoplay playsinline></video>
159
+ <app-control-panel></app-control-panel>
160
+ </div>
161
+ `,
162
+ })
163
+ export class OngoingCallComponent {
164
+ @ViewChild("callRoot", { static: true }) callRoot!: ElementRef<HTMLElement>;
165
+
166
+ constructor(private docPip: DocumentPipService, private zone: NgZone) {}
167
+
168
+ async enterDocumentPip() {
169
+ const pipWin = await this.docPip.openWindow(this.callRoot.nativeElement);
170
+ if (!pipWin) return;
171
+
172
+ pipWin.addEventListener("pagehide", () => {
173
+ this.zone.run(() => {
174
+ // Restore the call-root back to the original mount point
175
+ const host = document.getElementById("call-host");
176
+ if (host && this.callRoot.nativeElement) {
177
+ host.appendChild(this.callRoot.nativeElement);
178
+ }
179
+ });
180
+ });
181
+ }
182
+ }
183
+ ```
184
+
185
+ When you transfer the DOM node into the PiP window, Angular's change detection still works because the node is the same. Click handlers, OnPush updates, NgZone events all continue functioning across the window boundary. This is the magic of Document PiP.
186
+
187
+ ---
188
+
189
+ ## Auto-PiP on tab/window backgrounding
190
+
191
+ ```ts
192
+ @Component({...})
193
+ export class OngoingCallComponent implements OnInit, OnDestroy {
194
+ private visibilitySub?: Subscription;
195
+
196
+ ngOnInit() {
197
+ if (!document.pictureInPictureEnabled) return;
198
+ this.visibilitySub = fromEvent(document, "visibilitychange").subscribe(() => {
199
+ if (document.visibilityState === "hidden" && this.callActive) {
200
+ this.zone.run(() => {
201
+ this.remoteVideo.nativeElement.requestPictureInPicture().catch(() => {});
202
+ });
203
+ }
204
+ });
205
+ }
206
+
207
+ ngOnDestroy() {
208
+ this.visibilitySub?.unsubscribe();
209
+ }
210
+ }
211
+ ```
212
+
213
+ Same caveats as React — Safari rejects auto-PiP from non-user-gesture contexts in some versions. Test on real Safari before relying on this.
214
+
215
+ ---
216
+
217
+ ## Auto-leave on hangup
218
+
219
+ ```ts
220
+ async endCall() {
221
+ if (document.pictureInPictureElement) {
222
+ await document.exitPictureInPicture();
223
+ }
224
+ this.docPip.closeWindow();
225
+
226
+ CometChatCalls.leaveSession(); // v5 canonical (endSession is a deprecated shim)
227
+ // ...rest of cleanup
228
+ }
229
+ ```
230
+
231
+ ---
232
+
233
+ ## SSR considerations (Angular Universal)
234
+
235
+ Document and Video PiP both reference `document.pictureInPictureEnabled` and `window.documentPictureInPicture`. Both are browser-only — guard:
236
+
237
+ ```ts
238
+ import { isPlatformBrowser } from "@angular/common";
239
+
240
+ constructor(@Inject(PLATFORM_ID) private platformId: object) {}
241
+
242
+ get supported() {
243
+ return isPlatformBrowser(this.platformId)
244
+ && typeof document !== "undefined"
245
+ && document.pictureInPictureEnabled;
246
+ }
247
+ ```
248
+
249
+ Without this, SSR build crashes at boot.
250
+
251
+ ---
252
+
253
+ ## Anti-patterns
254
+
255
+ 1. **`requestPictureInPicture()` from `ngOnInit`.** Browsers reject — needs user gesture. `(click)` is the trigger.
256
+ 2. **Skipping `NgZone.run`** for PiP enter/leave events. OnPush components don't re-render.
257
+ 3. **Document PiP without copying stylesheets.** PiP window unstyled.
258
+ 4. **Forgetting `pagehide` cleanup** when user closes the PiP window via system X. DOM node stays detached; controls broken.
259
+ 5. **No SSR guard.** Universal build crashes.
260
+ 6. **Two separate video elements** (one for normal, one for PiP). Use one `<video>` and `[class.hidden]` it.
261
+ 7. **Auto-PiP in `ngOnInit` with no user-gesture context.** Safari rejects.
262
+
263
+ ---
264
+
265
+ ## Verification checklist
266
+
267
+ - [ ] PiP button feature-detects `document.pictureInPictureEnabled`
268
+ - [ ] Button hidden / disabled when unsupported
269
+ - [ ] PiP request from `(click)`, not `ngOnInit`
270
+ - [ ] `enterpictureinpicture` / `leavepictureinpicture` listeners wrapped in NgZone
271
+ - [ ] OnPush components call `markForCheck()` after PiP state change
272
+ - [ ] In-page video hidden while PiP active
273
+ - [ ] Hangup path calls `document.exitPictureInPicture()` if active
274
+ - [ ] Document PiP path closes window via `docPip.closeWindow()`
275
+ - [ ] SSR builds: `isPlatformBrowser` guards
276
+ - [ ] Real-browser smoke: Chrome (both APIs) + Safari (Video PiP) + Firefox (Video PiP)
277
+
278
+ ---
279
+
280
+ ## Pointers
281
+
282
+ - `cometchat-react-calls/references/picture-in-picture.md` — sister reference (browser API details, Document PiP semantics, browser support)
283
+ - `references/custom-ui.md` — Angular custom call UI (PiP integration via @ViewChild on the video element)
284
+ - `references/lazy-loading-pitfalls.md` — eager loading + SSR guards
285
+ - `cometchat-angular-calls` SKILL.md — base hard rules
@@ -0,0 +1,167 @@
1
+ # Raise hand on Angular
2
+
3
+ Same SDK API as web (`@cometchat/calls-sdk-javascript`). Angular-specific wiring: NgZone wrap on listeners, RxJS Subject for the raised-hands roster, OnPush + markForCheck.
4
+
5
+ **Canonical docs:** https://www.cometchat.com/docs/calls/javascript/raise-hand
6
+ **Read first:** `cometchat-react-calls/references/raise-hand.md` — integration shape + anti-patterns are identical; this reference is the Angular-specific wiring.
7
+
8
+ ---
9
+
10
+ ## SDK API (same as web)
11
+
12
+ ```ts
13
+ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
14
+
15
+ CometChatCalls.raiseHand();
16
+ CometChatCalls.lowerHand();
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Angular wiring — service-driven roster
22
+
23
+ Centralize raise-hand state in a service so any component can subscribe:
24
+
25
+ ```ts
26
+ // services/raise-hand.service.ts
27
+ import { Injectable, NgZone, OnDestroy } from "@angular/core";
28
+ import { BehaviorSubject } from "rxjs";
29
+ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
30
+
31
+ interface RaisedParticipant { uid: string; name: string; raisedAt: number; }
32
+
33
+ @Injectable({ providedIn: "root" })
34
+ export class RaiseHandService implements OnDestroy {
35
+ private readonly raised = new Map<string, RaisedParticipant>();
36
+ readonly raised$ = new BehaviorSubject<RaisedParticipant[]>([]);
37
+
38
+ private onRaised = (p: { uid: string; name: string }) => {
39
+ this.zone.run(() => {
40
+ this.raised.set(p.uid, { ...p, raisedAt: Date.now() });
41
+ this.emit();
42
+ });
43
+ };
44
+
45
+ private onLowered = (p: { uid: string }) => {
46
+ this.zone.run(() => {
47
+ this.raised.delete(p.uid);
48
+ this.emit();
49
+ });
50
+ };
51
+
52
+ constructor(private zone: NgZone) {
53
+ CometChatCalls.addEventListener("onParticipantHandRaised", this.onRaised);
54
+ CometChatCalls.addEventListener("onParticipantHandLowered", this.onLowered);
55
+ }
56
+
57
+ ngOnDestroy() {
58
+ CometChatCalls.removeEventListener("onParticipantHandRaised", this.onRaised);
59
+ CometChatCalls.removeEventListener("onParticipantHandLowered", this.onLowered);
60
+ }
61
+
62
+ raise() { CometChatCalls.raiseHand(); }
63
+ lower() { CometChatCalls.lowerHand(); }
64
+
65
+ private emit() {
66
+ const sorted = Array.from(this.raised.values()).sort((a, b) => a.raisedAt - b.raisedAt);
67
+ this.raised$.next(sorted);
68
+ }
69
+ }
70
+ ```
71
+
72
+ The `NgZone.run` wrapping is the canonical Angular rule (see `references/ngzone-and-async-callbacks.md`) — without it, `BehaviorSubject.next` doesn't trigger change detection in OnPush components.
73
+
74
+ ---
75
+
76
+ ## Toggle button component
77
+
78
+ ```ts
79
+ @Component({
80
+ selector: "app-raise-hand-button",
81
+ template: `
82
+ <button
83
+ (click)="toggle()"
84
+ [class.active]="raised"
85
+ [attr.aria-pressed]="raised"
86
+ [attr.aria-label]="raised ? 'Lower hand' : 'Raise hand'"
87
+ >
88
+ ✋ {{ raised ? "Lower" : "Raise" }}
89
+ </button>
90
+ `,
91
+ changeDetection: ChangeDetectionStrategy.OnPush,
92
+ })
93
+ export class RaiseHandButtonComponent {
94
+ raised = false;
95
+ constructor(private svc: RaiseHandService, private cd: ChangeDetectorRef) {}
96
+
97
+ toggle() {
98
+ if (this.raised) this.svc.lower();
99
+ else this.svc.raise();
100
+ this.raised = !this.raised;
101
+ this.cd.markForCheck();
102
+ }
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Roster component (host view)
109
+
110
+ ```ts
111
+ @Component({
112
+ selector: "app-raised-hands-list",
113
+ template: `
114
+ <div *ngIf="(raised$ | async) as list">
115
+ <ul *ngIf="list.length > 0" aria-label="Raised hands queue">
116
+ <li *ngFor="let p of list; trackBy: trackByUid">
117
+ ✋ {{ p.name }} <span class="ago">{{ secondsAgo(p.raisedAt) }}</span>
118
+ </li>
119
+ </ul>
120
+ </div>
121
+ `,
122
+ changeDetection: ChangeDetectionStrategy.OnPush,
123
+ })
124
+ export class RaisedHandsListComponent {
125
+ raised$ = this.svc.raised$;
126
+ constructor(private svc: RaiseHandService) {}
127
+ trackByUid(_: number, p: RaisedParticipant) { return p.uid; }
128
+ secondsAgo(t: number) { return `${Math.round((Date.now() - t) / 1000)}s ago`; }
129
+ }
130
+ ```
131
+
132
+ `trackByUid` is critical — without it, Angular re-renders every list item on every emit, which is bad for FlatList-style smooth scroll.
133
+
134
+ ---
135
+
136
+ ## Anti-patterns
137
+
138
+ Same shape as web sister reference, plus Angular-specific:
139
+
140
+ 1. **Service NOT provided in `root`.** If raise-hand service is provided in a feature module, it instantiates on lazy-load — listeners attach late. Provide in root so it boots with the app.
141
+ 2. **Skipping `markForCheck` with OnPush.** Service emits, component doesn't re-render.
142
+ 3. **Forgetting `ngOnDestroy` cleanup.** Service is `providedIn: "root"` so it lives forever, but the listeners would survive across logout/re-login. Reset on `CometChatUIKit.logout`.
143
+ 4. **`*ngFor` without `trackBy`.** Re-renders thrash; tile state lost.
144
+
145
+ ---
146
+
147
+ ## Verification checklist
148
+
149
+ - [ ] `RaiseHandService` provided in root
150
+ - [ ] `NgZone.run` wraps both listener callbacks
151
+ - [ ] `BehaviorSubject` emits sorted-by-raisedAt list
152
+ - [ ] Toggle button has `aria-pressed` + `aria-label`
153
+ - [ ] Roster uses `trackBy: trackByUid`
154
+ - [ ] OnPush components call `markForCheck()` on state change
155
+ - [ ] Listeners cleaned up in `ngOnDestroy`
156
+ - [ ] `hideRaiseHandButton: true` in CallSettings if using custom UI
157
+ - [ ] Browser smoke: 3 tabs in same call → host's roster updates with markForCheck
158
+
159
+ ---
160
+
161
+ ## Pointers
162
+
163
+ - `cometchat-react-calls/references/raise-hand.md` — sister reference
164
+ - `references/ngzone-and-async-callbacks.md` — NgZone primer
165
+ - `references/group-calls.md` — group call architecture in Angular
166
+ - `cometchat-a11y` — `aria-pressed` + screen reader announcements
167
+ - Canonical docs: https://www.cometchat.com/docs/calls/javascript/raise-hand