@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,245 @@
1
+ # Picture-in-Picture on web
2
+
3
+ Web has two PiP APIs, used for different things:
4
+
5
+ 1. **Video PiP** (`HTMLVideoElement.requestPictureInPicture()`) — lets a single `<video>` element float in a system-managed window above all browser tabs. Standard since Chrome 70 / Safari 13 / Firefox 71. Fine for one remote participant.
6
+
7
+ 2. **Document PiP** (`window.documentPictureInPicture.requestWindow()`) — lets you put arbitrary HTML (custom call UI with controls, multi-tile grid, roster) in a floating window. Chrome 116+ only. Falls back gracefully where unsupported.
8
+
9
+ This reference covers both, plus when to pick which.
10
+
11
+ ---
12
+
13
+ ## When to use Video PiP vs Document PiP
14
+
15
+ | Scenario | Pick |
16
+ |---|---|
17
+ | 1:1 call, just want the remote face floating while user works | Video PiP |
18
+ | Multi-party call, want the active speaker + a small roster floating | Document PiP if Chrome 116+, else fall back to Video PiP |
19
+ | Want call controls (mute/end) visible in the PiP window | Document PiP only — Video PiP doesn't allow custom controls |
20
+ | Cross-browser support including Safari + Firefox | Video PiP (with fallback when neither works) |
21
+
22
+ The skill defaults to Video PiP for cross-browser compatibility; Document PiP is opt-in for Chromium-only apps.
23
+
24
+ ---
25
+
26
+ ## Video PiP — the simple path
27
+
28
+ ```tsx
29
+ // CustomOngoingCallView.tsx — extends the version in references/custom-ui.md
30
+ const remoteVideoRef = useRef<HTMLVideoElement>(null);
31
+ const [pipActive, setPipActive] = useState(false);
32
+
33
+ async function enterPiP() {
34
+ const video = remoteVideoRef.current;
35
+ if (!video) return;
36
+ if (!document.pictureInPictureEnabled) {
37
+ setError("Picture-in-Picture isn't supported in this browser");
38
+ return;
39
+ }
40
+ try {
41
+ await video.requestPictureInPicture();
42
+ setPipActive(true);
43
+ } catch (err) {
44
+ // user denied, video not yet playing, etc.
45
+ console.warn("PiP request failed:", err);
46
+ }
47
+ }
48
+
49
+ useEffect(() => {
50
+ const video = remoteVideoRef.current;
51
+ if (!video) return;
52
+ const onEnter = () => setPipActive(true);
53
+ const onLeave = () => setPipActive(false);
54
+ video.addEventListener("enterpictureinpicture", onEnter);
55
+ video.addEventListener("leavepictureinpicture", onLeave);
56
+ return () => {
57
+ video.removeEventListener("enterpictureinpicture", onEnter);
58
+ video.removeEventListener("leavepictureinpicture", onLeave);
59
+ };
60
+ }, []);
61
+ ```
62
+
63
+ The `<video>` element keeps playing — PiP doesn't pause or remount. CSS doesn't apply (the OS owns the floating window). Hide the in-page video when PiP is active to avoid the "two videos playing" UX:
64
+
65
+ ```tsx
66
+ <video
67
+ ref={remoteVideoRef}
68
+ autoPlay
69
+ playsInline
70
+ style={{ display: pipActive ? "none" : "block" }}
71
+ />
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Document PiP — the rich path (Chrome 116+)
77
+
78
+ ```tsx
79
+ const [pipWindow, setPipWindow] = useState<Window | null>(null);
80
+
81
+ async function enterDocumentPiP() {
82
+ // Feature detect
83
+ if (!("documentPictureInPicture" in window)) {
84
+ return enterPiP(); // fall through to video PiP
85
+ }
86
+
87
+ const pipWin = await (window as unknown as {
88
+ documentPictureInPicture: { requestWindow: (opts: { width: number; height: number }) => Promise<Window> };
89
+ }).documentPictureInPicture.requestWindow({
90
+ width: 360,
91
+ height: 480,
92
+ });
93
+
94
+ // Copy the call container into the PiP window
95
+ const container = document.getElementById("ongoing-call-root");
96
+ if (container) {
97
+ pipWin.document.body.appendChild(container);
98
+ }
99
+
100
+ // PiP window has its own document — copy stylesheets so kit styling works
101
+ for (const styleSheet of Array.from(document.styleSheets)) {
102
+ try {
103
+ const cssRules = Array.from(styleSheet.cssRules ?? []).map((r) => r.cssText).join("\n");
104
+ const style = pipWin.document.createElement("style");
105
+ style.textContent = cssRules;
106
+ pipWin.document.head.appendChild(style);
107
+ } catch {
108
+ // cross-origin stylesheets throw — copy <link> href instead
109
+ if (styleSheet.href) {
110
+ const link = pipWin.document.createElement("link");
111
+ link.rel = "stylesheet";
112
+ link.href = styleSheet.href;
113
+ pipWin.document.head.appendChild(link);
114
+ }
115
+ }
116
+ }
117
+
118
+ // When the user closes the PiP window (system X button), restore the container
119
+ pipWin.addEventListener("pagehide", () => {
120
+ const restored = pipWin.document.getElementById("ongoing-call-root");
121
+ if (restored && document.getElementById("call-host")) {
122
+ document.getElementById("call-host")!.appendChild(restored);
123
+ }
124
+ setPipWindow(null);
125
+ });
126
+
127
+ setPipWindow(pipWin);
128
+ }
129
+ ```
130
+
131
+ The `container` keeps its event handlers and React fiber attached — clicking "End" inside the PiP window still calls your React handlers. This is the magic of Document PiP that single-video PiP doesn't give you.
132
+
133
+ **Caveat:** stylesheets are copied at PiP-open time. If you change the theme mid-PiP (light/dark toggle), styles in the PiP window go stale. Add a `MutationObserver` or just don't allow theme switching while PiP is active.
134
+
135
+ ---
136
+
137
+ ## Browser support matrix
138
+
139
+ | Browser | Video PiP | Document PiP |
140
+ |---|---|---|
141
+ | Chrome 70+ desktop | ✓ | Chrome 116+ |
142
+ | Edge 79+ desktop | ✓ | Edge 116+ |
143
+ | Safari 13+ desktop | ✓ | ✗ (no plans yet) |
144
+ | Firefox 71+ desktop | ✓ (custom toggle UI, not standard API) | ✗ |
145
+ | Chrome mobile (Android) | ✓ system-PiP equivalent | ✗ |
146
+ | Safari iOS | iPad: ✓; iPhone: limited | ✗ |
147
+
148
+ Feature-detect both. Don't render the "Enter PiP" button when neither is supported.
149
+
150
+ ```tsx
151
+ const canVideoPiP = typeof document !== "undefined" && document.pictureInPictureEnabled;
152
+ const canDocPiP = typeof window !== "undefined" && "documentPictureInPicture" in window;
153
+ const showPipButton = canVideoPiP || canDocPiP;
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Auto-enter PiP on tab switch
159
+
160
+ A "tab visibility" pattern many call UX teams want — auto-enter PiP when the user switches away from the call tab:
161
+
162
+ ```tsx
163
+ useEffect(() => {
164
+ const onVisibilityChange = () => {
165
+ if (document.visibilityState === "hidden" && remoteVideoRef.current) {
166
+ remoteVideoRef.current.requestPictureInPicture().catch(() => {});
167
+ }
168
+ };
169
+ document.addEventListener("visibilitychange", onVisibilityChange);
170
+ return () => document.removeEventListener("visibilitychange", onVisibilityChange);
171
+ }, []);
172
+ ```
173
+
174
+ Browsers reject auto-PiP requests not tied to user gestures in some contexts (Safari is strictest). Use `await navigator.mediaSession.setActionHandler("enterpictureinpicture", ...)` for a cleaner API where supported.
175
+
176
+ ---
177
+
178
+ ## Auto-leave PiP on hangup
179
+
180
+ When the call ends, exit PiP cleanly:
181
+
182
+ ```tsx
183
+ function endCall() {
184
+ if (document.pictureInPictureElement) {
185
+ document.exitPictureInPicture();
186
+ }
187
+ if (pipWindow) {
188
+ pipWindow.close();
189
+ setPipWindow(null);
190
+ }
191
+ CometChatCalls.leaveSession();
192
+ // ...rest of cleanup
193
+ }
194
+ ```
195
+
196
+ Without this, the PiP window stays floating after the call ends, showing a frozen frame.
197
+
198
+ ---
199
+
200
+ ## PiP + custom UI integration
201
+
202
+ If you're using `enableDefaultLayout(true)` (kit-rendered call UI), PiP works on the kit's internal `<video>` element. Reach into it via:
203
+
204
+ ```ts
205
+ const callContainer = document.getElementById("calls-container");
206
+ const video = callContainer?.querySelector("video"); // kit renders one or more
207
+ if (video instanceof HTMLVideoElement) {
208
+ await video.requestPictureInPicture();
209
+ }
210
+ ```
211
+
212
+ Brittle — kit DOM structure can change between versions. Custom UI (Document PiP path above) is more stable.
213
+
214
+ ---
215
+
216
+ ## Anti-patterns
217
+
218
+ 1. **Calling `requestPictureInPicture()` from `useEffect` on mount.** Browsers reject — must be in response to user gesture. Wire to a button.
219
+ 2. **Forgetting to hide the in-page `<video>` while PiP is active.** Two videos play, audio doubles, layout breaks.
220
+ 3. **Document PiP without copying stylesheets.** PiP window renders unstyled; user sees raw HTML.
221
+ 4. **Not exiting PiP on hangup.** Frozen frame floats after call ends.
222
+ 5. **Document PiP detection via `'documentPictureInPicture' in document`.** It's on `window`, not `document`. Common typo.
223
+ 6. **Auto-PiP on every visibility change, including page reload.** User reloads → unintended PiP. Gate on call active + user-initiated focus loss.
224
+
225
+ ---
226
+
227
+ ## Verification checklist
228
+
229
+ - [ ] PiP button only renders if `document.pictureInPictureEnabled` OR `'documentPictureInPicture' in window`
230
+ - [ ] PiP request triggered from a click handler, not `useEffect`
231
+ - [ ] In-page video hidden while PiP active (or repositioned)
232
+ - [ ] `enterpictureinpicture` / `leavepictureinpicture` listeners update local state
233
+ - [ ] Hangup path calls `document.exitPictureInPicture()` if active
234
+ - [ ] Document PiP path copies stylesheets to the PiP window's document
235
+ - [ ] Document PiP path restores the container to the main window on `pagehide`
236
+ - [ ] Real-browser smoke: Chrome desktop (both APIs) + Safari desktop (Video PiP) + Firefox (Video PiP)
237
+
238
+ ---
239
+
240
+ ## Pointers
241
+
242
+ - Custom UI integration: `references/custom-ui.md`
243
+ - Kit-default layout: kit handles internal video PiP via the kit's own controls
244
+ - Document PiP spec: https://wicg.github.io/document-picture-in-picture/
245
+ - `cometchat-react-calls` SKILL.md — base hard rules
@@ -0,0 +1,238 @@
1
+ # Raise hand on web
2
+
3
+ Lets participants signal they want to speak without interrupting the current speaker. The SDK ships first-party support — four method calls, two events, one settings flag. No custom signaling needed.
4
+
5
+ **Canonical docs:** https://www.cometchat.com/docs/calls/javascript/raise-hand
6
+ **Use it for:** classrooms, large group calls, town halls, any call with > ~5 participants where verbal turn-taking gets messy.
7
+
8
+ ---
9
+
10
+ ## SDK API (web Calls SDK)
11
+
12
+ ```ts
13
+ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
14
+
15
+ // Local user raises hand
16
+ CometChatCalls.raiseHand();
17
+
18
+ // Local user lowers hand
19
+ CometChatCalls.lowerHand();
20
+
21
+ // Subscribe to other participants' hand state
22
+ CometChatCalls.addEventListener("onParticipantHandRaised", (participant) => {
23
+ // participant.uid, participant.name available
24
+ });
25
+
26
+ CometChatCalls.addEventListener("onParticipantHandLowered", (participant) => {
27
+ // ...
28
+ });
29
+ ```
30
+
31
+ The SDK ships a built-in raise-hand button in the default control panel. Hide it via call settings if you're rolling custom UI:
32
+
33
+ ```ts
34
+ const callSettings = new CometChatCalls.CallSettingsBuilder()
35
+ .setSessionID(sessionId)
36
+ .hideRaiseHandButton(true) // suppress the SDK's button — your UI takes over
37
+ .build();
38
+ ```
39
+
40
+ ---
41
+
42
+ ## When to use built-in vs custom
43
+
44
+ | Scenario | Use |
45
+ |---|---|
46
+ | Default kit UI is fine; just want raise-hand | Built-in (don't pass `hideRaiseHandButton`) |
47
+ | Custom call UI (your own control panel) | Custom — call `raiseHand()` / `lowerHand()` from your buttons |
48
+ | Need different host vs participant UI | Custom — query group scope, render different controls |
49
+ | Need raise-hand list (host sees who's raised) | Custom — maintain local Map<uid, raisedAt> via the listeners |
50
+
51
+ ---
52
+
53
+ ## Custom raise-hand UX — three pieces
54
+
55
+ ### 1. Local participant button (toggle)
56
+
57
+ ```tsx
58
+ import { useState } from "react";
59
+ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
60
+
61
+ function RaiseHandButton() {
62
+ const [raised, setRaised] = useState(false);
63
+
64
+ function toggle() {
65
+ if (raised) {
66
+ CometChatCalls.lowerHand();
67
+ setRaised(false);
68
+ } else {
69
+ CometChatCalls.raiseHand();
70
+ setRaised(true);
71
+ }
72
+ }
73
+
74
+ return (
75
+ <button onClick={toggle} aria-pressed={raised}>
76
+ {raised ? "✋ Lower" : "✋ Raise hand"}
77
+ </button>
78
+ );
79
+ }
80
+ ```
81
+
82
+ Visual hint: render the icon with `aria-pressed={raised}` so screen readers announce the toggle state. (See `cometchat-a11y` for the broader rule.)
83
+
84
+ ### 2. Raised-hands roster (host view)
85
+
86
+ ```tsx
87
+ import { useEffect, useState } from "react";
88
+ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
89
+
90
+ interface RaisedParticipant { uid: string; name: string; raisedAt: number; }
91
+
92
+ function RaisedHandsList() {
93
+ const [raised, setRaised] = useState<Map<string, RaisedParticipant>>(new Map());
94
+
95
+ useEffect(() => {
96
+ const onRaised = (p: { uid: string; name: string }) => {
97
+ setRaised(prev => {
98
+ const next = new Map(prev);
99
+ next.set(p.uid, { ...p, raisedAt: Date.now() });
100
+ return next;
101
+ });
102
+ };
103
+ const onLowered = (p: { uid: string }) => {
104
+ setRaised(prev => {
105
+ const next = new Map(prev);
106
+ next.delete(p.uid);
107
+ return next;
108
+ });
109
+ };
110
+
111
+ CometChatCalls.addEventListener("onParticipantHandRaised", onRaised);
112
+ CometChatCalls.addEventListener("onParticipantHandLowered", onLowered);
113
+
114
+ return () => {
115
+ CometChatCalls.removeEventListener("onParticipantHandRaised", onRaised);
116
+ CometChatCalls.removeEventListener("onParticipantHandLowered", onLowered);
117
+ };
118
+ }, []);
119
+
120
+ // Sort oldest-first — fairness queue
121
+ const sorted = Array.from(raised.values()).sort((a, b) => a.raisedAt - b.raisedAt);
122
+ if (sorted.length === 0) return null;
123
+
124
+ return (
125
+ <ul aria-label="Raised hands queue">
126
+ {sorted.map(p => (
127
+ <li key={p.uid}>
128
+ ✋ {p.name} <span style={{ color: "#888" }}>{secondsAgo(p.raisedAt)}</span>
129
+ </li>
130
+ ))}
131
+ </ul>
132
+ );
133
+ }
134
+
135
+ function secondsAgo(t: number) { return `${Math.round((Date.now() - t) / 1000)}s ago`; }
136
+ ```
137
+
138
+ Sort by `raisedAt` ascending = first-raised-first-called, which feels fair to participants. Don't sort alphabetically.
139
+
140
+ ### 3. Toast notification for the host
141
+
142
+ ```tsx
143
+ useEffect(() => {
144
+ const onRaised = (p: { name: string }) => {
145
+ toast.info(`${p.name} raised their hand`, { duration: 4000 });
146
+ };
147
+ CometChatCalls.addEventListener("onParticipantHandRaised", onRaised);
148
+ return () => CometChatCalls.removeEventListener("onParticipantHandRaised", onRaised);
149
+ }, []);
150
+ ```
151
+
152
+ Use `aria-live="polite"` on the toast region so screen readers announce — same a11y pattern as new-message announcements (cf. `cometchat-a11y`).
153
+
154
+ ---
155
+
156
+ ## Lower-by-host pattern
157
+
158
+ The SDK exposes `lowerHand()` only for the local user. To let a host lower someone else's hand, you need a moderator action via the participant-management API:
159
+
160
+ ```ts
161
+ // Host action — requires moderator/admin scope on the group
162
+ async function lowerParticipantHand(uid: string) {
163
+ // SDK doesn't expose remoteLowerHand directly. Two options:
164
+ // A) Send a custom message to the participant; their client lowers itself
165
+ // B) Use the moderator mute/kick API as the boundary
166
+
167
+ // Option A: lightweight, requires the participant's client to listen
168
+ await CometChat.sendCustomMessage(new CometChat.CustomMessage(
169
+ uid, CometChat.RECEIVER_TYPE.USER, "lower_hand", {}
170
+ ));
171
+ }
172
+ ```
173
+
174
+ On the receiving side:
175
+
176
+ ```ts
177
+ CometChat.addMessageListener("raise-hand-control", new CometChat.MessageListener({
178
+ onCustomMessageReceived: (msg) => {
179
+ if (msg.getType() === "lower_hand") {
180
+ CometChatCalls.lowerHand();
181
+ }
182
+ },
183
+ }));
184
+ ```
185
+
186
+ This is application-level signaling, not SDK-built-in. Document the contract in your team's call protocols.
187
+
188
+ ---
189
+
190
+ ## Hide button on rendered surfaces
191
+
192
+ If using the kit's `<CometChatOngoingCall />` and want raise-hand off entirely (e.g. 1:1 calls don't need it):
193
+
194
+ ```tsx
195
+ import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
196
+
197
+ const settings = new CometChatCalls.CallSettingsBuilder()
198
+ .setSessionID(sessionId)
199
+ .hideRaiseHandButton(true)
200
+ .build();
201
+ ```
202
+
203
+ For 1:1 calls, default to hidden. For group calls > 5 participants, default to shown.
204
+
205
+ ---
206
+
207
+ ## Anti-patterns
208
+
209
+ 1. **Polling for raised-hand state.** The SDK fires events on change — listen, don't poll. Polling burns CPU.
210
+ 2. **Sorting raised-hands alphabetically.** First-raised-first-called is the fair queue. Sort by `raisedAt` ascending.
211
+ 3. **Auto-lowering hands after a timer.** Some people raise their hand and wait. Letting the SDK manage state means the participant lowers when called or via their own button.
212
+ 4. **Showing raise-hand button in 1:1 calls.** Visually noisy and pointless. Gate on `participantCount > 2`.
213
+ 5. **Skipping the listener cleanup in `useEffect`'s return.** Stacked listeners fire multiple times when the component re-mounts — duplicate toasts, duplicate roster entries.
214
+ 6. **Treating "hand raised" as a permission grant.** Raise-hand is a request, not a mute override. The host still has to unmute the participant separately.
215
+
216
+ ---
217
+
218
+ ## Verification checklist
219
+
220
+ - [ ] `raiseHand()` / `lowerHand()` calls in your code (not just relying on the SDK button)
221
+ - [ ] Both `onParticipantHandRaised` and `onParticipantHandLowered` listeners registered
222
+ - [ ] Listeners cleaned up in component unmount (return from `useEffect`)
223
+ - [ ] Roster sorted by `raisedAt` ascending
224
+ - [ ] `hideRaiseHandButton: true` in call settings IF custom UI is used (otherwise duplicates)
225
+ - [ ] Toast / badge UI uses `aria-live="polite"` (a11y)
226
+ - [ ] Browser smoke: 3 tabs, hand-raise from 2 of them, host's roster shows both in raise-order
227
+ - [ ] Lower-hand smoke: tab A raises, lowers, host's roster updates without page refresh
228
+
229
+ ---
230
+
231
+ ## Pointers
232
+
233
+ - `cometchat-react-calls` SKILL.md — the seven hard rules (still apply for raise-hand UI)
234
+ - `references/group-calls.md` — group call architecture (raise-hand is a group-call feature)
235
+ - `references/custom-ui.md` — custom call UI patterns
236
+ - `cometchat-a11y` — toast announcements for raised-hand events
237
+ - Canonical docs: https://www.cometchat.com/docs/calls/javascript/raise-hand
238
+ - For deeper SDK reference (other event types, presenter-mode interplay): query the docs MCP at `https://www.cometchat.com/docs/mcp`
@@ -0,0 +1,143 @@
1
+ # Recording + screen sharing on web
2
+
3
+ Both features ship with the Calls SDK; both have web-specific gotchas the kit's defaults don't handle.
4
+
5
+ ---
6
+
7
+ ## Recording
8
+
9
+ ### Server-side: enable in the dashboard first
10
+
11
+ Recording is a paid feature gated by your CometChat plan. Enable it in **Dashboard → Chat & Messaging → Calls → Recording**. Without that, the client-side flag below is a no-op.
12
+
13
+ ### Client-side: opt-in per session
14
+
15
+ ```ts
16
+ const settings = new CometChatCalls.CallSettingsBuilder()
17
+ .setSessionID(sessionId)
18
+ .setIsAudioOnly(false)
19
+ .enableRecording(true) // ← server starts recording when session begins
20
+ .setShowRecordingButton(true) // ← user-toggleable mid-call
21
+ .build();
22
+ ```
23
+
24
+ Two flags, two behaviors:
25
+
26
+ - `enableRecording(true)` — recording starts the moment the session begins. Server-side flag.
27
+ - `setShowRecordingButton(true)` — exposes a "Record" toggle in the default control panel. User decides when to start/stop. Custom-UI code must wire its own button.
28
+
29
+ **Compliance note:** in some jurisdictions you must notify all participants before recording starts. The default kit UI shows a small "Recording" indicator; if you're using custom UI, you must render this yourself. The skill's verification checklist flags this.
30
+
31
+ ### Recording lifecycle events
32
+
33
+ ```ts
34
+ const listener = new CometChatCalls.OngoingCallListener({
35
+ onRecordingStarted: (rec: unknown) => {
36
+ // server confirmed recording is active
37
+ },
38
+ onRecordingStopped: (rec: unknown) => {
39
+ // server stopped — file will appear in dashboard within ~30 seconds
40
+ },
41
+ onRecordingFailed: (error: unknown) => {
42
+ // surface to UI — usually plan limits or storage quota
43
+ },
44
+ });
45
+ ```
46
+
47
+ ### Where the recordings go
48
+
49
+ CometChat hosts the file. It appears in **Dashboard → Calls → Recordings** with a download link. The skill points users at the dashboard path; there is no client-side download API.
50
+
51
+ ---
52
+
53
+ ## Screen sharing
54
+
55
+ ### Two roles: presenter + viewer
56
+
57
+ - **Presenter** (the user sharing their screen) — calls `CometChatCalls.startScreenShare()` and receives a `MediaStream` from `getDisplayMedia`
58
+ - **Viewer** (everyone else) — sees the presenter's screen as another video tile, no special API call needed
59
+
60
+ Browser support: Chrome/Edge (full), Firefox (full), Safari 13+ (full). On mobile browsers, `getDisplayMedia` is supported on iOS 16+ Safari and recent Android Chrome.
61
+
62
+ ### Presenter — start sharing
63
+
64
+ ```ts
65
+ async function startScreenShare() {
66
+ try {
67
+ await CometChatCalls.startScreenShare();
68
+ // SDK handled getDisplayMedia + signaling; UI updates via onScreenShareStarted
69
+ } catch (err: unknown) {
70
+ if ((err as Error).name === "NotAllowedError") {
71
+ // user clicked "Cancel" on the picker — no error UI needed
72
+ return;
73
+ }
74
+ setError("Couldn't start screen share");
75
+ }
76
+ }
77
+ ```
78
+
79
+ Stop sharing:
80
+
81
+ ```ts
82
+ CometChatCalls.endScreenShare();
83
+ ```
84
+
85
+ The browser also fires its own "Stop sharing" button (the system overlay Chrome shows during a screen-share). The SDK listens for this too; `onScreenShareEnded` fires either way.
86
+
87
+ ### Viewer — listen for screen-share events
88
+
89
+ ```ts
90
+ const listener = new CometChatCalls.OngoingCallListener({
91
+ onScreenShareStarted: (presenterUid: string, stream: MediaStream) => {
92
+ // attach the stream to a <video> element
93
+ if (screenShareVideoRef.current) {
94
+ screenShareVideoRef.current.srcObject = stream;
95
+ }
96
+ },
97
+ onScreenShareEnded: () => {
98
+ if (screenShareVideoRef.current) {
99
+ screenShareVideoRef.current.srcObject = null;
100
+ }
101
+ },
102
+ });
103
+ ```
104
+
105
+ Compose the screen-share tile alongside the camera tiles in your custom layout.
106
+
107
+ ### Audio passthrough during screen share
108
+
109
+ By default, `getDisplayMedia` captures video only. To capture system audio (for sharing a video with sound), pass `audio: true`:
110
+
111
+ ```ts
112
+ // Browser-level API — the SDK's startScreenShare wraps this internally
113
+ const stream = await navigator.mediaDevices.getDisplayMedia({
114
+ video: true,
115
+ audio: true,
116
+ });
117
+ ```
118
+
119
+ Browser support is uneven — Chrome desktop has it; Firefox does not; Safari has it for tab capture but not full-screen.
120
+
121
+ The Calls SDK's `startScreenShare()` does NOT request audio by default in v4. If you need audio passthrough, use the lower-level `getDisplayMedia` API directly + pipe the audio track via a custom track-add hook (covered in `custom-ui.md`).
122
+
123
+ ---
124
+
125
+ ## Combining recording + screen-share
126
+
127
+ Server-side recording captures the active video composition, including screen-share when a participant is sharing. The recording file is one MP4 with the layout the kit was rendering at the time.
128
+
129
+ If you're using custom UI, the recording captures what the SDK sends to the server — not your custom DOM. The composition is determined by the SDK's internal layout, not your CSS.
130
+
131
+ ---
132
+
133
+ ## Browser permissions for screen-share
134
+
135
+ Like `getUserMedia`, `getDisplayMedia` requires HTTPS or `localhost`. It also requires an active user gesture (click/tap) — you cannot start it from a `useEffect` or timer. The skill scaffolds the API call inside an onClick handler.
136
+
137
+ System-level: macOS 10.15+ asks the user once to grant Chrome/Safari/Firefox permission to record the screen (System Preferences → Security & Privacy → Screen Recording). If the user denies, `getDisplayMedia` throws `NotAllowedError` with no remediation path inside the browser — surface a "Open System Preferences" instruction.
138
+
139
+ ---
140
+
141
+ ## Cleanup
142
+
143
+ Both recording and screen-share are part of the call session. `CometChatCalls.leaveSession()` stops both automatically. Custom UI must NOT separately call `getTracks().forEach(t => t.stop())` on the SDK's screen-share stream — the SDK owns it. Stop only the streams YOUR code created (e.g. local preview).