@cometchat/skills 4.4.2 → 5.0.1
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/.claude-plugin/marketplace.json +55 -0
- package/.claude-plugin/plugin.json +14 -0
- package/CHANGELOG.md +44 -0
- package/LICENSE +21 -0
- package/MIGRATING.md +187 -0
- package/README.md +52 -156
- package/RULES.md +125 -0
- package/bin/cometchat-skills.mjs +1280 -0
- package/bin/legacy-skills.json +95 -0
- package/catalogs/android-v6.json +1646 -0
- package/catalogs/flutter-v6.json +651 -0
- package/catalogs/ios-v5.json +1383 -0
- package/catalogs/rn-calls-v5.json +134 -0
- package/catalogs/rn-calls-v5.symbols.txt +58 -0
- package/catalogs/rn-sdk-v4.json +672 -0
- package/catalogs/rn-v5.json +449 -0
- package/catalogs/rn-v5.symbols.txt +216 -0
- package/catalogs/sdk-android-v5.json +514 -0
- package/contracts.android-calls-v5.json +122 -0
- package/contracts.android-v6.json +135 -0
- package/contracts.angular-v5.json +694 -0
- package/contracts.flutter-calls-v5.json +77 -0
- package/contracts.flutter-v6.json +126 -0
- package/contracts.ios-calls-v5.json +67 -0
- package/contracts.ios-v5.json +436 -0
- package/contracts.json +82 -0
- package/contracts.rn-calls-v5.json +77 -0
- package/contracts.rn-v5.json +727 -0
- package/contracts.sdk-android-v5.json +15 -0
- package/contracts.web-calls-v5.json +45 -0
- package/features.android-calls-v5.json +246 -0
- package/features.android-v6.json +65 -0
- package/features.angular-v5.json +521 -0
- package/features.flutter-calls-v5.json +286 -0
- package/features.flutter-v6.json +484 -0
- package/features.ios-calls-v5.json +236 -0
- package/features.ios-v5.json +573 -0
- package/features.json +61 -0
- package/features.rn-calls-v5.json +187 -0
- package/features.rn-v5.json +614 -0
- package/features.sdk-android-v5.json +40 -0
- package/features.sdk-jsv4.json +24 -0
- package/features.web-calls-v5.json +108 -0
- package/package.json +156 -74
- package/peers.yaml +355 -0
- package/registry/README.md +31 -0
- package/registry/android-calls-v5.json +94 -0
- package/registry/android-v6.json +177 -0
- package/registry/angular-v5.json +154 -0
- package/registry/flutter-calls-v5.json +94 -0
- package/registry/flutter-v6.json +159 -0
- package/registry/ios-calls-v5.json +99 -0
- package/registry/ios-v5.json +152 -0
- package/registry/rn-calls-v5.json +99 -0
- package/registry/rn-v5.json +169 -0
- package/registry/sdk-android-v5.json +93 -0
- package/registry/sdk-jsv4.json +93 -0
- package/registry/web-calls-v5.json +94 -0
- package/registry/web-v7.json +154 -0
- package/skills/cometchat/SKILL.md +47 -2096
- package/skills/cometchat-a11y/SKILL.md +44 -472
- package/skills/cometchat-analytics/SKILL.md +61 -0
- package/skills/cometchat-android-v5-calls-sdk/SKILL.md +206 -0
- package/skills/cometchat-android-v5-calls-sdk/references/build-truth.md +63 -0
- package/skills/cometchat-android-v5-calls-sdk/references/docs-map.md +119 -0
- package/skills/cometchat-android-v5-calls-sdk/references/method-map.md +53 -0
- package/skills/cometchat-android-v5-calls-sdk/references/pitfalls.md +72 -0
- package/skills/cometchat-android-v5-calls-sdk/references/ringing.md +92 -0
- package/skills/cometchat-android-v5-calls-sdk/references/user-switch.md +90 -0
- package/skills/cometchat-android-v5-sdk/SKILL.md +127 -0
- package/skills/cometchat-android-v5-sdk/references/app-surface.md +88 -0
- package/skills/cometchat-android-v5-sdk/references/docs-map.md +91 -0
- package/skills/cometchat-android-v6-builder-settings/SKILL.md +51 -137
- package/skills/cometchat-android-v6-calls/SKILL.md +128 -413
- package/skills/cometchat-android-v6-compose-components/SKILL.md +84 -194
- package/skills/cometchat-android-v6-compose-customization/SKILL.md +66 -411
- package/skills/cometchat-android-v6-compose-placement/SKILL.md +154 -237
- package/skills/cometchat-android-v6-core/SKILL.md +236 -672
- package/skills/cometchat-android-v6-core/references/anti-patterns.md +31 -0
- package/skills/cometchat-android-v6-core/references/component-props.md +168 -0
- package/skills/cometchat-android-v6-core/references/docs-map.md +153 -0
- package/skills/cometchat-android-v6-core/references/layout.md +112 -0
- package/skills/cometchat-android-v6-core/references/lifecycle.md +75 -0
- package/skills/cometchat-android-v6-core/references/setup-credentials.md +105 -0
- package/skills/cometchat-android-v6-core/references/troubleshooting.md +36 -0
- package/skills/cometchat-android-v6-events/SKILL.md +46 -184
- package/skills/cometchat-android-v6-extensions/SKILL.md +39 -179
- package/skills/cometchat-android-v6-features/SKILL.md +74 -143
- package/skills/cometchat-android-v6-kotlin-components/SKILL.md +75 -193
- package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +67 -419
- package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +77 -223
- package/skills/cometchat-android-v6-migration/SKILL.md +67 -378
- package/skills/cometchat-android-v6-production/SKILL.md +41 -179
- package/skills/cometchat-android-v6-push/SKILL.md +39 -289
- package/skills/cometchat-android-v6-testing/SKILL.md +50 -265
- package/skills/cometchat-android-v6-troubleshooting/SKILL.md +70 -254
- package/skills/cometchat-angular-v5-calls/SKILL.md +193 -0
- package/skills/cometchat-angular-v5-components/SKILL.md +131 -0
- package/skills/cometchat-angular-v5-components/references/catalog.md +111 -0
- package/skills/cometchat-angular-v5-components/references/host-composed.md +46 -0
- package/skills/cometchat-angular-v5-core/SKILL.md +300 -0
- package/skills/cometchat-angular-v5-core/references/anti-patterns.md +49 -0
- package/skills/cometchat-angular-v5-core/references/component-props.md +55 -0
- package/skills/cometchat-angular-v5-core/references/dependencies.md +66 -0
- package/skills/cometchat-angular-v5-core/references/docs-map.md +132 -0
- package/skills/cometchat-angular-v5-core/references/layout.md +64 -0
- package/skills/cometchat-angular-v5-core/references/lifecycle.md +202 -0
- package/skills/cometchat-angular-v5-core/references/setup-credentials.md +137 -0
- package/skills/cometchat-angular-v5-core/references/theming.md +70 -0
- package/skills/cometchat-angular-v5-core/references/troubleshooting.md +27 -0
- package/skills/cometchat-angular-v5-customization/SKILL.md +94 -0
- package/skills/cometchat-angular-v5-features/SKILL.md +107 -0
- package/skills/cometchat-angular-v5-features/references/custom-messages.md +133 -0
- package/skills/cometchat-angular-v5-features/references/formatters.md +28 -0
- package/skills/cometchat-angular-v5-features/references/host-composed-extensions.md +85 -0
- package/skills/cometchat-angular-v5-migration/SKILL.md +40 -0
- package/skills/cometchat-angular-v5-migration/references/migration-guide.md +165 -0
- package/skills/cometchat-angular-v5-patterns/SKILL.md +107 -0
- package/skills/cometchat-angular-v5-placement/SKILL.md +133 -0
- package/skills/cometchat-angular-v5-placement/references/combined-app.md +174 -0
- package/skills/cometchat-angular-v5-placement/references/core-surface.md +199 -0
- package/skills/cometchat-angular-v5-production/SKILL.md +102 -0
- package/skills/cometchat-angular-v5-push/SKILL.md +61 -0
- package/skills/cometchat-angular-v5-testing/SKILL.md +112 -0
- package/skills/cometchat-angular-v5-troubleshooting/SKILL.md +96 -0
- package/skills/cometchat-audit/SKILL.md +61 -0
- package/skills/cometchat-compliance/SKILL.md +63 -0
- package/skills/cometchat-flutter-v5-sdk/SKILL.md +188 -0
- package/skills/cometchat-flutter-v5-sdk/references/doc-corrections.md +55 -0
- package/skills/cometchat-flutter-v5-sdk/references/docs-map.md +211 -0
- package/skills/cometchat-flutter-v5-sdk/references/platform-notes.md +48 -0
- package/skills/cometchat-flutter-v5-sdk/references/transcription.md +87 -0
- package/skills/cometchat-flutter-v6-calls/SKILL.md +75 -389
- package/skills/cometchat-flutter-v6-components/SKILL.md +88 -361
- package/skills/cometchat-flutter-v6-core/SKILL.md +154 -593
- package/skills/cometchat-flutter-v6-core/references/anti-patterns.md +55 -0
- package/skills/cometchat-flutter-v6-core/references/docs-map.md +143 -0
- package/skills/cometchat-flutter-v6-core/references/layout.md +45 -0
- package/skills/cometchat-flutter-v6-core/references/lifecycle.md +87 -0
- package/skills/cometchat-flutter-v6-core/references/setup-credentials.md +84 -0
- package/skills/cometchat-flutter-v6-core/references/troubleshooting.md +26 -0
- package/skills/cometchat-flutter-v6-customization/SKILL.md +70 -712
- package/skills/cometchat-flutter-v6-events/SKILL.md +79 -174
- package/skills/cometchat-flutter-v6-features/SKILL.md +55 -394
- package/skills/cometchat-flutter-v6-migration/SKILL.md +68 -367
- package/skills/cometchat-flutter-v6-migration/references/migration-guide.md +132 -0
- package/skills/cometchat-flutter-v6-patterns/SKILL.md +61 -0
- package/skills/cometchat-flutter-v6-placement/SKILL.md +94 -381
- package/skills/cometchat-flutter-v6-production/SKILL.md +59 -615
- package/skills/cometchat-flutter-v6-push/SKILL.md +46 -455
- package/skills/cometchat-flutter-v6-testing/SKILL.md +68 -299
- package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +54 -878
- package/skills/cometchat-i18n/SKILL.md +35 -404
- package/skills/cometchat-ios-calls/SKILL.md +112 -563
- package/skills/cometchat-ios-components/SKILL.md +44 -834
- package/skills/cometchat-ios-core/SKILL.md +182 -1068
- package/skills/cometchat-ios-core/references/anti-patterns.md +113 -0
- package/skills/cometchat-ios-core/references/docs-map.md +124 -0
- package/skills/cometchat-ios-core/references/install.md +23 -0
- package/skills/cometchat-ios-core/references/layout.md +219 -0
- package/skills/cometchat-ios-core/references/setup-credentials.md +197 -0
- package/skills/cometchat-ios-core/references/swiftui.md +91 -0
- package/skills/cometchat-ios-core/references/troubleshooting.md +100 -0
- package/skills/cometchat-ios-customization/SKILL.md +33 -968
- package/skills/cometchat-ios-features/SKILL.md +29 -738
- package/skills/cometchat-ios-migration/SKILL.md +39 -0
- package/skills/cometchat-ios-placement/SKILL.md +51 -729
- package/skills/cometchat-ios-production/SKILL.md +67 -723
- package/skills/cometchat-ios-push/SKILL.md +24 -602
- package/skills/cometchat-ios-testing/SKILL.md +36 -355
- package/skills/cometchat-ios-troubleshooting/SKILL.md +31 -989
- package/skills/cometchat-ios-v5-sdk/SKILL.md +161 -0
- package/skills/cometchat-ios-v5-sdk/references/docs-map.md +326 -0
- package/skills/cometchat-js-v5-sdk/SKILL.md +95 -0
- package/skills/cometchat-js-v5-sdk/references/docs-map.md +114 -0
- package/skills/cometchat-migrate-from-getstream/SKILL.md +65 -0
- package/skills/cometchat-migrate-from-getstream/references/concept-map.md +98 -0
- package/skills/cometchat-migrate-from-getstream/references/data-migration.md +74 -0
- package/skills/cometchat-migrate-from-getstream/references/feature-map.md +108 -0
- package/skills/cometchat-migrate-from-getstream/references/inventory.md +82 -0
- package/skills/cometchat-migrate-from-getstream/references/native-build.md +9 -0
- package/skills/cometchat-migrate-from-getstream/references/report-template.md +59 -0
- package/skills/cometchat-migrate-from-sendbird/SKILL.md +64 -0
- package/skills/cometchat-migrate-from-sendbird/references/concept-map.md +99 -0
- package/skills/cometchat-migrate-from-sendbird/references/data-migration.md +74 -0
- package/skills/cometchat-migrate-from-sendbird/references/feature-map.md +104 -0
- package/skills/cometchat-migrate-from-sendbird/references/inventory.md +86 -0
- package/skills/cometchat-migrate-from-sendbird/references/native-build.md +10 -0
- package/skills/cometchat-migrate-from-sendbird/references/report-template.md +59 -0
- package/skills/cometchat-migrate-from-twilio/SKILL.md +52 -0
- package/skills/cometchat-migrate-from-twilio/references/concept-map.md +49 -0
- package/skills/cometchat-migrate-from-twilio/references/data-migration.md +50 -0
- package/skills/cometchat-migrate-from-twilio/references/feature-map.md +27 -0
- package/skills/cometchat-migrate-from-twilio/references/inventory.md +53 -0
- package/skills/cometchat-migrate-from-twilio/references/report-template.md +52 -0
- package/skills/cometchat-moderation/SKILL.md +58 -0
- package/skills/cometchat-onboarding/SKILL.md +92 -0
- package/skills/cometchat-onboarding/references/archetypes.md +51 -0
- package/skills/cometchat-onboarding/references/calling-first.md +77 -0
- package/skills/cometchat-onboarding/references/not-in-this-pack.md +8 -0
- package/skills/cometchat-onboarding/references/plan-artifact.md +133 -0
- package/skills/cometchat-onboarding/references/platforms.md +105 -0
- package/skills/cometchat-react-native-bare-patterns/SKILL.md +120 -0
- package/skills/cometchat-react-native-calls/SKILL.md +200 -0
- package/skills/cometchat-react-native-components/SKILL.md +142 -0
- package/skills/cometchat-react-native-core/SKILL.md +335 -0
- package/skills/cometchat-react-native-core/references/anti-patterns.md +79 -0
- package/skills/cometchat-react-native-core/references/component-props.md +105 -0
- package/skills/cometchat-react-native-core/references/dependencies.md +62 -0
- package/skills/cometchat-react-native-core/references/docs-map.md +127 -0
- package/skills/cometchat-react-native-core/references/layout.md +61 -0
- package/skills/cometchat-react-native-core/references/lifecycle.md +64 -0
- package/skills/cometchat-react-native-core/references/setup-credentials.md +39 -0
- package/skills/cometchat-react-native-customization/SKILL.md +198 -0
- package/skills/cometchat-react-native-expo-patterns/SKILL.md +116 -0
- package/skills/cometchat-react-native-features/SKILL.md +122 -0
- package/skills/cometchat-react-native-migration/SKILL.md +103 -0
- package/skills/cometchat-react-native-placement/SKILL.md +158 -0
- package/skills/cometchat-react-native-production/SKILL.md +79 -0
- package/skills/cometchat-react-native-push/SKILL.md +88 -0
- package/skills/cometchat-react-native-sdk/SKILL.md +133 -0
- package/skills/cometchat-react-native-sdk/references/method-map.md +239 -0
- package/skills/cometchat-react-native-sdk/references/page-map.md +96 -0
- package/skills/cometchat-react-native-testing/SKILL.md +94 -0
- package/skills/cometchat-react-native-troubleshooting/SKILL.md +174 -0
- package/skills/cometchat-react-native-v5-sdk/SKILL.md +150 -0
- package/skills/cometchat-react-native-v5-sdk/references/docs-map.md +127 -0
- package/skills/cometchat-react-native-v5-sdk/references/ringing-voip.md +369 -0
- package/skills/cometchat-react-v7-calls/SKILL.md +75 -0
- package/skills/cometchat-react-v7-components/SKILL.md +72 -0
- package/skills/cometchat-react-v7-core/SKILL.md +101 -0
- package/skills/cometchat-react-v7-core/references/anti-patterns.md +19 -0
- package/skills/cometchat-react-v7-core/references/component-props.md +82 -0
- package/skills/cometchat-react-v7-core/references/dependencies.md +23 -0
- package/skills/cometchat-react-v7-core/references/docs-map.md +117 -0
- package/skills/cometchat-react-v7-core/references/layout.md +150 -0
- package/skills/cometchat-react-v7-core/references/lifecycle.md +74 -0
- package/skills/cometchat-react-v7-core/references/setup-credentials.md +58 -0
- package/skills/cometchat-react-v7-core/references/ssr.md +11 -0
- package/skills/cometchat-react-v7-core/references/theming.md +52 -0
- package/skills/cometchat-react-v7-customization/SKILL.md +84 -0
- package/skills/cometchat-react-v7-features/SKILL.md +92 -0
- package/skills/cometchat-react-v7-migration/SKILL.md +39 -0
- package/skills/cometchat-react-v7-migration/references/migration-guide.md +119 -0
- package/skills/cometchat-react-v7-patterns/SKILL.md +43 -0
- package/skills/cometchat-react-v7-placement/SKILL.md +106 -0
- package/skills/cometchat-react-v7-placement/references/recipes.md +354 -0
- package/skills/cometchat-react-v7-production/SKILL.md +84 -0
- package/skills/cometchat-react-v7-push/SKILL.md +53 -0
- package/skills/cometchat-react-v7-testing/SKILL.md +60 -0
- package/skills/cometchat-react-v7-troubleshooting/SKILL.md +47 -0
- package/skills/cometchat-security/SKILL.md +80 -0
- package/skills/cometchat-self-host/SKILL.md +56 -0
- package/test-suite/README.md +70 -0
- package/test-suite/catalogs/android-calls-v5.json +830 -0
- package/test-suite/catalogs/android-calls-v5.symbols.txt +499 -0
- package/test-suite/catalogs/android-v6.json +1646 -0
- package/test-suite/catalogs/android-v6.symbols.txt +298 -0
- package/test-suite/catalogs/angular-v5.json +7587 -0
- package/test-suite/catalogs/flutter-calls-v5.json +196 -0
- package/test-suite/catalogs/flutter-calls-v5.symbols.txt +59 -0
- package/test-suite/catalogs/flutter-v6.json +651 -0
- package/test-suite/catalogs/ios-calls-v5.json +158 -0
- package/test-suite/catalogs/ios-calls-v5.symbols.txt +70 -0
- package/test-suite/catalogs/ios-v5.json +1383 -0
- package/test-suite/catalogs/ios-v5.symbols.txt +699 -0
- package/test-suite/catalogs/rn-calls-v5.json +134 -0
- package/test-suite/catalogs/rn-sdk-v4.json +672 -0
- package/test-suite/catalogs/rn-v5.json +449 -0
- package/test-suite/catalogs/sdk-android-v5.json +514 -0
- package/test-suite/catalogs/sdk-android-v5.symbols.txt +254 -0
- package/test-suite/catalogs/sdk-jsv4.json +800 -0
- package/test-suite/catalogs/web-calls-v5.json +195 -0
- package/test-suite/catalogs/web-v7.json +1243 -0
- package/test-suite/scripts/build-registry.mjs +113 -0
- package/test-suite/scripts/catalog-refresh-dart.mjs +151 -0
- package/test-suite/scripts/catalog-refresh.mjs +100 -0
- package/test-suite/scripts/lint-skills.mjs +932 -0
- package/test-suite/scripts/measure-tokens.mjs +169 -0
- package/test-suite/scripts/typecheck-fences-dart.mjs +437 -0
- package/test-suite/scripts/typecheck-fences-kotlin.mjs +269 -0
- package/test-suite/scripts/typecheck-fences.mjs +206 -0
- package/test-suite/scripts/verify-catalog.mjs +242 -0
- package/test-suite/scripts/verify-contract-fences.mjs +94 -0
- package/test-suite/scripts/verify-detection.mjs +178 -0
- package/test-suite/scripts/verify-docs-base.mjs +91 -0
- package/test-suite/scripts/verify-family-agnostic.mjs +134 -0
- package/test-suite/scripts/verify-golden-path.mjs +138 -0
- package/test-suite/scripts/verify-oracle-components.mjs +133 -0
- package/test-suite/scripts/verify-template-bindings.mjs +148 -0
- package/test-suite/typecheck/angular-v5/package.json +21 -0
- package/test-suite/typecheck/angular-v5/tsconfig.json +21 -0
- package/test-suite/typecheck/flutter-v6/analysis_options.yaml +25 -0
- package/test-suite/typecheck/flutter-v6/pubspec.yaml +21 -0
- package/test-suite/typecheck/web-v7/package.json +18 -0
- package/test-suite/typecheck/web-v7/tsconfig.json +19 -0
- package/bin/install.js +0 -1003
- package/skills/.claude-plugin/marketplace.json +0 -86
- package/skills/cometchat/references/asking-questions.md +0 -48
- package/skills/cometchat-android-v5/SKILL.md +0 -121
- package/skills/cometchat-android-v5-calls/SKILL.md +0 -429
- package/skills/cometchat-android-v5-calls/references/README.md +0 -53
- package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +0 -197
- package/skills/cometchat-android-v5-calls/references/audio-controls.md +0 -91
- package/skills/cometchat-android-v5-calls/references/background-handling.md +0 -168
- package/skills/cometchat-android-v5-calls/references/call-layouts.md +0 -131
- package/skills/cometchat-android-v5-calls/references/call-logs.md +0 -113
- package/skills/cometchat-android-v5-calls/references/call-session.md +0 -274
- package/skills/cometchat-android-v5-calls/references/custom-ui.md +0 -150
- package/skills/cometchat-android-v5-calls/references/event-listeners.md +0 -123
- package/skills/cometchat-android-v5-calls/references/group-calls.md +0 -205
- package/skills/cometchat-android-v5-calls/references/idle-timeout.md +0 -117
- package/skills/cometchat-android-v5-calls/references/in-call-chat.md +0 -134
- package/skills/cometchat-android-v5-calls/references/join-session.md +0 -120
- package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +0 -222
- package/skills/cometchat-android-v5-calls/references/participant-management.md +0 -110
- package/skills/cometchat-android-v5-calls/references/picture-in-picture.md +0 -106
- package/skills/cometchat-android-v5-calls/references/raise-hand.md +0 -248
- package/skills/cometchat-android-v5-calls/references/recording.md +0 -101
- package/skills/cometchat-android-v5-calls/references/ringing-integration.md +0 -152
- package/skills/cometchat-android-v5-calls/references/screen-sharing.md +0 -78
- package/skills/cometchat-android-v5-calls/references/server-fcm-voip.md +0 -215
- package/skills/cometchat-android-v5-calls/references/session-settings.md +0 -121
- package/skills/cometchat-android-v5-calls/references/setup.md +0 -137
- package/skills/cometchat-android-v5-calls/references/share-invite.md +0 -156
- package/skills/cometchat-android-v5-calls/references/video-controls.md +0 -87
- package/skills/cometchat-android-v5-calls/references/voip-calling.md +0 -526
- package/skills/cometchat-android-v5-components/SKILL.md +0 -431
- package/skills/cometchat-android-v5-core/SKILL.md +0 -486
- package/skills/cometchat-android-v5-customization/SKILL.md +0 -469
- package/skills/cometchat-android-v5-extensions/SKILL.md +0 -127
- package/skills/cometchat-android-v5-features/SKILL.md +0 -131
- package/skills/cometchat-android-v5-placement/SKILL.md +0 -277
- package/skills/cometchat-android-v5-production/SKILL.md +0 -95
- package/skills/cometchat-android-v5-push/SKILL.md +0 -619
- package/skills/cometchat-android-v5-testing/SKILL.md +0 -188
- package/skills/cometchat-android-v5-theming/SKILL.md +0 -167
- package/skills/cometchat-android-v5-troubleshooting/SKILL.md +0 -74
- package/skills/cometchat-android-v6/SKILL.md +0 -108
- package/skills/cometchat-android-v6-calls/references/add-calls-to-existing-chat.md +0 -97
- package/skills/cometchat-android-v6-calls/references/advanced-features.md +0 -87
- package/skills/cometchat-android-v6-calls/references/call-layouts.md +0 -100
- package/skills/cometchat-android-v6-calls/references/call-session.md +0 -163
- package/skills/cometchat-android-v6-calls/references/device-management.md +0 -172
- package/skills/cometchat-android-v6-calls/references/group-calls.md +0 -191
- package/skills/cometchat-android-v6-calls/references/idle-timeout.md +0 -110
- package/skills/cometchat-android-v6-calls/references/in-call-chat.md +0 -141
- package/skills/cometchat-android-v6-calls/references/raise-hand.md +0 -188
- package/skills/cometchat-android-v6-calls/references/ringing-integration.md +0 -176
- package/skills/cometchat-android-v6-calls/references/server-fcm-voip.md +0 -127
- package/skills/cometchat-android-v6-calls/references/share-invite.md +0 -105
- package/skills/cometchat-android-v6-compose-theming/SKILL.md +0 -250
- package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +0 -233
- package/skills/cometchat-angular-calls/SKILL.md +0 -380
- package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +0 -96
- package/skills/cometchat-angular-calls/references/call-layouts.md +0 -123
- package/skills/cometchat-angular-calls/references/call-session.md +0 -167
- package/skills/cometchat-angular-calls/references/custom-ui.md +0 -239
- package/skills/cometchat-angular-calls/references/device-management.md +0 -154
- package/skills/cometchat-angular-calls/references/group-calls.md +0 -433
- package/skills/cometchat-angular-calls/references/idle-timeout.md +0 -161
- package/skills/cometchat-angular-calls/references/in-call-chat.md +0 -148
- package/skills/cometchat-angular-calls/references/lazy-loading-pitfalls.md +0 -205
- package/skills/cometchat-angular-calls/references/migration-v4-to-v5.md +0 -53
- package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +0 -184
- package/skills/cometchat-angular-calls/references/picture-in-picture.md +0 -285
- package/skills/cometchat-angular-calls/references/raise-hand.md +0 -172
- package/skills/cometchat-angular-calls/references/recording-screen-share.md +0 -260
- package/skills/cometchat-angular-calls/references/ringing-integration.md +0 -133
- package/skills/cometchat-angular-calls/references/server-web-push-vapid.md +0 -100
- package/skills/cometchat-angular-calls/references/share-invite.md +0 -122
- package/skills/cometchat-angular-calls/references/virtual-background.md +0 -29
- package/skills/cometchat-angular-components/SKILL.md +0 -235
- package/skills/cometchat-angular-core/SKILL.md +0 -386
- package/skills/cometchat-angular-customization/SKILL.md +0 -616
- package/skills/cometchat-angular-features/SKILL.md +0 -329
- package/skills/cometchat-angular-patterns/SKILL.md +0 -256
- package/skills/cometchat-angular-placement/SKILL.md +0 -314
- package/skills/cometchat-angular-production/SKILL.md +0 -564
- package/skills/cometchat-angular-push/SKILL.md +0 -389
- package/skills/cometchat-angular-testing/SKILL.md +0 -605
- package/skills/cometchat-angular-theming/SKILL.md +0 -290
- package/skills/cometchat-angular-troubleshooting/SKILL.md +0 -364
- package/skills/cometchat-astro-patterns/SKILL.md +0 -708
- package/skills/cometchat-calls/SKILL.md +0 -364
- package/skills/cometchat-calls/references/use-case-broadcast.md +0 -199
- package/skills/cometchat-calls/references/use-case-marketplace.md +0 -157
- package/skills/cometchat-calls/references/use-case-support.md +0 -189
- package/skills/cometchat-calls/references/use-case-team.md +0 -180
- package/skills/cometchat-calls/references/use-case-telehealth.md +0 -153
- package/skills/cometchat-components/SKILL.md +0 -1142
- package/skills/cometchat-core/SKILL.md +0 -1048
- package/skills/cometchat-customization/SKILL.md +0 -580
- package/skills/cometchat-customization/references/component-catalog.md +0 -236
- package/skills/cometchat-features/SKILL.md +0 -861
- package/skills/cometchat-flutter-v5/SKILL.md +0 -173
- package/skills/cometchat-flutter-v5-calls/SKILL.md +0 -455
- package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +0 -193
- package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +0 -103
- package/skills/cometchat-flutter-v5-calls/references/call-session.md +0 -285
- package/skills/cometchat-flutter-v5-calls/references/device-management.md +0 -124
- package/skills/cometchat-flutter-v5-calls/references/group-calls.md +0 -181
- package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +0 -99
- package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +0 -135
- package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +0 -210
- package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +0 -255
- package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +0 -196
- package/skills/cometchat-flutter-v5-calls/references/server-push-bridge.md +0 -101
- package/skills/cometchat-flutter-v5-calls/references/share-invite.md +0 -148
- package/skills/cometchat-flutter-v5-conversations/SKILL.md +0 -118
- package/skills/cometchat-flutter-v5-core/SKILL.md +0 -239
- package/skills/cometchat-flutter-v5-customization/SKILL.md +0 -358
- package/skills/cometchat-flutter-v5-events/SKILL.md +0 -156
- package/skills/cometchat-flutter-v5-messages/SKILL.md +0 -259
- package/skills/cometchat-flutter-v5-production/SKILL.md +0 -216
- package/skills/cometchat-flutter-v5-push/SKILL.md +0 -285
- package/skills/cometchat-flutter-v5-testing/SKILL.md +0 -401
- package/skills/cometchat-flutter-v5-theming/SKILL.md +0 -161
- package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +0 -130
- package/skills/cometchat-flutter-v5-users-groups/SKILL.md +0 -152
- package/skills/cometchat-flutter-v6/SKILL.md +0 -446
- package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +0 -136
- package/skills/cometchat-flutter-v6-calls/references/advanced-features.md +0 -89
- package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +0 -105
- package/skills/cometchat-flutter-v6-calls/references/call-session.md +0 -229
- package/skills/cometchat-flutter-v6-calls/references/device-management.md +0 -105
- package/skills/cometchat-flutter-v6-calls/references/group-calls.md +0 -190
- package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +0 -88
- package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +0 -125
- package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +0 -275
- package/skills/cometchat-flutter-v6-calls/references/ringing-integration.md +0 -171
- package/skills/cometchat-flutter-v6-calls/references/server-push-bridge.md +0 -93
- package/skills/cometchat-flutter-v6-calls/references/share-invite.md +0 -102
- package/skills/cometchat-flutter-v6-conversations/SKILL.md +0 -238
- package/skills/cometchat-flutter-v6-messages/SKILL.md +0 -384
- package/skills/cometchat-flutter-v6-theming/SKILL.md +0 -293
- package/skills/cometchat-flutter-v6-users-groups/SKILL.md +0 -224
- package/skills/cometchat-ios/SKILL.md +0 -325
- package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +0 -181
- package/skills/cometchat-ios-calls/references/audio-modes-and-controls.md +0 -45
- package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +0 -188
- package/skills/cometchat-ios-calls/references/call-layouts.md +0 -76
- package/skills/cometchat-ios-calls/references/call-session.md +0 -218
- package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +0 -357
- package/skills/cometchat-ios-calls/references/custom-ui.md +0 -322
- package/skills/cometchat-ios-calls/references/device-management.md +0 -171
- package/skills/cometchat-ios-calls/references/group-calls.md +0 -359
- package/skills/cometchat-ios-calls/references/idle-timeout.md +0 -184
- package/skills/cometchat-ios-calls/references/in-call-chat.md +0 -179
- package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +0 -196
- package/skills/cometchat-ios-calls/references/picture-in-picture.md +0 -246
- package/skills/cometchat-ios-calls/references/raise-hand.md +0 -26
- package/skills/cometchat-ios-calls/references/recording-screen-share.md +0 -252
- package/skills/cometchat-ios-calls/references/ringing-integration.md +0 -143
- package/skills/cometchat-ios-calls/references/server-apns-pushkit.md +0 -267
- package/skills/cometchat-ios-calls/references/share-invite.md +0 -148
- package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +0 -246
- package/skills/cometchat-ios-calls/references/voip-cert-setup.md +0 -166
- package/skills/cometchat-ios-theming/SKILL.md +0 -667
- package/skills/cometchat-native-bare-patterns/SKILL.md +0 -550
- package/skills/cometchat-native-calls/SKILL.md +0 -671
- package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +0 -203
- package/skills/cometchat-native-calls/references/call-layouts.md +0 -125
- package/skills/cometchat-native-calls/references/call-session.md +0 -182
- package/skills/cometchat-native-calls/references/custom-ui.md +0 -254
- package/skills/cometchat-native-calls/references/device-management.md +0 -158
- package/skills/cometchat-native-calls/references/expo-vs-bare.md +0 -179
- package/skills/cometchat-native-calls/references/group-calls.md +0 -296
- package/skills/cometchat-native-calls/references/idle-timeout.md +0 -128
- package/skills/cometchat-native-calls/references/in-call-chat.md +0 -145
- package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +0 -72
- package/skills/cometchat-native-calls/references/picture-in-picture.md +0 -276
- package/skills/cometchat-native-calls/references/raise-hand.md +0 -205
- package/skills/cometchat-native-calls/references/recording-screen-share.md +0 -169
- package/skills/cometchat-native-calls/references/ringing-integration.md +0 -118
- package/skills/cometchat-native-calls/references/server-push-bridge.md +0 -135
- package/skills/cometchat-native-calls/references/server-push-payloads.md +0 -193
- package/skills/cometchat-native-calls/references/share-invite.md +0 -146
- package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +0 -319
- package/skills/cometchat-native-components/SKILL.md +0 -628
- package/skills/cometchat-native-core/SKILL.md +0 -679
- package/skills/cometchat-native-customization/SKILL.md +0 -716
- package/skills/cometchat-native-expo-patterns/SKILL.md +0 -552
- package/skills/cometchat-native-features/SKILL.md +0 -638
- package/skills/cometchat-native-placement/SKILL.md +0 -509
- package/skills/cometchat-native-production/SKILL.md +0 -700
- package/skills/cometchat-native-push/SKILL.md +0 -594
- package/skills/cometchat-native-testing/SKILL.md +0 -582
- package/skills/cometchat-native-theming/SKILL.md +0 -681
- package/skills/cometchat-native-troubleshooting/SKILL.md +0 -501
- package/skills/cometchat-nextjs-patterns/SKILL.md +0 -899
- package/skills/cometchat-placement/SKILL.md +0 -1360
- package/skills/cometchat-production/SKILL.md +0 -1027
- package/skills/cometchat-react-calls/SKILL.md +0 -752
- package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +0 -146
- package/skills/cometchat-react-calls/references/call-layouts.md +0 -160
- package/skills/cometchat-react-calls/references/call-session.md +0 -235
- package/skills/cometchat-react-calls/references/custom-ui.md +0 -247
- package/skills/cometchat-react-calls/references/device-management.md +0 -210
- package/skills/cometchat-react-calls/references/group-calls.md +0 -257
- package/skills/cometchat-react-calls/references/idle-timeout.md +0 -188
- package/skills/cometchat-react-calls/references/in-call-chat.md +0 -212
- package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +0 -170
- package/skills/cometchat-react-calls/references/picture-in-picture.md +0 -245
- package/skills/cometchat-react-calls/references/raise-hand.md +0 -238
- package/skills/cometchat-react-calls/references/recording-screen-share.md +0 -144
- package/skills/cometchat-react-calls/references/ringing-integration.md +0 -255
- package/skills/cometchat-react-calls/references/server-web-push-vapid.md +0 -241
- package/skills/cometchat-react-calls/references/share-invite.md +0 -175
- package/skills/cometchat-react-calls/references/testing-calls-on-web.md +0 -216
- package/skills/cometchat-react-calls/references/virtual-background.md +0 -32
- package/skills/cometchat-react-calls/references/voip-and-web-push.md +0 -165
- package/skills/cometchat-react-patterns/SKILL.md +0 -628
- package/skills/cometchat-react-push/SKILL.md +0 -634
- package/skills/cometchat-react-router-patterns/SKILL.md +0 -758
- package/skills/cometchat-react-testing/SKILL.md +0 -413
- package/skills/cometchat-theming/SKILL.md +0 -498
- package/skills/cometchat-troubleshooting/SKILL.md +0 -294
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
# Recording + screen-share on iOS
|
|
2
|
-
|
|
3
|
-
Recording is server-side (same as every family). Screen-share on iOS requires a **separate Xcode target** — the iOS Broadcast Upload Extension — because Apple sandboxes screen capture in a separate process. This is the most involved screen-share integration of any family.
|
|
4
|
-
|
|
5
|
-
For SDK semantics + browser-side details, read `cometchat-react-calls/references/recording-screen-share.md` first. This reference is the iOS-specific manual setup and bridge code.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Recording
|
|
10
|
-
|
|
11
|
-
### Server-side: dashboard gate
|
|
12
|
-
|
|
13
|
-
Same as web/RN — enable in **Dashboard → Chat & Messaging → Calls → Recording**. Client flag is no-op without it.
|
|
14
|
-
|
|
15
|
-
### Client-side flag
|
|
16
|
-
|
|
17
|
-
```swift
|
|
18
|
-
import CometChatCallsSDK
|
|
19
|
-
|
|
20
|
-
let settings = CallSettingsBuilder()
|
|
21
|
-
.setIsAudioOnly(false)
|
|
22
|
-
.setStartRecordingOnCallStart(true) // auto-start recording on session start
|
|
23
|
-
.setShowRecordingButton(true) // show the kit's user-toggleable REC button
|
|
24
|
-
.build()
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
There is no `setSessionType` and no `enableRecording` on the iOS v5 builder. Auto-start is `setStartRecordingOnCallStart(_:)`; button visibility is `setShowRecordingButton(_:)`. To toggle recording programmatically mid-call, use the static `CometChatCalls.startRecording()` / `CometChatCalls.stopRecording()`.
|
|
28
|
-
|
|
29
|
-
### Lifecycle events (REC indicator)
|
|
30
|
-
|
|
31
|
-
The iOS Calls SDK v5 has a SINGLE recording callback — `onRecordingToggled(info:)` on `CallsEventsDelegate` (swiftinterface label is `info:`, payload is an `NSDictionary`). There is no `onRecordingStarted`/`onRecordingStopped`/`onRecordingFailed` split, and the delegate is a protocol you conform to (not an object with assignable closure properties).
|
|
32
|
-
|
|
33
|
-
```swift
|
|
34
|
-
extension CustomOngoingCallViewController: CallsEventsDelegate {
|
|
35
|
-
// swiftinterface: onRecordingToggled(info: NSDictionary)
|
|
36
|
-
func onRecordingToggled(info: NSDictionary) {
|
|
37
|
-
DispatchQueue.main.async { [weak self] in
|
|
38
|
-
// info carries the current recording state + initiating user.
|
|
39
|
-
// Drive the REC badge from your own isRecording flag toggled here.
|
|
40
|
-
self?.isRecording.toggle()
|
|
41
|
-
self?.recBadge.isHidden = !(self?.isRecording ?? false)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Wire the delegate via `CallSettingsBuilder.setDelegate(self)` or `CometChatCalls.addCallEventListener(observerId:delegate:)`. There is no separate recording-failure callback — surface failures from your own start/stop call sites if you toggle programmatically.
|
|
48
|
-
|
|
49
|
-
The badge: a small "REC" pill with a blinking red dot. Must be visible to all participants — compliance requirement (CCPA, GDPR Art. 6/7, two-party-consent US states).
|
|
50
|
-
|
|
51
|
-
```swift
|
|
52
|
-
final class RecBadgeView: UIView {
|
|
53
|
-
override init(frame: CGRect) {
|
|
54
|
-
super.init(frame: frame)
|
|
55
|
-
backgroundColor = UIColor(white: 0, alpha: 0.6)
|
|
56
|
-
layer.cornerRadius = 4
|
|
57
|
-
|
|
58
|
-
let dot = UILabel()
|
|
59
|
-
dot.text = "●"
|
|
60
|
-
dot.textColor = .systemRed
|
|
61
|
-
dot.font = .systemFont(ofSize: 12)
|
|
62
|
-
dot.translatesAutoresizingMaskIntoConstraints = false
|
|
63
|
-
|
|
64
|
-
let label = UILabel()
|
|
65
|
-
label.text = "REC"
|
|
66
|
-
label.textColor = .white
|
|
67
|
-
label.font = .systemFont(ofSize: 12, weight: .semibold)
|
|
68
|
-
label.translatesAutoresizingMaskIntoConstraints = false
|
|
69
|
-
|
|
70
|
-
addSubview(dot)
|
|
71
|
-
addSubview(label)
|
|
72
|
-
NSLayoutConstraint.activate([
|
|
73
|
-
dot.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 6),
|
|
74
|
-
dot.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
75
|
-
label.leadingAnchor.constraint(equalTo: dot.trailingAnchor, constant: 4),
|
|
76
|
-
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -6),
|
|
77
|
-
label.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
78
|
-
])
|
|
79
|
-
|
|
80
|
-
// Blink animation
|
|
81
|
-
UIView.animate(withDuration: 0.8, delay: 0, options: [.repeat, .autoreverse], animations: {
|
|
82
|
-
dot.alpha = 0.3
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
required init?(coder: NSCoder) { fatalError() }
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Recording retrieval
|
|
90
|
-
|
|
91
|
-
CometChat hosts the file. Same as web/RN — accessible via dashboard UI or REST API from your server. Never expose recording URLs to the iOS client.
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## Screen sharing — iOS Calls SDK v5.x does NOT support INITIATING
|
|
96
|
-
|
|
97
|
-
**Confirmed against the v5 `CometChatCallsSDK` Swift interface:** the iOS Calls SDK does not support initiating screen sharing. iOS callees can RECEIVE incoming screen shares from web/Android peers — the SDK renders the incoming screen track into the session view automatically — but `CallsEventsDelegate` exposes NO dedicated screen-share callback (no `onScreenShareStarted`/`onScreenShareEnded`, no `onParticipantStartedScreenShare`, no `OngoingCallListener`). iOS cannot SEND.
|
|
98
|
-
|
|
99
|
-
The symbols previously documented in this file (`CometChatCalls.startScreenShareBroadcast`, `processBroadcastVideoFrame`, `processBroadcastAudioFrame`, `endScreenShareBroadcast`) **do not exist** on `CometChatCallsSDK` v5.x. If you've copied these from an earlier draft of this doc, they will not compile against the actual SDK.
|
|
100
|
-
|
|
101
|
-
### What works today
|
|
102
|
-
|
|
103
|
-
| Direction | Status | API |
|
|
104
|
-
|---|---|---|
|
|
105
|
-
| Receive screen share (iOS callee) | ✅ supported (rendered by the SDK into the session view) | no dedicated callback — the screen track renders like any remote video |
|
|
106
|
-
| Initiate screen share (iOS caller → others) | ❌ NOT supported by CometChatCallsSDK v5 | n/a |
|
|
107
|
-
|
|
108
|
-
For applications that need iOS users to share their screen today, the practical options are:
|
|
109
|
-
|
|
110
|
-
1. **Defer screen-share initiation to web/Android peers.** Document that iOS callers are receive-only for screen content.
|
|
111
|
-
2. **Wait for vendor support.** Track the CometChat iOS Calls SDK release notes; this is a known gap.
|
|
112
|
-
3. **Build your own WebRTC bridge** in a Broadcast Upload Extension and attach a manual video track to the underlying peer connection. The CometChat session is a WebRTC peer connection internally, but the SDK does not expose the peer-connection handle, so this requires forking/patching the SDK — not recommended.
|
|
113
|
-
|
|
114
|
-
### Architecture pieces that remain valid (for future SDK support)
|
|
115
|
-
|
|
116
|
-
Steps 1–4 below (Broadcast Upload Extension target, App Groups capability, `RPBroadcastProcessModeSampleBuffer` Info.plist, `RPSystemBroadcastPickerView`) are all valid iOS-level setup that any future SDK adding sender-side screen-share would also require. Kept here for reference. **Skip Steps 5–6 (SampleHandler.swift + App-Group state pre-write) — they reference SDK symbols that do not exist.**
|
|
117
|
-
|
|
118
|
-
iOS sandboxes screen capture inside a separate process. To share (IF the SDK supported it), you would need:
|
|
119
|
-
|
|
120
|
-
1. **A Broadcast Upload Extension target** in your Xcode project
|
|
121
|
-
2. **An App Group capability** shared between the main app and the extension
|
|
122
|
-
3. **An RPSystemBroadcastPickerView** (provided by ReplayKit) that lets the user start sharing
|
|
123
|
-
4. **A WebRTC bridge in the extension** that pipes captured frames into the Calls SDK session
|
|
124
|
-
|
|
125
|
-
Apple doesn't allow main-app screen capture for privacy reasons; this Extension architecture is unavoidable.
|
|
126
|
-
|
|
127
|
-
### Step 1 — Create the Broadcast Upload Extension
|
|
128
|
-
|
|
129
|
-
Xcode → File → New → Target → **Broadcast Upload Extension**.
|
|
130
|
-
|
|
131
|
-
- Product Name: `YourAppBroadcastExtension`
|
|
132
|
-
- Bundle Identifier: `com.yourcompany.YourApp.BroadcastExtension`
|
|
133
|
-
- Embed in Application: YourApp
|
|
134
|
-
|
|
135
|
-
Xcode generates a `SampleHandler.swift` with stub methods.
|
|
136
|
-
|
|
137
|
-
### Step 2 — App Group
|
|
138
|
-
|
|
139
|
-
Both the main target AND the extension target need this capability.
|
|
140
|
-
|
|
141
|
-
Main app target → Signing & Capabilities → + Capability → **App Groups** → enable `group.com.yourcompany.yourapp.broadcast`.
|
|
142
|
-
|
|
143
|
-
Extension target → same capability, same group identifier.
|
|
144
|
-
|
|
145
|
-
### Step 3 — Info.plist for the extension
|
|
146
|
-
|
|
147
|
-
The extension's `Info.plist` (auto-generated by Xcode) must have:
|
|
148
|
-
|
|
149
|
-
```xml
|
|
150
|
-
<key>NSExtension</key>
|
|
151
|
-
<dict>
|
|
152
|
-
<key>NSExtensionPointIdentifier</key>
|
|
153
|
-
<string>com.apple.broadcast-services-upload</string>
|
|
154
|
-
<key>NSExtensionPrincipalClass</key>
|
|
155
|
-
<string>$(PRODUCT_MODULE_NAME).SampleHandler</string>
|
|
156
|
-
<key>RPBroadcastProcessMode</key>
|
|
157
|
-
<string>RPBroadcastProcessModeSampleBuffer</string>
|
|
158
|
-
</dict>
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
`RPBroadcastProcessModeSampleBuffer` is critical — without it, the extension receives audio/video data in a different format that doesn't fit the Calls SDK's bridge.
|
|
162
|
-
|
|
163
|
-
### Step 4 — RPSystemBroadcastPickerView in the call screen
|
|
164
|
-
|
|
165
|
-
```swift
|
|
166
|
-
import ReplayKit
|
|
167
|
-
|
|
168
|
-
class CustomOngoingCallViewController: UIViewController {
|
|
169
|
-
private lazy var broadcastPicker: RPSystemBroadcastPickerView = {
|
|
170
|
-
let picker = RPSystemBroadcastPickerView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
|
|
171
|
-
picker.preferredExtension = "com.yourcompany.YourApp.BroadcastExtension"
|
|
172
|
-
picker.showsMicrophoneButton = false // SDK handles mic
|
|
173
|
-
return picker
|
|
174
|
-
}()
|
|
175
|
-
|
|
176
|
-
override func viewDidLoad() {
|
|
177
|
-
super.viewDidLoad()
|
|
178
|
-
// Find and customize the actual button inside the picker (Apple's API restriction)
|
|
179
|
-
if let button = broadcastPicker.subviews.compactMap({ $0 as? UIButton }).first {
|
|
180
|
-
button.setImage(UIImage(systemName: "rectangle.on.rectangle.angled"), for: .normal)
|
|
181
|
-
}
|
|
182
|
-
view.addSubview(broadcastPicker)
|
|
183
|
-
// Layout broadcastPicker as part of your control panel
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
When the user taps the picker, iOS shows the system broadcast UI listing your extension. They tap it; the extension activates; capture begins.
|
|
189
|
-
|
|
190
|
-
### Steps 5–6 — SDK frame bridge: NOT available
|
|
191
|
-
|
|
192
|
-
iOS cannot INITIATE screen share (receive-only). `CometChatCallsSDK` v5.x exposes no frame-bridge API (`startScreenShareBroadcast`/`processBroadcastVideoFrame`/`processBroadcastAudioFrame`/`endScreenShareBroadcast` are all absent), so there is no `SampleHandler` pipeline to write — defer screen-share initiation to web/Android peers.
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## Viewer — receiving someone else's screen share
|
|
197
|
-
|
|
198
|
-
When a web/Android peer starts sharing, the iOS Calls SDK renders the incoming screen track into the session `view` you passed to `startSession` — exactly like any other remote video tile. There is **no** `onScreenShareStarted`/`onScreenShareEnded` callback on `CallsEventsDelegate` to hook (those symbols do not exist on iOS v5).
|
|
199
|
-
|
|
200
|
-
If you need to react to participant changes around a screen share (e.g. relayout), use the typed participant callbacks — `onUserJoined(rtcUser:)`, `onUserLeft(rtcUser:)`, `onUserListChanged(rtcUsers:)` (swiftinterface:35,38,41 — `RTCUser` objects). For default-UI integrations no code is required: the SDK handles the screen-track layout for you.
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
## Common failure modes
|
|
205
|
-
|
|
206
|
-
| Symptom | Cause | Fix |
|
|
207
|
-
|---|---|---|
|
|
208
|
-
| Picker doesn't show your extension | Bundle ID mismatch in `preferredExtension` | Match the extension target's Bundle ID exactly |
|
|
209
|
-
| "No active session" finishBroadcastWithError | App Group identifier mismatch | Both targets must use the same `group.*` identifier |
|
|
210
|
-
| Extension launches but no video on remote side | Missing `RPBroadcastProcessModeSampleBuffer` in extension Info.plist | Add it |
|
|
211
|
-
| Recording flag set but no recording in dashboard | Plan doesn't include recording, or dashboard toggle off | Enable in dashboard |
|
|
212
|
-
| REC badge missing | Custom UI — must render manually | Subscribe to `onRecordingToggled(info:)` and render badge |
|
|
213
|
-
| Screen share doesn't end on call hangup | `broadcastFinished` not triggering | Manually call `RPBroadcastController.shared.finishBroadcast(...)` from main app on hangup |
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## Anti-patterns
|
|
218
|
-
|
|
219
|
-
1. **Embedding screen-share logic in the main app target.** iOS doesn't allow it — must be a separate extension.
|
|
220
|
-
2. **App Groups with mismatched identifiers.** Extension can't see main app state; broadcast finishes immediately.
|
|
221
|
-
3. **`RPSystemBroadcastPickerView` with hidden button via removeFromSuperview.** Apple may reject the build for App Store. Customize via subview iteration only.
|
|
222
|
-
4. **No REC indicator.** Compliance violation in two-party-consent jurisdictions.
|
|
223
|
-
5. **Trying to access recording files from the device.** They're not local — server-only access via REST API.
|
|
224
|
-
6. **Implementing the SampleHandler.broadcastStarted/processSampleBuffer/broadcastFinished pipeline against CometChatCallsSDK v5.x.** Per the audit above, the SDK does not expose `startScreenShareBroadcast`, `processBroadcastVideoFrame`, `processBroadcastAudioFrame`, or `endScreenShareBroadcast`. Steps 5–6 of this doc are kept for reference but will not compile against the actual SDK today.
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## Verification checklist
|
|
229
|
-
|
|
230
|
-
**Recording:**
|
|
231
|
-
- [ ] Dashboard plan includes recording feature
|
|
232
|
-
- [ ] `setStartRecordingOnCallStart(true)` and/or `setShowRecordingButton(true)` on `CallSettingsBuilder` (no `enableRecording`)
|
|
233
|
-
- [ ] `onRecordingToggled(info:)` listener wired (single callback — no Started/Stopped/Failed split)
|
|
234
|
-
- [ ] REC badge visible to all participants when active
|
|
235
|
-
|
|
236
|
-
**Screen share — receiver side only (iOS Calls SDK v5 cannot INITIATE):**
|
|
237
|
-
- [ ] No code required for default UI — the SDK renders the incoming screen track into the session view
|
|
238
|
-
- [ ] No `onScreenShareStarted`/`onScreenShareEnded`/`onParticipantStartedScreenShare`/`OngoingCallListener` referenced (none exist on iOS v5)
|
|
239
|
-
- [ ] Sender-side screen-share architecture (Broadcast Extension, SampleHandler) NOT implemented against current SDK — the symbols don't exist
|
|
240
|
-
|
|
241
|
-
**Real-device smoke (receive-only — iOS cannot INITIATE screen share):**
|
|
242
|
-
- [ ] When a participant on another platform (web/Android) shares their screen, it renders in the iOS call view
|
|
243
|
-
- [ ] No sender-side broadcast picker/UI is shown on iOS (there is no initiation API in the v5 SDK)
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Pointers
|
|
248
|
-
|
|
249
|
-
- `cometchat-react-calls/references/recording-screen-share.md` — sister reference (SDK semantics, browser semantics, server-side recording retrieval)
|
|
250
|
-
- `cometchat-native-calls/references/recording-screen-share.md` — RN reference (same Broadcast Upload Extension pattern; this iOS version is more detailed)
|
|
251
|
-
- `references/group-calls.md` — recording group calls (server composition handles layout)
|
|
252
|
-
- `cometchat-ios-calls` SKILL.md — base hard rules
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
# Ringing — call signaling with custom UI (iOS)
|
|
2
|
-
|
|
3
|
-
iOS-specific deltas: PushKit + CallKit are mandatory for backgrounded ring delivery; foreground ringing uses the Chat SDK's `CometChatCallDelegate` (NOT the Calls SDK's `CallsEventsDelegate`); AVAudioSession routing.
|
|
4
|
-
|
|
5
|
-
**Read first:** `cometchat-react-calls/references/ringing-integration.md` — full architecture, hard rules.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## SDK API
|
|
10
|
-
|
|
11
|
-
```swift
|
|
12
|
-
import CometChatSDK
|
|
13
|
-
import CometChatCallsSDK
|
|
14
|
-
|
|
15
|
-
let call = Call(receiverId: receiverUid, callType: .video, receiverType: .user)
|
|
16
|
-
CometChat.initiateCall(call: call, onSuccess: { outgoing in
|
|
17
|
-
self.showOutgoingCallScreen(outgoing)
|
|
18
|
-
}, onError: { err in
|
|
19
|
-
print("Initiate failed:", err)
|
|
20
|
-
})
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Foreground listener
|
|
26
|
-
|
|
27
|
-
Ringing/signaling events live on the Chat SDK's `CometChatCallDelegate` (its callbacks take TWO params: the call and an error). Implement it and register at app start with the positional `CometChat.addCallListener(_:_:)`:
|
|
28
|
-
|
|
29
|
-
```swift
|
|
30
|
-
class AppCallListener: NSObject, CometChatCallDelegate {
|
|
31
|
-
func onIncomingCallReceived(incomingCall: Call?, error: CometChatException?) {
|
|
32
|
-
guard let call = incomingCall else { return }
|
|
33
|
-
DispatchQueue.main.async { showIncomingCallScreen(call) }
|
|
34
|
-
}
|
|
35
|
-
func onOutgoingCallAccepted(acceptedCall: Call?, error: CometChatException?) {
|
|
36
|
-
guard let call = acceptedCall else { return }
|
|
37
|
-
DispatchQueue.main.async { startCallSession(sessionId: call.sessionId) }
|
|
38
|
-
}
|
|
39
|
-
func onIncomingCallCancelled(canceledCall: Call?, error: CometChatException?) {
|
|
40
|
-
DispatchQueue.main.async { dismissIncomingCallScreen() }
|
|
41
|
-
}
|
|
42
|
-
func onOutgoingCallRejected(rejectedCall: Call?, error: CometChatException?) {
|
|
43
|
-
DispatchQueue.main.async { dismissOutgoingCallScreen() }
|
|
44
|
-
}
|
|
45
|
-
func onCallEndedMessageReceived(endedCall: Call?, error: CometChatException?) {
|
|
46
|
-
DispatchQueue.main.async { teardownCallUI() }
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
CometChat.addCallListener("app", AppCallListener()) // positional labels
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Add this in `AppDelegate.didFinishLaunchingWithOptions` AFTER `CometChat.init` succeeds.
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Backgrounded ring — PushKit + CallKit (mandatory)
|
|
58
|
-
|
|
59
|
-
iOS requires PushKit + CallKit for ring delivery when the app is backgrounded or killed. The foreground listener does NOT fire in those states. See `cometchat-ios-calls/references/server-apns-pushkit.md` for the server template.
|
|
60
|
-
|
|
61
|
-
PushKit delegate flow:
|
|
62
|
-
1. `pushRegistry(_:didReceiveIncomingPushWith:for:completion:)` fires
|
|
63
|
-
2. Within ~5s, call `CXProvider.reportNewIncomingCall(with:update:)` — Apple revokes VoIP entitlement after 3 missed reports
|
|
64
|
-
3. CallKit shows the system incoming-call UI
|
|
65
|
-
4. User taps Accept → `provider(_:perform:CXAnswerCallAction)` fires → start CometChat session
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## SwiftUI incoming-call screen
|
|
70
|
-
|
|
71
|
-
```swift
|
|
72
|
-
struct IncomingCallScreen: View {
|
|
73
|
-
let call: Call
|
|
74
|
-
let onAccept: () -> Void
|
|
75
|
-
let onReject: () -> Void
|
|
76
|
-
|
|
77
|
-
var body: some View {
|
|
78
|
-
ZStack {
|
|
79
|
-
Color.black.opacity(0.85).ignoresSafeArea()
|
|
80
|
-
VStack(spacing: 24) {
|
|
81
|
-
AsyncImage(url: URL(string: call.callInitiator?.avatar ?? ""))
|
|
82
|
-
.frame(width: 120, height: 120)
|
|
83
|
-
.clipShape(Circle())
|
|
84
|
-
Text(call.callInitiator?.name ?? "Unknown")
|
|
85
|
-
.font(.title)
|
|
86
|
-
Text("Incoming \(call.type.rawValue) call")
|
|
87
|
-
.foregroundStyle(.secondary)
|
|
88
|
-
HStack(spacing: 32) {
|
|
89
|
-
Button(action: onReject) {
|
|
90
|
-
Image(systemName: "phone.down.fill")
|
|
91
|
-
.padding(20)
|
|
92
|
-
.background(Color.red, in: Circle())
|
|
93
|
-
.foregroundStyle(.white)
|
|
94
|
-
}
|
|
95
|
-
.accessibilityLabel("Decline call")
|
|
96
|
-
Button(action: onAccept) {
|
|
97
|
-
Image(systemName: "phone.fill")
|
|
98
|
-
.padding(20)
|
|
99
|
-
.background(Color.green, in: Circle())
|
|
100
|
-
.foregroundStyle(.white)
|
|
101
|
-
}
|
|
102
|
-
.accessibilityLabel("Accept call")
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
.foregroundStyle(.white)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
For backgrounded ring, CallKit's UI takes over — your SwiftUI screen only fires for foreground rings.
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## Anti-patterns
|
|
116
|
-
|
|
117
|
-
Web sister rules apply, plus iOS-specific:
|
|
118
|
-
|
|
119
|
-
1. **Listener registered before `CometChat.init`.** Crash. Always register after init's success block.
|
|
120
|
-
2. **Skipping PushKit + CallKit.** Backgrounded calls don't ring. Apple may also revoke VoIP entitlement if you ship with `pushType: .voIP` registered but no CallKit reporting.
|
|
121
|
-
3. **Updating UI from listener callback's thread.** SDK fires off main; always `DispatchQueue.main.async` for UI updates.
|
|
122
|
-
4. **Playing AVAudioPlayer ringtone during CallKit ring.** CallKit plays system ringtone; double-up is jarring.
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Verification checklist
|
|
127
|
-
|
|
128
|
-
- [ ] Foreground listener registered after `CometChat.init` resolves
|
|
129
|
-
- [ ] PushKit registry initialized + .p8 key configured
|
|
130
|
-
- [ ] CallKit `CXProvider.reportNewIncomingCall` fires within 5s of push
|
|
131
|
-
- [ ] All listener callbacks dispatch to main queue
|
|
132
|
-
- [ ] `removeCallListener` in app teardown
|
|
133
|
-
- [ ] Real-device smoke: foreground ring, backgrounded ring (push), killed-app ring (push) all surface UI
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
## Pointers
|
|
138
|
-
|
|
139
|
-
- `cometchat-react-calls/references/ringing-integration.md` — canonical
|
|
140
|
-
- `cometchat-ios-calls/SKILL.md` — seven hard rules
|
|
141
|
-
- `cometchat-ios-calls/references/server-apns-pushkit.md` — PushKit server-side
|
|
142
|
-
- `cometchat-ios-calls/references/callkit-and-pushkit.md` — CallKit details
|
|
143
|
-
- Canonical docs: https://www.cometchat.com/docs/calls/ios/ringing
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
# Server-side APNs PushKit for iOS VoIP
|
|
2
|
-
|
|
3
|
-
When a CometChat call event fires (`onIncomingCallReceived` → CometChat backend webhook), your server sends a **VoIP push** to the recipient's iPhone via Apple's PushKit. Your app's PushKit delegate then triggers CallKit's incoming-call UI. Without VoIP push, the recipient's phone won't ring when the app is backgrounded.
|
|
4
|
-
|
|
5
|
-
**Canonical docs:** https://developer.apple.com/documentation/pushkit, https://developer.apple.com/documentation/usernotifications/sending-notification-requests-to-apns
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Hard rules
|
|
10
|
-
|
|
11
|
-
1. **VoIP push is .p8 only** (token-auth). Old .pem cert auth was deprecated in 2020 and is no longer supported for VoIP.
|
|
12
|
-
2. **Use a separate APNs topic.** VoIP topic = `<bundle-id>.voip`. NOT the same as your regular APNs topic.
|
|
13
|
-
3. **`apns-push-type: voip`** header is mandatory. Apple drops the push silently if missing.
|
|
14
|
-
4. **`apns-priority: 10`** (immediate). VoIP must be high-priority.
|
|
15
|
-
5. **Must report to CallKit within ~5 seconds.** PushKit gives you a tiny window — if you don't call `CXProvider.reportNewIncomingCall(with:update:)` fast, iOS terminates your app and counts a strike. Three strikes in 24h and Apple revokes your VoIP entitlement.
|
|
16
|
-
6. **VoIP push payload size ≤ 4KB.** Include the minimum (`sessionId`, `callerName`, `callType`); fetch the rest after CallKit is reported.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## .p8 setup
|
|
21
|
-
|
|
22
|
-
1. Apple Developer Portal → Certificates, Identifiers & Profiles → **Keys** → "+"
|
|
23
|
-
2. Enable **Apple Push Notifications service (APNs)** → Continue → Register
|
|
24
|
-
3. Download the `.p8` file. **Save it — Apple shows it once.**
|
|
25
|
-
4. Note the **Key ID** (10-char alphanumeric).
|
|
26
|
-
5. Note your **Team ID** (top-right of Apple Developer dashboard).
|
|
27
|
-
|
|
28
|
-
Store securely on your server (Secret Manager / Vault — never in source).
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Node.js template
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
// npm install @parse/node-apn
|
|
36
|
-
import apn from "@parse/node-apn";
|
|
37
|
-
import fs from "fs";
|
|
38
|
-
|
|
39
|
-
const provider = new apn.Provider({
|
|
40
|
-
token: {
|
|
41
|
-
key: fs.readFileSync("/secrets/AuthKey_ABC123.p8"),
|
|
42
|
-
keyId: process.env.APNS_KEY_ID, // e.g. "ABC123XYZ"
|
|
43
|
-
teamId: process.env.APNS_TEAM_ID, // e.g. "TEAM12345"
|
|
44
|
-
},
|
|
45
|
-
production: process.env.NODE_ENV === "production",
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Called from your CometChat call-event webhook handler.
|
|
50
|
-
* Looks up the recipient's PushKit token (you stored it when their app
|
|
51
|
-
* registered) and fires the VoIP push.
|
|
52
|
-
*/
|
|
53
|
-
export async function sendVoipPush(opts) {
|
|
54
|
-
const { recipientUid, sessionId, callerName, callerUid, callType } = opts;
|
|
55
|
-
|
|
56
|
-
const pushKitToken = await db.getVoipToken(recipientUid);
|
|
57
|
-
if (!pushKitToken) return; // user not on iOS or token expired
|
|
58
|
-
|
|
59
|
-
const note = new apn.Notification();
|
|
60
|
-
note.topic = `${process.env.APNS_BUNDLE_ID}.voip`; // <bundle>.voip — required
|
|
61
|
-
note.pushType = "voip"; // apns-push-type: voip
|
|
62
|
-
note.priority = 10; // apns-priority: 10 — immediate
|
|
63
|
-
note.expiry = Math.floor(Date.now() / 1000) + 30; // 30s — VoIP push must fire fast
|
|
64
|
-
|
|
65
|
-
// Custom payload — keep ≤4KB, include only what CallKit needs
|
|
66
|
-
note.rawPayload = {
|
|
67
|
-
aps: { "content-available": 1 },
|
|
68
|
-
sessionId,
|
|
69
|
-
callerName,
|
|
70
|
-
callerUid,
|
|
71
|
-
callType, // "audio" | "video"
|
|
72
|
-
timestamp: Date.now(),
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const result = await provider.send(note, pushKitToken);
|
|
76
|
-
if (result.failed.length > 0) {
|
|
77
|
-
const fail = result.failed[0];
|
|
78
|
-
if (fail.status === "410" || fail.response?.reason === "Unregistered") {
|
|
79
|
-
// Token is dead — remove from DB so we don't keep retrying
|
|
80
|
-
await db.removeVoipToken(recipientUid, pushKitToken);
|
|
81
|
-
}
|
|
82
|
-
console.error("APNs VoIP push failed", fail);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## Python template
|
|
91
|
-
|
|
92
|
-
```python
|
|
93
|
-
# pip install httpx pyjwt cryptography
|
|
94
|
-
import time, json, jwt, httpx
|
|
95
|
-
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
|
96
|
-
|
|
97
|
-
PRIVATE_KEY = load_pem_private_key(
|
|
98
|
-
open("/secrets/AuthKey_ABC123.p8", "rb").read(), password=None
|
|
99
|
-
)
|
|
100
|
-
KEY_ID = os.environ["APNS_KEY_ID"]
|
|
101
|
-
TEAM_ID = os.environ["APNS_TEAM_ID"]
|
|
102
|
-
BUNDLE_ID = os.environ["APNS_BUNDLE_ID"]
|
|
103
|
-
APNS_HOST = "https://api.push.apple.com" if os.environ.get("ENV") == "production" else "https://api.sandbox.push.apple.com"
|
|
104
|
-
|
|
105
|
-
# Provider tokens are valid for 1h; cache + refresh
|
|
106
|
-
_token_cache = {"token": None, "issued_at": 0}
|
|
107
|
-
|
|
108
|
-
def provider_token() -> str:
|
|
109
|
-
if time.time() - _token_cache["issued_at"] < 3000: # refresh every 50min
|
|
110
|
-
return _token_cache["token"]
|
|
111
|
-
token = jwt.encode(
|
|
112
|
-
{"iss": TEAM_ID, "iat": int(time.time())},
|
|
113
|
-
PRIVATE_KEY,
|
|
114
|
-
algorithm="ES256",
|
|
115
|
-
headers={"kid": KEY_ID},
|
|
116
|
-
)
|
|
117
|
-
_token_cache.update(token=token, issued_at=time.time())
|
|
118
|
-
return token
|
|
119
|
-
|
|
120
|
-
async def send_voip_push(pushkit_token: str, payload: dict):
|
|
121
|
-
headers = {
|
|
122
|
-
"authorization": f"bearer {provider_token()}",
|
|
123
|
-
"apns-topic": f"{BUNDLE_ID}.voip",
|
|
124
|
-
"apns-push-type": "voip",
|
|
125
|
-
"apns-priority": "10",
|
|
126
|
-
"apns-expiration": str(int(time.time()) + 30),
|
|
127
|
-
}
|
|
128
|
-
async with httpx.AsyncClient(http2=True) as client:
|
|
129
|
-
r = await client.post(
|
|
130
|
-
f"{APNS_HOST}/3/device/{pushkit_token}",
|
|
131
|
-
headers=headers,
|
|
132
|
-
content=json.dumps(payload),
|
|
133
|
-
)
|
|
134
|
-
if r.status_code == 410:
|
|
135
|
-
# Token unregistered — remove from DB
|
|
136
|
-
return "unregistered"
|
|
137
|
-
if r.status_code != 200:
|
|
138
|
-
raise RuntimeError(f"APNs error {r.status_code}: {r.text}")
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## Webhook payload from CometChat
|
|
144
|
-
|
|
145
|
-
In the CometChat dashboard, configure a **Webhook** → "Call events" → POST to `https://yourserver.com/webhooks/call`. The body shape:
|
|
146
|
-
|
|
147
|
-
```json
|
|
148
|
-
{
|
|
149
|
-
"trigger": "call_initiated",
|
|
150
|
-
"data": {
|
|
151
|
-
"id": "session-uuid",
|
|
152
|
-
"sessionId": "session-uuid",
|
|
153
|
-
"type": "video",
|
|
154
|
-
"initiator": { "uid": "alice", "name": "Alice" },
|
|
155
|
-
"receiver": { "uid": "bob", "name": "Bob" },
|
|
156
|
-
"receiverType": "user"
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Your handler:
|
|
162
|
-
|
|
163
|
-
```js
|
|
164
|
-
app.post("/webhooks/call", async (req, res) => {
|
|
165
|
-
// 1. Verify webhook signature (X-CometChat-Signature header)
|
|
166
|
-
const sig = req.headers["x-cometchat-signature"];
|
|
167
|
-
const expected = crypto.createHmac("sha256", process.env.COMETCHAT_WEBHOOK_SECRET)
|
|
168
|
-
.update(req.rawBody).digest("hex");
|
|
169
|
-
if (sig !== expected) return res.status(401).end();
|
|
170
|
-
|
|
171
|
-
// 2. Only fire VoIP push on call_initiated (not on call-ended)
|
|
172
|
-
if (req.body.trigger !== "call_initiated") return res.status(200).end();
|
|
173
|
-
|
|
174
|
-
// 3. Forward to platform-specific push
|
|
175
|
-
const { sessionId, type, initiator, receiver } = req.body.data;
|
|
176
|
-
await sendVoipPush({
|
|
177
|
-
recipientUid: receiver.uid,
|
|
178
|
-
sessionId,
|
|
179
|
-
callerName: initiator.name,
|
|
180
|
-
callerUid: initiator.uid,
|
|
181
|
-
callType: type,
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
res.status(200).end();
|
|
185
|
-
});
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## Token registration (the round-trip)
|
|
191
|
-
|
|
192
|
-
When your iOS app launches, register PushKit and POST the token to your server:
|
|
193
|
-
|
|
194
|
-
```swift
|
|
195
|
-
// AppDelegate or dedicated VoIP manager
|
|
196
|
-
import PushKit
|
|
197
|
-
|
|
198
|
-
class VoipPushHandler: NSObject, PKPushRegistryDelegate {
|
|
199
|
-
let registry = PKPushRegistry(queue: .main)
|
|
200
|
-
|
|
201
|
-
override init() {
|
|
202
|
-
super.init()
|
|
203
|
-
registry.delegate = self
|
|
204
|
-
registry.desiredPushTypes = [.voIP]
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
|
|
208
|
-
guard type == .voIP else { return }
|
|
209
|
-
let token = credentials.token.map { String(format: "%02x", $0) }.joined()
|
|
210
|
-
Task { try? await api.registerVoipToken(uid: currentUserUid, token: token) }
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
|
|
214
|
-
Task { try? await api.removeVoipToken(uid: currentUserUid) }
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
|
|
218
|
-
// Report to CallKit IMMEDIATELY — Apple gives you ~5s
|
|
219
|
-
let dict = payload.dictionaryPayload
|
|
220
|
-
let update = CXCallUpdate()
|
|
221
|
-
update.remoteHandle = CXHandle(type: .generic, value: dict["callerUid"] as? String ?? "Unknown")
|
|
222
|
-
update.localizedCallerName = dict["callerName"] as? String ?? "Unknown"
|
|
223
|
-
update.hasVideo = (dict["callType"] as? String) == "video"
|
|
224
|
-
|
|
225
|
-
let uuid = UUID()
|
|
226
|
-
callProvider.reportNewIncomingCall(with: uuid, update: update) { error in
|
|
227
|
-
if let error = error { print("CallKit reportNewIncomingCall failed:", error) }
|
|
228
|
-
completion()
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
## Anti-patterns
|
|
237
|
-
|
|
238
|
-
1. **Using regular APNs token, not VoIP.** Push arrives but CallKit doesn't trigger — the app got woken up, not put into "incoming call" state.
|
|
239
|
-
2. **Forgetting `apns-push-type: voip`.** Apple drops the push, no error to your server.
|
|
240
|
-
3. **Not calling `reportNewIncomingCall` from `didReceiveIncomingPushWith`.** Three strikes → entitlement revoked.
|
|
241
|
-
4. **Sending too much in the VoIP payload.** Apple throttles or rejects >4KB. Send minimum, fetch the rest after CallKit fires.
|
|
242
|
-
5. **Webhook handler doing slow work synchronously.** Push to a queue (Redis, SQS, BullMQ); return 200 immediately. Slow webhook = CometChat retries = duplicate calls.
|
|
243
|
-
6. **Same token for chat push and VoIP push.** Different tokens — you must register both via `UNUserNotificationCenter` (regular) AND `PKPushRegistry` (VoIP).
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Verification checklist
|
|
248
|
-
|
|
249
|
-
- [ ] `.p8` key stored in secret manager
|
|
250
|
-
- [ ] `apns-topic = <bundle-id>.voip`
|
|
251
|
-
- [ ] `apns-push-type: voip` + `apns-priority: 10`
|
|
252
|
-
- [ ] `reportNewIncomingCall` fires from PushKit delegate inside ~5s
|
|
253
|
-
- [ ] 410 responses purge dead tokens from DB
|
|
254
|
-
- [ ] Webhook signature verified before processing
|
|
255
|
-
- [ ] Webhook returns 200 within 1s (push enqueued, not awaited)
|
|
256
|
-
- [ ] Real-device smoke: backgrounded recipient → caller dials → recipient phone rings on lock screen
|
|
257
|
-
|
|
258
|
-
---
|
|
259
|
-
|
|
260
|
-
## Pointers
|
|
261
|
-
|
|
262
|
-
- `cometchat-ios-calls/SKILL.md` — the seven hard rules (init order, IncomingCall mounting, hangup teardown)
|
|
263
|
-
- `cometchat-ios-push/SKILL.md` — chat push (sister, different APNs topic)
|
|
264
|
-
- `cometchat-android-v5-calls/references/server-fcm-voip.md` — Android sibling (FCM HTTP v1)
|
|
265
|
-
- `cometchat-react-calls/references/server-web-push-vapid.md` — Web sibling
|
|
266
|
-
- Apple PushKit: https://developer.apple.com/documentation/pushkit
|
|
267
|
-
- APNs HTTP/2 reference: https://developer.apple.com/documentation/usernotifications/sending-notification-requests-to-apns
|