@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.
- package/README.md +42 -2
- package/bin/install.js +448 -57
- package/package.json +1 -1
- package/skills/cometchat/SKILL.md +337 -80
- package/skills/cometchat-a11y/SKILL.md +476 -0
- package/skills/cometchat-android-v5/SKILL.md +1 -1
- package/skills/cometchat-android-v5-calls/SKILL.md +413 -0
- package/skills/cometchat-android-v5-calls/references/README.md +53 -0
- package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +195 -0
- package/skills/cometchat-android-v5-calls/references/audio-controls.md +91 -0
- package/skills/cometchat-android-v5-calls/references/background-handling.md +168 -0
- package/skills/cometchat-android-v5-calls/references/call-layouts.md +123 -0
- package/skills/cometchat-android-v5-calls/references/call-logs.md +113 -0
- package/skills/cometchat-android-v5-calls/references/call-session.md +274 -0
- package/skills/cometchat-android-v5-calls/references/custom-ui.md +150 -0
- package/skills/cometchat-android-v5-calls/references/event-listeners.md +123 -0
- package/skills/cometchat-android-v5-calls/references/group-calls.md +205 -0
- package/skills/cometchat-android-v5-calls/references/idle-timeout.md +111 -0
- package/skills/cometchat-android-v5-calls/references/in-call-chat.md +134 -0
- package/skills/cometchat-android-v5-calls/references/join-session.md +120 -0
- package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +206 -0
- package/skills/cometchat-android-v5-calls/references/participant-management.md +110 -0
- package/skills/cometchat-android-v5-calls/references/picture-in-picture.md +106 -0
- package/skills/cometchat-android-v5-calls/references/raise-hand.md +242 -0
- package/skills/cometchat-android-v5-calls/references/recording.md +101 -0
- package/skills/cometchat-android-v5-calls/references/ringing-integration.md +152 -0
- package/skills/cometchat-android-v5-calls/references/screen-sharing.md +82 -0
- package/skills/cometchat-android-v5-calls/references/server-fcm-voip.md +215 -0
- package/skills/cometchat-android-v5-calls/references/session-settings.md +121 -0
- package/skills/cometchat-android-v5-calls/references/setup.md +137 -0
- package/skills/cometchat-android-v5-calls/references/share-invite.md +151 -0
- package/skills/cometchat-android-v5-calls/references/video-controls.md +87 -0
- package/skills/cometchat-android-v5-calls/references/voip-calling.md +526 -0
- package/skills/cometchat-android-v5-components/SKILL.md +1 -1
- package/skills/cometchat-android-v5-core/SKILL.md +1 -1
- package/skills/cometchat-android-v5-customization/SKILL.md +1 -1
- package/skills/cometchat-android-v5-extensions/SKILL.md +1 -1
- package/skills/cometchat-android-v5-features/SKILL.md +1 -1
- package/skills/cometchat-android-v5-placement/SKILL.md +1 -1
- package/skills/cometchat-android-v5-production/SKILL.md +1 -1
- package/skills/cometchat-android-v5-push/SKILL.md +1 -1
- package/skills/cometchat-android-v5-testing/SKILL.md +1 -1
- package/skills/cometchat-android-v5-theming/SKILL.md +1 -1
- package/skills/cometchat-android-v5-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-android-v6/SKILL.md +1 -1
- package/skills/cometchat-android-v6-builder-settings/SKILL.md +1 -1
- package/skills/cometchat-android-v6-calls/SKILL.md +375 -0
- package/skills/cometchat-android-v6-calls/references/add-calls-to-existing-chat.md +97 -0
- package/skills/cometchat-android-v6-calls/references/call-layouts.md +91 -0
- package/skills/cometchat-android-v6-calls/references/call-session.md +163 -0
- package/skills/cometchat-android-v6-calls/references/device-management.md +171 -0
- package/skills/cometchat-android-v6-calls/references/group-calls.md +191 -0
- package/skills/cometchat-android-v6-calls/references/idle-timeout.md +107 -0
- package/skills/cometchat-android-v6-calls/references/in-call-chat.md +136 -0
- package/skills/cometchat-android-v6-calls/references/raise-hand.md +186 -0
- package/skills/cometchat-android-v6-calls/references/ringing-integration.md +176 -0
- package/skills/cometchat-android-v6-calls/references/server-fcm-voip.md +127 -0
- package/skills/cometchat-android-v6-calls/references/share-invite.md +105 -0
- package/skills/cometchat-android-v6-compose-components/SKILL.md +2 -2
- package/skills/cometchat-android-v6-compose-customization/SKILL.md +1 -1
- package/skills/cometchat-android-v6-compose-placement/SKILL.md +1 -1
- package/skills/cometchat-android-v6-compose-theming/SKILL.md +1 -1
- package/skills/cometchat-android-v6-core/SKILL.md +1 -1
- package/skills/cometchat-android-v6-events/SKILL.md +1 -1
- package/skills/cometchat-android-v6-extensions/SKILL.md +1 -1
- package/skills/cometchat-android-v6-features/SKILL.md +1 -1
- package/skills/cometchat-android-v6-kotlin-components/SKILL.md +1 -1
- package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +1 -1
- package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +1 -1
- package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +1 -1
- package/skills/cometchat-android-v6-migration/SKILL.md +398 -0
- package/skills/cometchat-android-v6-production/SKILL.md +1 -1
- package/skills/cometchat-android-v6-push/SKILL.md +1 -1
- package/skills/cometchat-android-v6-testing/SKILL.md +1 -1
- package/skills/cometchat-android-v6-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-angular-calls/SKILL.md +511 -0
- package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +95 -0
- package/skills/cometchat-angular-calls/references/call-layouts.md +106 -0
- package/skills/cometchat-angular-calls/references/call-session.md +167 -0
- package/skills/cometchat-angular-calls/references/custom-ui.md +231 -0
- package/skills/cometchat-angular-calls/references/device-management.md +135 -0
- package/skills/cometchat-angular-calls/references/group-calls.md +412 -0
- package/skills/cometchat-angular-calls/references/idle-timeout.md +145 -0
- package/skills/cometchat-angular-calls/references/in-call-chat.md +148 -0
- package/skills/cometchat-angular-calls/references/lazy-loading-pitfalls.md +205 -0
- package/skills/cometchat-angular-calls/references/migration-v4-to-v5.md +53 -0
- package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +183 -0
- package/skills/cometchat-angular-calls/references/picture-in-picture.md +285 -0
- package/skills/cometchat-angular-calls/references/raise-hand.md +167 -0
- package/skills/cometchat-angular-calls/references/recording-screen-share.md +267 -0
- package/skills/cometchat-angular-calls/references/ringing-integration.md +131 -0
- package/skills/cometchat-angular-calls/references/server-web-push-vapid.md +100 -0
- package/skills/cometchat-angular-calls/references/share-invite.md +116 -0
- package/skills/cometchat-angular-components/SKILL.md +1 -1
- package/skills/cometchat-angular-core/SKILL.md +1 -1
- package/skills/cometchat-angular-customization/SKILL.md +1 -1
- package/skills/cometchat-angular-features/SKILL.md +1 -1
- package/skills/cometchat-angular-patterns/SKILL.md +1 -1
- package/skills/cometchat-angular-placement/SKILL.md +1 -1
- package/skills/cometchat-angular-production/SKILL.md +1 -1
- package/skills/cometchat-angular-push/SKILL.md +403 -0
- package/skills/cometchat-angular-testing/SKILL.md +333 -0
- package/skills/cometchat-angular-theming/SKILL.md +1 -1
- package/skills/cometchat-angular-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-astro-patterns/SKILL.md +1 -1
- package/skills/cometchat-calls/SKILL.md +358 -0
- package/skills/cometchat-calls/references/use-case-broadcast.md +194 -0
- package/skills/cometchat-calls/references/use-case-marketplace.md +158 -0
- package/skills/cometchat-calls/references/use-case-support.md +190 -0
- package/skills/cometchat-calls/references/use-case-team.md +169 -0
- package/skills/cometchat-calls/references/use-case-telehealth.md +154 -0
- package/skills/cometchat-components/SKILL.md +1 -1
- package/skills/cometchat-core/SKILL.md +1 -1
- package/skills/cometchat-customization/SKILL.md +2 -2
- package/skills/cometchat-features/SKILL.md +2 -2
- package/skills/cometchat-flutter-v5/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-calls/SKILL.md +325 -94
- package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +169 -0
- package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +98 -0
- package/skills/cometchat-flutter-v5-calls/references/call-session.md +330 -0
- package/skills/cometchat-flutter-v5-calls/references/device-management.md +120 -0
- package/skills/cometchat-flutter-v5-calls/references/group-calls.md +187 -0
- package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +97 -0
- package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +132 -0
- package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +160 -0
- package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +244 -0
- package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +193 -0
- package/skills/cometchat-flutter-v5-calls/references/server-push-bridge.md +101 -0
- package/skills/cometchat-flutter-v5-calls/references/share-invite.md +142 -0
- package/skills/cometchat-flutter-v5-conversations/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-core/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-customization/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-events/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-messages/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-production/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-push/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-testing/SKILL.md +390 -0
- package/skills/cometchat-flutter-v5-theming/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-flutter-v5-users-groups/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-calls/SKILL.md +308 -243
- package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +134 -0
- package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +102 -0
- package/skills/cometchat-flutter-v6-calls/references/call-session.md +229 -0
- package/skills/cometchat-flutter-v6-calls/references/device-management.md +99 -0
- package/skills/cometchat-flutter-v6-calls/references/group-calls.md +190 -0
- package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +80 -0
- package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +122 -0
- package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +268 -0
- package/skills/cometchat-flutter-v6-calls/references/ringing-integration.md +171 -0
- package/skills/cometchat-flutter-v6-calls/references/server-push-bridge.md +93 -0
- package/skills/cometchat-flutter-v6-calls/references/share-invite.md +102 -0
- package/skills/cometchat-flutter-v6-components/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-conversations/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-core/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-customization/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-events/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-features/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-messages/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-migration/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-placement/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-production/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-push/SKILL.md +452 -0
- package/skills/cometchat-flutter-v6-testing/SKILL.md +319 -0
- package/skills/cometchat-flutter-v6-theming/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-flutter-v6-users-groups/SKILL.md +1 -1
- package/skills/cometchat-i18n/SKILL.md +358 -0
- package/skills/cometchat-ios/SKILL.md +5 -5
- package/skills/cometchat-ios-calls/SKILL.md +409 -0
- package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +172 -0
- package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +189 -0
- package/skills/cometchat-ios-calls/references/call-layouts.md +136 -0
- package/skills/cometchat-ios-calls/references/call-session.md +221 -0
- package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +353 -0
- package/skills/cometchat-ios-calls/references/custom-ui.md +322 -0
- package/skills/cometchat-ios-calls/references/device-management.md +171 -0
- package/skills/cometchat-ios-calls/references/group-calls.md +396 -0
- package/skills/cometchat-ios-calls/references/idle-timeout.md +185 -0
- package/skills/cometchat-ios-calls/references/in-call-chat.md +183 -0
- package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +138 -0
- package/skills/cometchat-ios-calls/references/picture-in-picture.md +246 -0
- package/skills/cometchat-ios-calls/references/raise-hand.md +239 -0
- package/skills/cometchat-ios-calls/references/recording-screen-share.md +339 -0
- package/skills/cometchat-ios-calls/references/ringing-integration.md +142 -0
- package/skills/cometchat-ios-calls/references/server-apns-pushkit.md +267 -0
- package/skills/cometchat-ios-calls/references/share-invite.md +152 -0
- package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +246 -0
- package/skills/cometchat-ios-calls/references/voip-cert-setup.md +166 -0
- package/skills/cometchat-ios-components/SKILL.md +1 -1
- package/skills/cometchat-ios-core/SKILL.md +1 -1
- package/skills/cometchat-ios-customization/SKILL.md +1 -1
- package/skills/cometchat-ios-features/SKILL.md +1 -1
- package/skills/cometchat-ios-placement/SKILL.md +1 -1
- package/skills/cometchat-ios-production/SKILL.md +1 -1
- package/skills/cometchat-ios-push/SKILL.md +1 -1
- package/skills/cometchat-ios-testing/SKILL.md +371 -0
- package/skills/cometchat-ios-theming/SKILL.md +1 -1
- package/skills/cometchat-ios-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-native-bare-patterns/SKILL.md +45 -3
- package/skills/cometchat-native-calls/SKILL.md +599 -0
- package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +203 -0
- package/skills/cometchat-native-calls/references/call-layouts.md +124 -0
- package/skills/cometchat-native-calls/references/call-session.md +182 -0
- package/skills/cometchat-native-calls/references/custom-ui.md +250 -0
- package/skills/cometchat-native-calls/references/device-management.md +135 -0
- package/skills/cometchat-native-calls/references/expo-vs-bare.md +179 -0
- package/skills/cometchat-native-calls/references/group-calls.md +291 -0
- package/skills/cometchat-native-calls/references/idle-timeout.md +128 -0
- package/skills/cometchat-native-calls/references/in-call-chat.md +143 -0
- package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +72 -0
- package/skills/cometchat-native-calls/references/picture-in-picture.md +276 -0
- package/skills/cometchat-native-calls/references/raise-hand.md +203 -0
- package/skills/cometchat-native-calls/references/recording-screen-share.md +290 -0
- package/skills/cometchat-native-calls/references/ringing-integration.md +118 -0
- package/skills/cometchat-native-calls/references/server-push-bridge.md +135 -0
- package/skills/cometchat-native-calls/references/server-push-payloads.md +193 -0
- package/skills/cometchat-native-calls/references/share-invite.md +144 -0
- package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +317 -0
- package/skills/cometchat-native-components/SKILL.md +1 -1
- package/skills/cometchat-native-core/SKILL.md +1 -1
- package/skills/cometchat-native-customization/SKILL.md +1 -1
- package/skills/cometchat-native-expo-patterns/SKILL.md +18 -1
- package/skills/cometchat-native-features/SKILL.md +1 -1
- package/skills/cometchat-native-placement/SKILL.md +1 -1
- package/skills/cometchat-native-production/SKILL.md +1 -1
- package/skills/cometchat-native-push/SKILL.md +1 -1
- package/skills/cometchat-native-testing/SKILL.md +1 -1
- package/skills/cometchat-native-theming/SKILL.md +1 -1
- package/skills/cometchat-native-troubleshooting/SKILL.md +1 -1
- package/skills/cometchat-nextjs-patterns/SKILL.md +1 -1
- package/skills/cometchat-placement/SKILL.md +29 -1
- package/skills/cometchat-production/SKILL.md +1 -1
- package/skills/cometchat-react-calls/SKILL.md +539 -0
- package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +145 -0
- package/skills/cometchat-react-calls/references/call-layouts.md +161 -0
- package/skills/cometchat-react-calls/references/call-session.md +235 -0
- package/skills/cometchat-react-calls/references/custom-ui.md +201 -0
- package/skills/cometchat-react-calls/references/device-management.md +206 -0
- package/skills/cometchat-react-calls/references/group-calls.md +262 -0
- package/skills/cometchat-react-calls/references/idle-timeout.md +175 -0
- package/skills/cometchat-react-calls/references/in-call-chat.md +212 -0
- package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +172 -0
- package/skills/cometchat-react-calls/references/picture-in-picture.md +245 -0
- package/skills/cometchat-react-calls/references/raise-hand.md +238 -0
- package/skills/cometchat-react-calls/references/recording-screen-share.md +143 -0
- package/skills/cometchat-react-calls/references/ringing-integration.md +255 -0
- package/skills/cometchat-react-calls/references/server-web-push-vapid.md +241 -0
- package/skills/cometchat-react-calls/references/share-invite.md +176 -0
- package/skills/cometchat-react-calls/references/testing-calls-on-web.md +198 -0
- package/skills/cometchat-react-calls/references/voip-and-web-push.md +165 -0
- package/skills/cometchat-react-patterns/SKILL.md +56 -8
- package/skills/cometchat-react-push/SKILL.md +448 -0
- package/skills/cometchat-react-router-patterns/SKILL.md +1 -1
- package/skills/cometchat-react-testing/SKILL.md +404 -0
- package/skills/cometchat-theming/SKILL.md +3 -3
- package/skills/cometchat-troubleshooting/SKILL.md +2 -2
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Group calls — broadcast meeting pattern (Flutter V6)
|
|
2
|
+
|
|
3
|
+
Group calls use a **different signaling channel than 1:1 user calls**. The Ringing flow (`CometChat.initiateCall` → `onIncomingCallReceived` on peer) is **1:1 user only**. For groups, the kit broadcasts a **custom message of type `"meeting"`** to the group; receivers see a "Join meeting" card in `CometChatMessageList` (kit) or need an explicit `MessageListener.onCustomMessageReceived` (custom UI).
|
|
4
|
+
|
|
5
|
+
By-design kit behavior — same semantic across all CometChat kits.
|
|
6
|
+
|
|
7
|
+
**Canonical docs:** https://www.cometchat.com/docs/calls/flutter/group-calls
|
|
8
|
+
|
|
9
|
+
V6 specifics: Flutter V6 folds calls into `cometchat_chat_uikit ^6.0.0-beta2` (no separate calls package). Bloc-based state. **At v6.0.0-beta2, the outgoing-call → in-call transition is broken for 1:1 calls** (vendor bug — see SKILL.md §1.7); this affects group meetings too if customers use the kit's outgoing-call UI. The custom-UI approach is more reliable on V6 today.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Caller (uidA, member of groupX) CometChat Receivers (members of groupX)
|
|
17
|
+
│ │ │
|
|
18
|
+
│ CometChatCallButtons / custom code │ │
|
|
19
|
+
│ sends CustomMessage(GUID, GROUP, │ │
|
|
20
|
+
│ "meeting", { callType, sessionId }) │ │
|
|
21
|
+
├──────────────────────────────────────>│ │
|
|
22
|
+
│ │ onCustomMessageReceived │
|
|
23
|
+
│ ├─────────────────────────────>│
|
|
24
|
+
│ caller pushes OngoingCall screen │ receiver taps Join │
|
|
25
|
+
│ with sessionID = groupGuid │ → joinSession(GUID) │
|
|
26
|
+
├──────────────────────────────────────>│ <─────────────────────────── │
|
|
27
|
+
│ ───── WebRTC session active (sessionId = group GUID) ─────│
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Channel | 1:1 user calls | Group calls |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| Signaling | `CometChat.initiateCall(call, callback)` | `CometChat.sendCustomMessage(message, callback)` (type="meeting") |
|
|
33
|
+
| Receiver event | `CallListener.onIncomingCallReceived` | `MessageListener.onCustomMessageReceived` |
|
|
34
|
+
| Session ID | server-generated unique | group's GUID (persistent) |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Hard rules
|
|
39
|
+
|
|
40
|
+
1. **Group calls broadcast a custom message; they do NOT use the call listener.** Custom UI must add a `MessageListener`.
|
|
41
|
+
2. **Session ID = group GUID.** Persistent.
|
|
42
|
+
3. **V6 vendor bug applies to groups too** (SKILL.md §1.7) — kit's outgoing-call screen does not reliably transition to ongoing-call surface. Prefer custom UI for groups on v6.0.0-beta2.
|
|
43
|
+
4. **`navigatorKey: CallNavigationContext.navigatorKey` required on MaterialApp** if using ANY kit-driven call UI path (group or 1:1) — same as the SKILL rule.
|
|
44
|
+
5. **No `CometChat.endCall` for groups.** Use `CometChatUIKitCalls.endSession()` only.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Caller side — kit-based
|
|
49
|
+
|
|
50
|
+
```dart
|
|
51
|
+
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
|
|
52
|
+
|
|
53
|
+
CometChatCallButtons(
|
|
54
|
+
group: group,
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Tap → kit sends meeting `CustomMessage` + opens outgoing-call screen.
|
|
59
|
+
|
|
60
|
+
> **⚠️ At v6.0.0-beta2, the outgoing→in-call transition is broken** (vendor — SKILL §1.7). Caller may see "Calling..." indefinitely after kit-driven group call. **Workaround**: use the custom-UI path below until vendor fix lands.
|
|
61
|
+
|
|
62
|
+
## Caller side — custom UI (RECOMMENDED on v6.0.0-beta2)
|
|
63
|
+
|
|
64
|
+
```dart
|
|
65
|
+
import 'package:flutter_chat_sdk/flutter_chat_sdk.dart';
|
|
66
|
+
|
|
67
|
+
Future<void> startGroupCall(BuildContext context, String groupGuid, String callType) async {
|
|
68
|
+
final sessionId = groupGuid;
|
|
69
|
+
final customData = {'callType': callType, 'sessionId': sessionId};
|
|
70
|
+
|
|
71
|
+
final meetingMessage = CustomMessage(
|
|
72
|
+
receiverUid: groupGuid,
|
|
73
|
+
receiverType: CometChatReceiverType.group,
|
|
74
|
+
customData: customData,
|
|
75
|
+
type: 'meeting',
|
|
76
|
+
)
|
|
77
|
+
..category = MessageCategoryConstants.custom
|
|
78
|
+
..metadata = {
|
|
79
|
+
'incrementUnreadCount': true,
|
|
80
|
+
'pushNotification': 'meeting',
|
|
81
|
+
...customData,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
await CometChat.sendCustomMessage(
|
|
85
|
+
meetingMessage,
|
|
86
|
+
onSuccess: (msg) {
|
|
87
|
+
// Caller navigates to YOUR OngoingCall screen (not the kit's)
|
|
88
|
+
Navigator.of(context).pushNamed('/ongoing-call', arguments: {
|
|
89
|
+
'sessionId': sessionId,
|
|
90
|
+
'callType': callType,
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
onError: (e) {/* surface error */},
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then in your custom `/ongoing-call` screen, call `CometChatUIKitCalls.startSession(callToken, callSettings, ...)` against your own RTC view — same primitives the kit uses internally, but you control the navigation.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Receiver side — kit-based
|
|
103
|
+
|
|
104
|
+
`CometChatMessageList(group: group)` (or whichever message-list widget V6 ships) auto-renders the meeting message as a "Join meeting" card. Tap → kit calls `generateToken` + pushes the ongoing-call screen.
|
|
105
|
+
|
|
106
|
+
> Same v6.0.0-beta2 caveat applies — if the kit's ongoing-call transition is broken, receivers may also see "Connecting…" indefinitely. Prefer custom join flow.
|
|
107
|
+
|
|
108
|
+
## Receiver side — custom UI (RECOMMENDED)
|
|
109
|
+
|
|
110
|
+
```dart
|
|
111
|
+
import 'package:flutter_chat_sdk/flutter_chat_sdk.dart';
|
|
112
|
+
|
|
113
|
+
const groupMeetingListenerId = 'APP_ROOT_GROUP_MEETING_LISTENER';
|
|
114
|
+
|
|
115
|
+
class MeetingListener {
|
|
116
|
+
void register({required void Function(IncomingMeetingInfo) onIncoming}) {
|
|
117
|
+
CometChat.addMessageListener(
|
|
118
|
+
groupMeetingListenerId,
|
|
119
|
+
MessageListener(
|
|
120
|
+
onCustomMessageReceived: (msg) {
|
|
121
|
+
if (msg.category != MessageCategoryConstants.custom) return;
|
|
122
|
+
if (msg.type != 'meeting') return;
|
|
123
|
+
|
|
124
|
+
final customData = msg.customData ?? {};
|
|
125
|
+
onIncoming(IncomingMeetingInfo(
|
|
126
|
+
sessionId: customData['sessionId'] as String? ?? msg.receiverUid,
|
|
127
|
+
callType: customData['callType'] as String? ?? 'video',
|
|
128
|
+
fromUid: msg.sender?.uid ?? 'unknown',
|
|
129
|
+
groupGuid: msg.receiverUid,
|
|
130
|
+
));
|
|
131
|
+
},
|
|
132
|
+
),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void unregister() => CometChat.removeMessageListener(groupMeetingListenerId);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
In a Bloc-based app, dispatch an event into your CallBloc; the listener's `onIncoming` callback wraps the Bloc emit.
|
|
141
|
+
|
|
142
|
+
Register AFTER `CometChatUIKit.login` succeeds (e.g. in the auth Bloc's `_onLoginSuccess` state transition).
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Edge cases
|
|
147
|
+
|
|
148
|
+
### V6 vendor blocker context
|
|
149
|
+
|
|
150
|
+
This SKILL.md notes that V6 calling is partially-blocked at v6.0.0-beta2 — specifically the outgoing-call → in-call screen transition. **Production Flutter customers should stay on V5** for both 1:1 and group calls until the vendor fixes the V6 BLoC handler. Group calls on V6 inherit the same blocker.
|
|
151
|
+
|
|
152
|
+
### Late joining
|
|
153
|
+
|
|
154
|
+
Meeting persists in chat. Tap any time to join.
|
|
155
|
+
|
|
156
|
+
### Push notifications
|
|
157
|
+
|
|
158
|
+
Meeting `CustomMessage.metadata.pushNotification = "meeting"` — delivered as regular FCM/APNs. To get CallKit/ConnectionService ring on iOS/Android, intercept the push and route to `flutter_callkit_incoming` manually.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Anti-patterns
|
|
163
|
+
|
|
164
|
+
1. **Only `CometChat.addCallListener` registered.** Won't fire for groups.
|
|
165
|
+
2. **Relying on V6 kit's outgoing-call screen for groups on v6.0.0-beta2.** Vendor blocker. Use custom navigation.
|
|
166
|
+
3. **`CometChat.endCall(sessionId)` after group hangup.** No call entity.
|
|
167
|
+
4. **`MessageListener` registered before login.** Silently dropped.
|
|
168
|
+
5. **Skipping `navigatorKey` setup** for any kit-driven call path.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Verification checklist
|
|
173
|
+
|
|
174
|
+
- [ ] V6 SKILL.md §1.7 `navigatorKey` requirement met (MaterialApp has CallNavigationContext.navigatorKey)
|
|
175
|
+
- [ ] If kit caller: `CometChatCallButtons(group: group)` — but verify outgoing-call transition works post-vendor-fix
|
|
176
|
+
- [ ] If custom caller: `CometChat.sendCustomMessage(type: 'meeting', category: custom, customData: {callType, sessionId})`
|
|
177
|
+
- [ ] If kit receiver: `CometChatMessageList(group: group)` — see V6 vendor blocker caveat
|
|
178
|
+
- [ ] If custom receiver: `CometChat.addMessageListener` registered AFTER login with category+type filter
|
|
179
|
+
- [ ] On hangup: `CometChatUIKitCalls.endSession()` only
|
|
180
|
+
- [ ] Late-joining tested
|
|
181
|
+
- [ ] Push notifications fire for offline members
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Pointers
|
|
186
|
+
|
|
187
|
+
- `cometchat-flutter-v6-calls/SKILL.md` §1.7 — `navigatorKey` requirement + V6 vendor blocker context
|
|
188
|
+
- `ringing-integration.md` — 1:1 user calls (different channel)
|
|
189
|
+
- Cross-platform reference (semantic ground-truth): `cometchat-react-calls/references/group-calls.md`
|
|
190
|
+
- Canonical docs: https://www.cometchat.com/docs/calls/flutter/group-calls
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Idle timeout on Flutter V6 (Bloc-based)
|
|
2
|
+
|
|
3
|
+
Same SDK API as V5; Bloc-based wiring. Read `cometchat-flutter-v5-calls/references/idle-timeout.md` first.
|
|
4
|
+
|
|
5
|
+
**Canonical docs:** https://www.cometchat.com/docs/calls/flutter/idle-timeout
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## SDK API + listener bridge
|
|
10
|
+
|
|
11
|
+
Same `CallSettingsBuilder` setters as V5. Listener via Bloc bridge (cf. `cometchat-flutter-v6-calls/references/raise-hand.md`):
|
|
12
|
+
|
|
13
|
+
```dart
|
|
14
|
+
abstract class CallEvent {}
|
|
15
|
+
class _SessionTimedOut extends CallEvent {}
|
|
16
|
+
|
|
17
|
+
class CallBloc extends Bloc<CallEvent, CallState> implements CometChatCallsEventsListener {
|
|
18
|
+
CallBloc() : super(const CallState()) {
|
|
19
|
+
on<_SessionTimedOut>(_onTimedOut);
|
|
20
|
+
CometChatCalls.addCallEventListener('call-bloc', this);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@override
|
|
24
|
+
void onSessionTimedOut() {
|
|
25
|
+
add(_SessionTimedOut());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void _onTimedOut(_SessionTimedOut event, Emitter<CallState> emit) {
|
|
29
|
+
emit(state.copyWith(timedOut: true));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@override
|
|
33
|
+
Future<void> close() {
|
|
34
|
+
CometChatCalls.removeCallEventListener('call-bloc');
|
|
35
|
+
return super.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
UI listens for `state.timedOut`:
|
|
41
|
+
|
|
42
|
+
```dart
|
|
43
|
+
BlocListener<CallBloc, CallState>(
|
|
44
|
+
listenWhen: (prev, curr) => !prev.timedOut && curr.timedOut,
|
|
45
|
+
listener: (context, state) async {
|
|
46
|
+
ScaffoldMessenger.of(context).showSnackBar(
|
|
47
|
+
const SnackBar(content: Text('Call ended due to inactivity')),
|
|
48
|
+
);
|
|
49
|
+
Navigator.of(context).popUntil((route) => route.isFirst);
|
|
50
|
+
},
|
|
51
|
+
child: /* call surface */,
|
|
52
|
+
)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`BlocListener` is one-shot side effects (navigation, snackbars). `listenWhen` ensures the listener only fires on the transition.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Custom prompt — same showDialog as V5
|
|
60
|
+
|
|
61
|
+
Identical code; cite V5 sister reference.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Verification checklist
|
|
66
|
+
|
|
67
|
+
- [ ] CallSettingsBuilder sets both idle periods
|
|
68
|
+
- [ ] CallBloc bridges `onSessionTimedOut` to `_SessionTimedOut` event
|
|
69
|
+
- [ ] BlocListener with `listenWhen` triggers nav + snackbar
|
|
70
|
+
- [ ] Bloc `close()` removes the listener
|
|
71
|
+
- [ ] Real-device smoke: same as V5
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Pointers
|
|
76
|
+
|
|
77
|
+
- `cometchat-flutter-v5-calls/references/idle-timeout.md` — V5 sister
|
|
78
|
+
- `cometchat-flutter-v6-calls` SKILL.md — V6 hard rules
|
|
79
|
+
- `cometchat-flutter-v6-calls/references/raise-hand.md` — Bloc-bridge sibling pattern
|
|
80
|
+
- Canonical docs: https://www.cometchat.com/docs/calls/flutter/idle-timeout
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# In-call chat on Flutter V6 (Bloc)
|
|
2
|
+
|
|
3
|
+
Same SDK shape; Bloc-driven open/unread state.
|
|
4
|
+
|
|
5
|
+
**Canonical docs:** https://www.cometchat.com/docs/calls/flutter/in-call-chat
|
|
6
|
+
**Read first:** `cometchat-flutter-v5-calls/references/in-call-chat.md` — sheet pattern + group-as-session helper.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## State + bloc
|
|
11
|
+
|
|
12
|
+
```dart
|
|
13
|
+
class InCallChatState extends Equatable {
|
|
14
|
+
final bool open;
|
|
15
|
+
final int unread;
|
|
16
|
+
final Group? group;
|
|
17
|
+
const InCallChatState({this.open = false, this.unread = 0, this.group});
|
|
18
|
+
InCallChatState copyWith({bool? open, int? unread, Group? group}) =>
|
|
19
|
+
InCallChatState(open: open ?? this.open, unread: unread ?? this.unread, group: group ?? this.group);
|
|
20
|
+
@override List<Object?> get props => [open, unread, group?.guid];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
abstract class InCallChatEvent {}
|
|
24
|
+
class InitChat extends InCallChatEvent { final String sessionId; InitChat(this.sessionId); }
|
|
25
|
+
class OpenChat extends InCallChatEvent {}
|
|
26
|
+
class CloseChat extends InCallChatEvent {}
|
|
27
|
+
class _MessageReceived extends InCallChatEvent {}
|
|
28
|
+
|
|
29
|
+
class InCallChatBloc extends Bloc<InCallChatEvent, InCallChatState> {
|
|
30
|
+
InCallChatBloc() : super(const InCallChatState()) {
|
|
31
|
+
on<InitChat>(_onInit);
|
|
32
|
+
on<OpenChat>(_onOpen);
|
|
33
|
+
on<CloseChat>(_onClose);
|
|
34
|
+
on<_MessageReceived>(_onReceived);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
Future<void> _onInit(InitChat event, Emitter<InCallChatState> emit) async {
|
|
38
|
+
final group = await ensureCallGroup(event.sessionId);
|
|
39
|
+
emit(state.copyWith(group: group));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
void _onOpen(OpenChat event, Emitter<InCallChatState> emit) {
|
|
43
|
+
emit(state.copyWith(open: true, unread: 0));
|
|
44
|
+
CometChatCalls.setChatButtonUnreadCount(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void _onClose(OpenChat event, Emitter<InCallChatState> emit) {
|
|
48
|
+
emit(state.copyWith(open: false));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void _onReceived(_MessageReceived event, Emitter<InCallChatState> emit) {
|
|
52
|
+
if (state.open) return;
|
|
53
|
+
final next = state.unread + 1;
|
|
54
|
+
emit(state.copyWith(unread: next));
|
|
55
|
+
CometChatCalls.setChatButtonUnreadCount(next);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Triggering open from SDK event
|
|
63
|
+
|
|
64
|
+
In your `CometChatCallsEventsListener` impl:
|
|
65
|
+
|
|
66
|
+
```dart
|
|
67
|
+
@override
|
|
68
|
+
void onChatButtonClicked() {
|
|
69
|
+
context.read<InCallChatBloc>().add(OpenChat());
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Sheet UI
|
|
76
|
+
|
|
77
|
+
Same `showModalBottomSheet` shape as V5. Use `BlocSelector` to react to `state.open`:
|
|
78
|
+
|
|
79
|
+
```dart
|
|
80
|
+
BlocListener<InCallChatBloc, InCallChatState>(
|
|
81
|
+
listenWhen: (prev, curr) => !prev.open && curr.open,
|
|
82
|
+
listener: (context, state) {
|
|
83
|
+
if (state.group == null) return;
|
|
84
|
+
showModalBottomSheet(
|
|
85
|
+
context: context,
|
|
86
|
+
isScrollControlled: true,
|
|
87
|
+
barrierColor: Colors.transparent,
|
|
88
|
+
builder: (_) => InCallChatPanel(group: state.group!),
|
|
89
|
+
).whenComplete(() {
|
|
90
|
+
context.read<InCallChatBloc>().add(CloseChat());
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
child: /* call surface */,
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Anti-patterns
|
|
100
|
+
|
|
101
|
+
V5 sister rules apply, plus V6-specific:
|
|
102
|
+
|
|
103
|
+
1. **`BlocBuilder` instead of `BlocListener` for opening the sheet.** BlocBuilder is for rebuilding UI; sheet-open is a one-shot side effect → BlocListener.
|
|
104
|
+
2. **`listenWhen` omitted.** Sheet opens on every state change.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Verification checklist
|
|
109
|
+
|
|
110
|
+
- [ ] InCallChatBloc with `InitChat`, `OpenChat`, `CloseChat`, `_MessageReceived` events
|
|
111
|
+
- [ ] BlocListener with `listenWhen` for the open transition
|
|
112
|
+
- [ ] `showModalBottomSheet.whenComplete` dispatches `CloseChat`
|
|
113
|
+
- [ ] Real-device smoke: same as V5
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Pointers
|
|
118
|
+
|
|
119
|
+
- `cometchat-flutter-v5-calls/references/in-call-chat.md` — V5 sister (sheet pattern)
|
|
120
|
+
- `cometchat-flutter-v6-calls` SKILL.md
|
|
121
|
+
- `cometchat-flutter-v6-calls/references/raise-hand.md` — Bloc bridge sibling
|
|
122
|
+
- Canonical docs: https://www.cometchat.com/docs/calls/flutter/in-call-chat
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Raise hand on Flutter (UIKit V6, Bloc-based)
|
|
2
|
+
|
|
3
|
+
Same SDK conceptual API as V5; the difference is state management — V6 uses `flutter_bloc` rather than GetX. The reactive shape is `RaiseHandBloc → emit(state)` where state is an immutable record of `localRaised + raisedParticipants`.
|
|
4
|
+
|
|
5
|
+
**Canonical docs:** https://www.cometchat.com/docs/calls/flutter/raise-hand
|
|
6
|
+
**Read first:** `cometchat-flutter-v5-calls/references/raise-hand.md` — UX shape is identical; this is the V6 Bloc translation.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## SDK API (same as V5)
|
|
11
|
+
|
|
12
|
+
```dart
|
|
13
|
+
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
|
|
14
|
+
import 'package:cometchat_chat_uikit/cometchat_calls_uikit.dart';
|
|
15
|
+
|
|
16
|
+
CometChatCalls.raiseHand();
|
|
17
|
+
CometChatCalls.lowerHand();
|
|
18
|
+
|
|
19
|
+
// In a CometChatCallsEventsListener implementation:
|
|
20
|
+
@override
|
|
21
|
+
void onParticipantHandRaised(Participant p) { /* ... */ }
|
|
22
|
+
@override
|
|
23
|
+
void onParticipantHandLowered(Participant p) { /* ... */ }
|
|
24
|
+
|
|
25
|
+
final settings = CallSettingsBuilder()..hideRaiseHandButton = true;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Bloc setup
|
|
31
|
+
|
|
32
|
+
```dart
|
|
33
|
+
import 'package:bloc/bloc.dart';
|
|
34
|
+
import 'package:equatable/equatable.dart';
|
|
35
|
+
import 'package:cometchat_chat_uikit/cometchat_calls_uikit.dart';
|
|
36
|
+
|
|
37
|
+
// State
|
|
38
|
+
class RaiseHandState extends Equatable {
|
|
39
|
+
final bool localRaised;
|
|
40
|
+
final List<RaisedParticipant> raised;
|
|
41
|
+
const RaiseHandState({this.localRaised = false, this.raised = const []});
|
|
42
|
+
|
|
43
|
+
RaiseHandState copyWith({bool? localRaised, List<RaisedParticipant>? raised}) =>
|
|
44
|
+
RaiseHandState(
|
|
45
|
+
localRaised: localRaised ?? this.localRaised,
|
|
46
|
+
raised: raised ?? this.raised,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
@override
|
|
50
|
+
List<Object> get props => [localRaised, raised];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class RaisedParticipant extends Equatable {
|
|
54
|
+
final String uid;
|
|
55
|
+
final String name;
|
|
56
|
+
final DateTime raisedAt;
|
|
57
|
+
const RaisedParticipant({required this.uid, required this.name, required this.raisedAt});
|
|
58
|
+
@override
|
|
59
|
+
List<Object> get props => [uid, name, raisedAt];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Events
|
|
63
|
+
abstract class RaiseHandEvent {}
|
|
64
|
+
class ToggleHand extends RaiseHandEvent {}
|
|
65
|
+
class _ParticipantRaised extends RaiseHandEvent {
|
|
66
|
+
final Participant participant;
|
|
67
|
+
_ParticipantRaised(this.participant);
|
|
68
|
+
}
|
|
69
|
+
class _ParticipantLowered extends RaiseHandEvent {
|
|
70
|
+
final Participant participant;
|
|
71
|
+
_ParticipantLowered(this.participant);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Bloc implementation
|
|
78
|
+
|
|
79
|
+
```dart
|
|
80
|
+
class RaiseHandBloc extends Bloc<RaiseHandEvent, RaiseHandState>
|
|
81
|
+
implements CometChatCallsEventsListener {
|
|
82
|
+
|
|
83
|
+
RaiseHandBloc() : super(const RaiseHandState()) {
|
|
84
|
+
on<ToggleHand>(_onToggle);
|
|
85
|
+
on<_ParticipantRaised>(_onParticipantRaised);
|
|
86
|
+
on<_ParticipantLowered>(_onParticipantLowered);
|
|
87
|
+
|
|
88
|
+
// Self-register as the call event listener
|
|
89
|
+
CometChatCalls.addCallEventListener('raise-hand-bloc', this);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void _onToggle(ToggleHand event, Emitter<RaiseHandState> emit) {
|
|
93
|
+
if (state.localRaised) {
|
|
94
|
+
CometChatCalls.lowerHand();
|
|
95
|
+
} else {
|
|
96
|
+
CometChatCalls.raiseHand();
|
|
97
|
+
}
|
|
98
|
+
emit(state.copyWith(localRaised: !state.localRaised));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void _onParticipantRaised(_ParticipantRaised event, Emitter<RaiseHandState> emit) {
|
|
102
|
+
final entry = RaisedParticipant(
|
|
103
|
+
uid: event.participant.uid,
|
|
104
|
+
name: event.participant.name,
|
|
105
|
+
raisedAt: DateTime.now(),
|
|
106
|
+
);
|
|
107
|
+
final next = [...state.raised.where((r) => r.uid != entry.uid), entry];
|
|
108
|
+
next.sort((a, b) => a.raisedAt.compareTo(b.raisedAt));
|
|
109
|
+
emit(state.copyWith(raised: next));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void _onParticipantLowered(_ParticipantLowered event, Emitter<RaiseHandState> emit) {
|
|
113
|
+
final next = state.raised.where((r) => r.uid != event.participant.uid).toList();
|
|
114
|
+
emit(state.copyWith(raised: next));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// CometChatCallsEventsListener — bridge to Bloc events
|
|
118
|
+
@override
|
|
119
|
+
void onParticipantHandRaised(Participant p) {
|
|
120
|
+
add(_ParticipantRaised(p));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@override
|
|
124
|
+
void onParticipantHandLowered(Participant p) {
|
|
125
|
+
add(_ParticipantLowered(p));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ... implement other CometChatCallsEventsListener methods (no-ops or pass-through)
|
|
129
|
+
|
|
130
|
+
@override
|
|
131
|
+
Future<void> close() {
|
|
132
|
+
CometChatCalls.removeCallEventListener('raise-hand-bloc');
|
|
133
|
+
return super.close();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The bridge pattern: the bloc IS the SDK listener. SDK callbacks call `add()` on the bloc, which dispatches an event handler that emits new state. This keeps Bloc's "single source of truth" intact — no parallel state outside the bloc.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Toggle button widget
|
|
143
|
+
|
|
144
|
+
```dart
|
|
145
|
+
class RaiseHandButton extends StatelessWidget {
|
|
146
|
+
const RaiseHandButton({super.key});
|
|
147
|
+
|
|
148
|
+
@override
|
|
149
|
+
Widget build(BuildContext context) {
|
|
150
|
+
return BlocBuilder<RaiseHandBloc, RaiseHandState>(
|
|
151
|
+
buildWhen: (prev, curr) => prev.localRaised != curr.localRaised,
|
|
152
|
+
builder: (context, state) => Semantics(
|
|
153
|
+
button: true,
|
|
154
|
+
selected: state.localRaised,
|
|
155
|
+
label: state.localRaised ? 'Lower hand' : 'Raise hand',
|
|
156
|
+
child: GestureDetector(
|
|
157
|
+
onTap: () {
|
|
158
|
+
context.read<RaiseHandBloc>().add(ToggleHand());
|
|
159
|
+
SemanticsService.announce(
|
|
160
|
+
state.localRaised ? 'Hand lowered' : 'Hand raised',
|
|
161
|
+
TextDirection.ltr,
|
|
162
|
+
);
|
|
163
|
+
},
|
|
164
|
+
child: Container(
|
|
165
|
+
padding: const EdgeInsets.all(12),
|
|
166
|
+
decoration: BoxDecoration(
|
|
167
|
+
color: state.localRaised ? const Color(0xFFFFD60A) : Colors.white24,
|
|
168
|
+
borderRadius: BorderRadius.circular(32),
|
|
169
|
+
),
|
|
170
|
+
child: Row(
|
|
171
|
+
children: [
|
|
172
|
+
const Text('✋'),
|
|
173
|
+
const SizedBox(width: 4),
|
|
174
|
+
Text(state.localRaised ? 'Lower' : 'Raise'),
|
|
175
|
+
],
|
|
176
|
+
),
|
|
177
|
+
),
|
|
178
|
+
),
|
|
179
|
+
),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`buildWhen` ensures the button only rebuilds when `localRaised` changes — not on every roster update. Performance discipline matters in a video call.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Raised-hands sheet
|
|
190
|
+
|
|
191
|
+
Same `DraggableScrollableSheet` shape as V5; bind via `BlocBuilder` instead of `Obx`:
|
|
192
|
+
|
|
193
|
+
```dart
|
|
194
|
+
BlocBuilder<RaiseHandBloc, RaiseHandState>(
|
|
195
|
+
buildWhen: (prev, curr) => prev.raised != curr.raised,
|
|
196
|
+
builder: (context, state) => ListView(
|
|
197
|
+
children: [
|
|
198
|
+
Text('Raised hands (${state.raised.length})'),
|
|
199
|
+
for (final p in state.raised)
|
|
200
|
+
ListTile(leading: const Text('✋'), title: Text(p.name)),
|
|
201
|
+
],
|
|
202
|
+
),
|
|
203
|
+
)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`buildWhen` again — only rebuild when the roster changes, not on toggle.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Wiring to the call screen
|
|
211
|
+
|
|
212
|
+
```dart
|
|
213
|
+
class CallScreen extends StatelessWidget {
|
|
214
|
+
@override
|
|
215
|
+
Widget build(BuildContext context) {
|
|
216
|
+
return BlocProvider(
|
|
217
|
+
create: (_) => RaiseHandBloc(),
|
|
218
|
+
child: Scaffold(
|
|
219
|
+
body: Stack(
|
|
220
|
+
children: [
|
|
221
|
+
// ... call surface (CometChatOngoingCall)
|
|
222
|
+
const Positioned(bottom: 100, right: 20, child: RaiseHandButton()),
|
|
223
|
+
const RaisedHandsSheet(),
|
|
224
|
+
],
|
|
225
|
+
),
|
|
226
|
+
),
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`BlocProvider(create:)` scopes the bloc to the screen — disposed automatically on screen pop.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Anti-patterns
|
|
237
|
+
|
|
238
|
+
Web sister reference rules apply, plus V6-specific:
|
|
239
|
+
|
|
240
|
+
1. **`buildWhen` omitted.** Every state change rebuilds every BlocBuilder — lots of unnecessary work during a call. Add `buildWhen` for narrow rebuilds.
|
|
241
|
+
2. **Mutating `state.raised` directly** instead of creating a new list. `Equatable` props compare via `==`; mutation doesn't trigger rebuild.
|
|
242
|
+
3. **Calling `CometChatCalls.raiseHand()` outside the bloc.** Bypasses the state machine; UI doesn't update. Always go through `add(ToggleHand())`.
|
|
243
|
+
4. **Adding the SDK listener in `initState`** instead of the bloc constructor. Component-level lifecycle ≠ Bloc lifecycle. Bloc `close()` is the canonical place to clean up.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Verification checklist
|
|
248
|
+
|
|
249
|
+
- [ ] `RaiseHandBloc` extends `Bloc<RaiseHandEvent, RaiseHandState>`
|
|
250
|
+
- [ ] `RaiseHandState` extends `Equatable` with proper `props`
|
|
251
|
+
- [ ] Bloc registers itself as `CometChatCallsEventsListener` in constructor
|
|
252
|
+
- [ ] Bloc `close()` removes the listener
|
|
253
|
+
- [ ] `BlocProvider(create:)` scopes the bloc to the call screen
|
|
254
|
+
- [ ] `buildWhen` on every BlocBuilder narrows rebuilds
|
|
255
|
+
- [ ] `Semantics` + `SemanticsService.announce` for a11y
|
|
256
|
+
- [ ] `hideRaiseHandButton: true` in CallSettings if custom UI
|
|
257
|
+
- [ ] Real-device smoke: 3 devices (iOS + Android), 2 raise hands, host sees both
|
|
258
|
+
- [ ] Hot-reload smoke: trigger raise → save code → bloc state survives (bloc is created via `create:`, persists across hot reload)
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Pointers
|
|
263
|
+
|
|
264
|
+
- `cometchat-react-calls/references/raise-hand.md` — sister reference (UX shape)
|
|
265
|
+
- `cometchat-flutter-v5-calls/references/raise-hand.md` — V5 sibling (GetX-based)
|
|
266
|
+
- `cometchat-flutter-v6-calls` SKILL.md — V6 hard rules + Bloc patterns
|
|
267
|
+
- `cometchat-a11y` — Flutter Semantics + SemanticsService
|
|
268
|
+
- Canonical docs: https://www.cometchat.com/docs/calls/flutter/raise-hand
|