@tencent-rtc/mcp 1.4.6 → 1.6.0-beta.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/cursor-setting.png +0 -0
- package/knowledge/bm25-cache.js +74 -0
- package/knowledge/bm25-cache.js.map +1 -0
- package/knowledge/bm25.js +148 -0
- package/knowledge/bm25.js.map +1 -0
- package/knowledge/build-index.js +70 -0
- package/knowledge/build-index.js.map +1 -0
- package/knowledge/chunker.js +168 -0
- package/knowledge/chunker.js.map +1 -0
- package/knowledge/content-loader.js +40 -0
- package/knowledge/content-loader.js.map +1 -0
- package/knowledge/doc-url-resolver.js +143 -0
- package/knowledge/doc-url-resolver.js.map +1 -0
- package/knowledge/extractors.js +26 -0
- package/knowledge/extractors.js.map +1 -0
- package/knowledge/path-meta.js +185 -0
- package/knowledge/path-meta.js.map +1 -0
- package/knowledge/search/exact-lookup.js +498 -0
- package/knowledge/search/exact-lookup.js.map +1 -0
- package/knowledge/search/filter-pool.js +105 -0
- package/knowledge/search/filter-pool.js.map +1 -0
- package/knowledge/search/product-scope-intent.js +41 -0
- package/knowledge/search/product-scope-intent.js.map +1 -0
- package/knowledge/search/requires-framework.js +82 -0
- package/knowledge/search/requires-framework.js.map +1 -0
- package/knowledge/search/search-knowledge.js +230 -0
- package/knowledge/search/search-knowledge.js.map +1 -0
- package/mcp-server-prompt.png +0 -0
- package/package.json +1 -1
- package/resource/_schema/feature-aliases.yaml +10 -0
- package/resource/_schema/goal-tags.yaml +72 -0
- package/resource/_schema/products.yaml +19 -0
- package/resource/_schema/trtc-intents.yaml +27 -0
- package/resource/_schema/types.yaml +43 -0
- package/resource/index/component-slugs.json +1 -0
- package/resource/index/doc-source-urls.json +1 -0
- package/resource/index/manifest.json +1 -0
- package/resource/{doc → integration}/callkit/preset/android/integration.md +34 -28
- package/resource/integration/callkit/preset/flutter/integration.md +346 -0
- package/resource/integration/callkit/preset/ios/integration.md +408 -0
- package/resource/integration/callkit/preset/react/integration.md +362 -0
- package/resource/integration/callkit/preset/vue/integration.md +356 -0
- package/resource/integration/chat/preset/android/integration.md +500 -0
- package/resource/integration/chat/preset/flutter/integration.md +370 -0
- package/resource/integration/chat/preset/ios/integration.md +566 -0
- package/resource/integration/chat/preset/react/integration.md +490 -0
- package/resource/integration/chat/preset/vue/integration.md +504 -0
- package/resource/{doc → integration}/livekit/preset/live/vue/live-list-integration.md +26 -22
- package/resource/{doc → integration}/livekit/preset/live/vue/live-player-desk-integration.md +22 -18
- package/resource/integration/livekit/preset/live/vue/live-player-h5-integration.md +309 -0
- package/resource/{doc → integration}/livekit/preset/live/vue/live-pusher-integration.md +47 -39
- package/resource/integration/roomkit/preset/vue/integration.md +562 -0
- package/resource/knowledge/callkit/core-sdk/android/answer-call.md +828 -0
- package/resource/knowledge/callkit/core-sdk/android/make-call.md +897 -0
- package/resource/knowledge/callkit/core-sdk/android/offline-push.md +363 -0
- package/resource/knowledge/callkit/core-sdk/flutter/answer-call.md +1111 -0
- package/resource/knowledge/callkit/core-sdk/flutter/make-call.md +1132 -0
- package/resource/{doc → knowledge}/callkit/core-sdk/flutter/offline-push.md +174 -151
- package/resource/knowledge/callkit/core-sdk/ios/answer-call.md +1084 -0
- package/resource/knowledge/callkit/core-sdk/ios/make-call.md +1252 -0
- package/resource/knowledge/callkit/core-sdk/ios/offline-push.md +534 -0
- package/resource/knowledge/callkit/core-sdk/uni-app/answer-call.md +953 -0
- package/resource/knowledge/callkit/core-sdk/uni-app/make-call.md +1061 -0
- package/resource/knowledge/callkit/faq/android.md +92 -0
- package/resource/{doc/callkit/faq/android-faq.md → knowledge/callkit/faq/common.md} +11 -12
- package/resource/knowledge/callkit/faq/error-code.md +67 -0
- package/resource/knowledge/callkit/faq/flutter.md +52 -0
- package/resource/knowledge/callkit/faq/ios.md +104 -0
- package/resource/knowledge/callkit/faq/web.md +74 -0
- package/resource/knowledge/callkit/preset/android/api.md +412 -0
- package/resource/knowledge/callkit/preset/flutter/api.md +22 -0
- package/resource/knowledge/callkit/preset/ios/api.md +234 -0
- package/resource/knowledge/callkit/preset/web/api.md +83 -0
- package/resource/knowledge/chat/preset/android/features/chat-setting.md +74 -0
- package/resource/knowledge/chat/preset/android/features/contact-list.md +43 -0
- package/resource/knowledge/chat/preset/android/features/conversation-list.md +117 -0
- package/resource/knowledge/chat/preset/android/features/language.md +136 -0
- package/resource/knowledge/chat/preset/android/features/message-input.md +57 -0
- package/resource/knowledge/chat/preset/android/features/message-list.md +142 -0
- package/resource/knowledge/chat/preset/android/features/search.md +64 -0
- package/resource/knowledge/chat/preset/android/features/theme.md +222 -0
- package/resource/knowledge/chat/preset/android-view/integration.md +300 -0
- package/resource/knowledge/chat/preset/flutter/features/chat-setting.md +64 -0
- package/resource/knowledge/chat/preset/flutter/features/contact-list.md +40 -0
- package/resource/knowledge/chat/preset/flutter/features/conversation-list.md +129 -0
- package/resource/knowledge/chat/preset/flutter/features/language.md +104 -0
- package/resource/knowledge/chat/preset/flutter/features/message-input.md +54 -0
- package/resource/knowledge/chat/preset/flutter/features/message-list.md +158 -0
- package/resource/knowledge/chat/preset/flutter/features/search.md +59 -0
- package/resource/knowledge/chat/preset/flutter/features/theme.md +261 -0
- package/resource/knowledge/chat/preset/ios/features/chat-setting.md +94 -0
- package/resource/knowledge/chat/preset/ios/features/contact-list.md +119 -0
- package/resource/knowledge/chat/preset/ios/features/conversation-list.md +134 -0
- package/resource/knowledge/chat/preset/ios/features/language.md +125 -0
- package/resource/knowledge/chat/preset/ios/features/message-input.md +69 -0
- package/resource/knowledge/chat/preset/ios/features/message-list.md +162 -0
- package/resource/knowledge/chat/preset/ios/features/search.md +93 -0
- package/resource/knowledge/chat/preset/ios/features/theme.md +270 -0
- package/resource/{doc/chatkit/ios → knowledge/chat/preset/ios-uikit}/integration.md +160 -158
- package/resource/knowledge/chat/preset/react/features/chat-setting.md +101 -0
- package/resource/{doc/chatkit/react/components → knowledge/chat/preset/react/features}/contact-list.md +43 -41
- package/resource/knowledge/chat/preset/react/features/conversation-actions.md +215 -0
- package/resource/knowledge/chat/preset/react/features/conversation-list.md +339 -0
- package/resource/knowledge/chat/preset/react/features/conversation-preview.md +101 -0
- package/resource/knowledge/chat/preset/react/features/conversation-search.md +61 -0
- package/resource/{doc/chatkit/react/components → knowledge/chat/preset/react/features}/message-input.md +117 -156
- package/resource/knowledge/chat/preset/react/features/message-list.md +297 -0
- package/resource/{doc/chatkit/react/components → knowledge/chat/preset/react/features}/search.md +65 -59
- package/resource/knowledge/chat/preset/react/features/theme.md +93 -0
- package/resource/knowledge/chat/preset/vue/features/chat-header.md +331 -0
- package/resource/knowledge/chat/preset/vue/features/chat-setting.md +79 -0
- package/resource/knowledge/chat/preset/vue/features/contact-list.md +277 -0
- package/resource/knowledge/chat/preset/vue/features/conversation-actions.md +234 -0
- package/resource/knowledge/chat/preset/vue/features/conversation-list.md +331 -0
- package/resource/knowledge/chat/preset/vue/features/conversation-preview.md +216 -0
- package/resource/{doc/chatkit/vue/components → knowledge/chat/preset/vue/features}/conversation-search.md +13 -13
- package/resource/knowledge/chat/preset/vue/features/message-input.md +551 -0
- package/resource/knowledge/chat/preset/vue/features/message-list.md +350 -0
- package/resource/{doc/chatkit/vue/components → knowledge/chat/preset/vue/features}/search.md +79 -73
- package/resource/knowledge/chat/preset/vue/features/theme.md +136 -0
- package/resource/knowledge/chat/urls/error-code.md +17 -0
- package/resource/knowledge/chat/urls/product.md +43 -0
- package/resource/knowledge/chat/urls/restapi.md +204 -0
- package/resource/knowledge/chat/urls/sdk/android.md +80 -0
- package/resource/knowledge/chat/urls/sdk/flutter.md +71 -0
- package/resource/knowledge/chat/urls/sdk/ios.md +80 -0
- package/resource/knowledge/chat/urls/sdk/web.md +80 -0
- package/resource/knowledge/chat/urls/webhook.md +68 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/AudioEffectStore.md +286 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/BarrageStore.md +174 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/BattleStore.md +329 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CameraView.md +55 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CoGuestStore.md +434 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/CoHostStore.md +362 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/DeviceStore.md +466 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/GiftStore.md +173 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LikeStore.md +51 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveAudienceStore.md +291 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveCoreView.md +78 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LiveSeatStore.md +488 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/android/LoginStore.md +219 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/AudioEffectStore.md +282 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BarrageStore.md +212 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BaseBeautyStore.md +153 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/BattleStore.md +312 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoGuestStore.md +404 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/CoHostStore.md +334 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/DeviceStore.md +426 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/GiftStore.md +166 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LikeStore.md +52 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveAudienceStore.md +281 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveCoreView.md +150 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LiveSeatStore.md +438 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/flutter/LoginStore.md +190 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/AudioEffectStore.md +291 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BarrageStore.md +192 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BaseBeautyStore.md +146 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/BattleStore.md +309 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoGuestStore.md +370 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/CoHostStore.md +339 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/DeviceStore.md +503 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/GiftStore.md +188 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LikeStore.md +51 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveAudienceStore.md +289 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveCoreView.md +78 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LiveSeatStore.md +487 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/ios/LoginStore.md +183 -0
- package/resource/knowledge/livekit/core-sdk/api-reference/web/index.md +736 -0
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-audience-list.md +53 -47
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-audio-effect.md +28 -24
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-barrage.md +22 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-base-beauty.md +17 -15
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-co-guest-interaction.md +19 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-gift.md +102 -89
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-host-interaction.md +41 -37
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-integration.md +45 -43
- package/resource/{doc → knowledge}/livekit/core-sdk/live/android/live-live-list.md +23 -20
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-audience-list.md +41 -41
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-audio-effect.md +70 -69
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-barrage.md +68 -71
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-base-beauty.md +43 -47
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-co-guest-interaction.md +59 -56
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-gift.md +103 -105
- package/resource/knowledge/livekit/core-sdk/live/flutter/live-host-interaction.md +869 -0
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-integration.md +84 -87
- package/resource/{doc → knowledge}/livekit/core-sdk/live/flutter/live-live-list.md +43 -40
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-audience-list.md +11 -10
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-audio-effect.md +28 -24
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-barrage.md +22 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-base-beauty.md +15 -14
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-co-guest-interaction.md +19 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-gift.md +54 -50
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-host-interaction.md +41 -37
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-integration.md +40 -40
- package/resource/{doc → knowledge}/livekit/core-sdk/live/ios/live-live-list.md +19 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-audience-list.md +53 -47
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-audio-effect.md +28 -24
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-barrage.md +22 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-co-guest-interaction.md +41 -33
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-gift.md +94 -81
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-host-interaction.md +35 -30
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-integration.md +45 -42
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/android/voice-room-list.md +23 -20
- package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-audience-list.md +260 -0
- package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-audio-effect.md +598 -0
- package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-barrage.md +490 -0
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/flutter/voice-co-guest-interaction.md +65 -59
- package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-gift.md +424 -0
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/flutter/voice-integration.md +69 -76
- package/resource/knowledge/livekit/core-sdk/voice/flutter/voice-room-list.md +726 -0
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-audience-list.md +11 -10
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-audio-effect.md +28 -24
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-barrage.md +22 -18
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-co-guest-interaction.md +41 -33
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-gift.md +54 -50
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-host-interaction.md +35 -30
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-integration.md +49 -46
- package/resource/{doc → knowledge}/livekit/core-sdk/voice/ios/voice-room-list.md +19 -18
- package/resource/knowledge/livekit/faq/error-code.md +193 -0
- package/resource/{doc/livekit/preset/live/vue/components → knowledge/livekit/preset/live/vue/features}/barrage.md +56 -53
- package/resource/{doc/livekit/preset/live/vue/components → knowledge/livekit/preset/live/vue/features}/live-audience-list.md +22 -21
- package/resource/{doc/livekit/preset/live/vue/components → knowledge/livekit/preset/live/vue/features}/live-view.md +34 -32
- package/resource/knowledge/push/config/android.md +92 -0
- package/resource/knowledge/push/config/harmonyos.md +83 -0
- package/resource/knowledge/push/config/ios.md +254 -0
- package/resource/knowledge/push/config/react-native.md +254 -0
- package/resource/knowledge/push/config/unity.md +209 -0
- package/resource/knowledge/push/config/unreal-engine.md +194 -0
- package/resource/knowledge/push/integration/android.md +404 -0
- package/resource/knowledge/push/integration/flutter.md +465 -0
- package/resource/knowledge/push/integration/harmonyos.md +63 -0
- package/resource/knowledge/push/integration/ios.md +246 -0
- package/resource/knowledge/push/integration/react-native.md +366 -0
- package/resource/knowledge/push/integration/uni-app.md +208 -0
- package/resource/knowledge/push/integration/unity.md +389 -0
- package/resource/knowledge/push/integration/unreal-engine.md +390 -0
- package/resource/knowledge/push/overview/prepare.md +60 -0
- package/resource/knowledge/roomkit/core-sdk/android/call-user-to-room.md +241 -0
- package/resource/knowledge/roomkit/core-sdk/android/room-participant-state.md +588 -0
- package/resource/knowledge/roomkit/core-sdk/android/room-state.md +364 -0
- package/resource/knowledge/roomkit/core-sdk/android/schedule-room.md +340 -0
- package/resource/knowledge/roomkit/core-sdk/flutter/call-user-to-room.md +230 -0
- package/resource/knowledge/roomkit/core-sdk/flutter/room-participant-state.md +797 -0
- package/resource/knowledge/roomkit/core-sdk/flutter/room-state.md +325 -0
- package/resource/knowledge/roomkit/core-sdk/flutter/schedule-room.md +325 -0
- package/resource/knowledge/roomkit/core-sdk/ios/call-user-to-room.md +233 -0
- package/resource/knowledge/roomkit/core-sdk/ios/room-participant-state.md +569 -0
- package/resource/knowledge/roomkit/core-sdk/ios/room-state.md +325 -0
- package/resource/knowledge/roomkit/core-sdk/ios/schedule-room.md +322 -0
- package/resource/knowledge/roomkit/core-sdk/vue/call-user-to-room.md +221 -0
- package/resource/{doc/roomkit/vue/features → knowledge/roomkit/core-sdk/vue}/device-detection.md +49 -48
- package/resource/knowledge/roomkit/core-sdk/vue/device-state.md +461 -0
- package/resource/knowledge/roomkit/core-sdk/vue/free-beauty-panel.md +216 -0
- package/resource/knowledge/roomkit/core-sdk/vue/room-chat.md +370 -0
- package/resource/{doc/roomkit/vue/features → knowledge/roomkit/core-sdk/vue}/room-participant-state.md +61 -60
- package/resource/knowledge/roomkit/core-sdk/vue/room-state.md +280 -0
- package/resource/{doc/roomkit/vue/features → knowledge/roomkit/core-sdk/vue}/room-view.md +57 -56
- package/resource/knowledge/roomkit/core-sdk/vue/schedule-room.md +319 -0
- package/resource/knowledge/roomkit/core-sdk/vue/screen-share.md +267 -0
- package/resource/knowledge/roomkit/core-sdk/vue/virtual-background.md +261 -0
- package/resource/knowledge/roomkit/preset/android/integration.md +396 -0
- package/resource/knowledge/roomkit/preset/flutter/integration.md +404 -0
- package/resource/knowledge/roomkit/preset/ios/integration.md +369 -0
- package/resource/knowledge/roomkit/preset/react/integration.md +576 -0
- package/resource/knowledge/rtcengine/web/how_to_run_web_sdk_demo.md +44 -0
- package/resource/{doc → knowledge}/rtcengine/web/plugin/21-advanced-auto-play-policy.md +8 -2
- package/resource/{doc → knowledge}/rtcengine/web/plugin/22-advanced-audio-mixer.md +19 -1
- package/resource/{doc → knowledge}/rtcengine/web/plugin/23-advanced-support-detection.md +1 -1
- package/resource/{doc → knowledge}/rtcengine/web/plugin/24-advanced-network-quality.md +8 -8
- package/resource/{doc → knowledge}/rtcengine/web/plugin/25-advanced-device-change.md +1 -1
- package/resource/{doc → knowledge}/rtcengine/web/plugin/26-advanced-publish-cdn-stream.md +6 -6
- package/resource/{doc → knowledge}/rtcengine/web/plugin/27-advanced-small-stream.md +3 -3
- package/resource/{doc → knowledge}/rtcengine/web/plugin/29-advanced-water-mark.md +18 -0
- package/resource/{doc → knowledge}/rtcengine/web/plugin/31-advanced-plugins-overview.md +1 -1
- package/resource/{doc → knowledge}/rtcengine/web/plugin/34-advanced-proxy.md +2 -2
- package/resource/{doc → knowledge}/rtcengine/web/plugin/35-advanced-ai-denoiser.md +1 -1
- package/resource/knowledge/trtc/android/TRTCCloud.md +1915 -0
- package/resource/knowledge/trtc/android/TRTCCloudDef.md +1029 -0
- package/resource/knowledge/trtc/android/TRTCCloudListener.md +1095 -0
- package/resource/knowledge/trtc/android/TRTCStatistics.md +68 -0
- package/resource/knowledge/trtc/android/TXAudioEffectManager.md +502 -0
- package/resource/knowledge/trtc/android/TXBeautyManager.md +415 -0
- package/resource/knowledge/trtc/android/TXDeviceManager.md +169 -0
- package/resource/knowledge/trtc/android/TXLiteAVCode.md +125 -0
- package/resource/knowledge/trtc/c++/ITRTCCloud.md +2069 -0
- package/resource/knowledge/trtc/c++/ITRTCStatistics.md +73 -0
- package/resource/knowledge/trtc/c++/ITXAudioEffectManager.md +502 -0
- package/resource/knowledge/trtc/c++/ITXDeviceManager.md +391 -0
- package/resource/knowledge/trtc/c++/TRTCCloudCallback.md +1191 -0
- package/resource/knowledge/trtc/c++/TRTCTypeDef.md +931 -0
- package/resource/knowledge/trtc/c++/TXLiteAVCode.md +127 -0
- package/resource/knowledge/trtc/ios/TRTCCloud.md +2118 -0
- package/resource/knowledge/trtc/ios/TRTCCloudDef.md +975 -0
- package/resource/knowledge/trtc/ios/TRTCCloudDelegate.md +1131 -0
- package/resource/knowledge/trtc/ios/TRTCStatistics.md +68 -0
- package/resource/knowledge/trtc/ios/TXAudioEffectManager.md +423 -0
- package/resource/knowledge/trtc/ios/TXBeautyManager.md +416 -0
- package/resource/knowledge/trtc/ios/TXDeviceManager.md +387 -0
- package/resource/knowledge/trtc/ios/TXLiteAVCode.md +127 -0
- package/server.js +35 -10
- package/server.js.map +1 -1
- package/tools/call/get_native_call_uikit_integration.js +2 -3
- package/tools/call/get_native_call_uikit_integration.js.map +1 -1
- package/tools/call/get_native_callkit_core_integration.js +2 -5
- package/tools/call/get_native_callkit_core_integration.js.map +1 -1
- package/tools/call/get_web_call_uikit_integration.js +2 -3
- package/tools/call/get_web_call_uikit_integration.js.map +1 -1
- package/tools/chat/get_native_chat_uikit_integration.js +2 -3
- package/tools/chat/get_native_chat_uikit_integration.js.map +1 -1
- package/tools/chat/get_web_chat_uikit_integration.js +2 -3
- package/tools/chat/get_web_chat_uikit_integration.js.map +1 -1
- package/tools/common/present_framework_choice.js +19 -13
- package/tools/common/present_framework_choice.js.map +1 -1
- package/tools/common/record_answer.js +19 -25
- package/tools/common/record_answer.js.map +1 -1
- package/tools/common/record_feedback.js +17 -30
- package/tools/common/record_feedback.js.map +1 -1
- package/tools/common/search_trtc_knowledge.js +45 -0
- package/tools/common/search_trtc_knowledge.js.map +1 -0
- package/tools/definitions/get_native_call_uikit_integration_def.js +3 -1
- package/tools/definitions/get_native_call_uikit_integration_def.js.map +1 -1
- package/tools/definitions/get_native_callkit_core_integration_def.js +5 -3
- package/tools/definitions/get_native_callkit_core_integration_def.js.map +1 -1
- package/tools/definitions/get_native_chat_uikit_integration_def.js +5 -2
- package/tools/definitions/get_native_chat_uikit_integration_def.js.map +1 -1
- package/tools/definitions/get_native_livekit_core_integration_def.js +6 -5
- package/tools/definitions/get_native_livekit_core_integration_def.js.map +1 -1
- package/tools/definitions/get_web_call_uikit_integration_def.js +4 -2
- package/tools/definitions/get_web_call_uikit_integration_def.js.map +1 -1
- package/tools/definitions/get_web_chat_uikit_integration_def.js +2 -0
- package/tools/definitions/get_web_chat_uikit_integration_def.js.map +1 -1
- package/tools/definitions/get_web_live_uikit_integration_def.js +5 -5
- package/tools/definitions/get_web_live_uikit_integration_def.js.map +1 -1
- package/tools/definitions/get_web_room_core_integration_def.js +50 -0
- package/tools/definitions/get_web_room_core_integration_def.js.map +1 -0
- package/tools/definitions/get_web_room_uikit_integration_def.js +5 -4
- package/tools/definitions/get_web_room_uikit_integration_def.js.map +1 -1
- package/tools/definitions/integration-boundary.js +6 -0
- package/tools/definitions/integration-boundary.js.map +1 -0
- package/tools/definitions/present_framework_choice_def.js +12 -10
- package/tools/definitions/present_framework_choice_def.js.map +1 -1
- package/tools/definitions/record_answer_def.js +19 -17
- package/tools/definitions/record_answer_def.js.map +1 -1
- package/tools/definitions/record_feedback_def.js +14 -13
- package/tools/definitions/record_feedback_def.js.map +1 -1
- package/tools/definitions/search_trtc_knowledge_def.js +40 -0
- package/tools/definitions/search_trtc_knowledge_def.js.map +1 -0
- package/tools/index.js +5 -36
- package/tools/index.js.map +1 -1
- package/tools/live/get_native_livekit_core_integration.js +1 -3
- package/tools/live/get_native_livekit_core_integration.js.map +1 -1
- package/tools/live/get_web_live_uikit_integration.js +2 -4
- package/tools/live/get_web_live_uikit_integration.js.map +1 -1
- package/tools/room/get_web_room_core_integration.js +48 -0
- package/tools/room/get_web_room_core_integration.js.map +1 -0
- package/tools/room/get_web_room_uikit_integration.js +2 -3
- package/tools/room/get_web_room_uikit_integration.js.map +1 -1
- package/utils/generate-structured-result.js +24 -30
- package/utils/generate-structured-result.js.map +1 -1
- package/utils/get-doc-content.js +14 -8
- package/utils/get-doc-content.js.map +1 -1
- package/utils/report-cls-client.js +18 -20
- package/utils/report-cls-client.js.map +1 -1
- package/utils/report-es-client.js +1 -1
- package/resource/doc/callkit/core-sdk/.gitkeep +0 -0
- package/resource/doc/callkit/core-sdk/android/answer-call.md +0 -852
- package/resource/doc/callkit/core-sdk/android/make-call.md +0 -954
- package/resource/doc/callkit/core-sdk/android/offline-push.md +0 -361
- package/resource/doc/callkit/core-sdk/flutter/answer-call.md +0 -1160
- package/resource/doc/callkit/core-sdk/flutter/make-call.md +0 -1205
- package/resource/doc/callkit/core-sdk/ios/answer-call.md +0 -1090
- package/resource/doc/callkit/core-sdk/ios/make-call.md +0 -1248
- package/resource/doc/callkit/core-sdk/ios/offline-push.md +0 -485
- package/resource/doc/callkit/core-sdk/uni-app/answer-call.md +0 -950
- package/resource/doc/callkit/core-sdk/uni-app/make-call.md +0 -1052
- package/resource/doc/callkit/faq/common/error-code.md +0 -47
- package/resource/doc/callkit/faq/flutter-faq.md +0 -115
- package/resource/doc/callkit/faq/ios-faq.md +0 -115
- package/resource/doc/callkit/faq/web-faq.md +0 -36
- package/resource/doc/callkit/preset/android/api.md +0 -296
- package/resource/doc/callkit/preset/flutter/api.md +0 -410
- package/resource/doc/callkit/preset/flutter/integration.md +0 -164
- package/resource/doc/callkit/preset/ios/api.md +0 -80
- package/resource/doc/callkit/preset/ios/integration.md +0 -187
- package/resource/doc/callkit/preset/react/api.md +0 -501
- package/resource/doc/callkit/preset/react/integration.md +0 -86
- package/resource/doc/callkit/preset/vue/api.md +0 -501
- package/resource/doc/callkit/preset/vue/integration.md +0 -83
- package/resource/doc/chatkit/android/faq.md +0 -111
- package/resource/doc/chatkit/android/features/theme.md +0 -219
- package/resource/doc/chatkit/android/integration.md +0 -490
- package/resource/doc/chatkit/faq/android_sdk/client-api.md +0 -281
- package/resource/doc/chatkit/faq/common/product.md +0 -7
- package/resource/doc/chatkit/faq/common/server.md +0 -44
- package/resource/doc/chatkit/faq/common/server_error_code.md +0 -74
- package/resource/doc/chatkit/faq/flutter_sdk/client-api.md +0 -199
- package/resource/doc/chatkit/faq/flutter_sdk/faq.md +0 -53
- package/resource/doc/chatkit/faq/ios_sdk/client-api.md +0 -235
- package/resource/doc/chatkit/faq/web_sdk/error_code.md +0 -47
- package/resource/doc/chatkit/faq/web_sdk/faq.md +0 -287
- package/resource/doc/chatkit/flutter/faq.md +0 -23
- package/resource/doc/chatkit/flutter/features/theme.md +0 -235
- package/resource/doc/chatkit/flutter/integration.md +0 -344
- package/resource/doc/chatkit/ios/faq.md +0 -111
- package/resource/doc/chatkit/ios/features/theme.md +0 -267
- package/resource/doc/chatkit/react/components/avatar.md +0 -104
- package/resource/doc/chatkit/react/components/chat-header.md +0 -148
- package/resource/doc/chatkit/react/components/chat-setting.md +0 -57
- package/resource/doc/chatkit/react/components/chat.md +0 -38
- package/resource/doc/chatkit/react/components/component-list.md +0 -37
- package/resource/doc/chatkit/react/components/conversation-actions.md +0 -174
- package/resource/doc/chatkit/react/components/conversation-list.md +0 -333
- package/resource/doc/chatkit/react/components/conversation-preview.md +0 -118
- package/resource/doc/chatkit/react/components/conversation-search.md +0 -60
- package/resource/doc/chatkit/react/components/message-list.md +0 -293
- package/resource/doc/chatkit/react/components/tuikit.md +0 -34
- package/resource/doc/chatkit/react/faq.md +0 -26
- package/resource/doc/chatkit/react/integration.md +0 -416
- package/resource/doc/chatkit/vue/components/avatar.md +0 -104
- package/resource/doc/chatkit/vue/components/chat-header.md +0 -148
- package/resource/doc/chatkit/vue/components/chat-setting.md +0 -62
- package/resource/doc/chatkit/vue/components/chat.md +0 -45
- package/resource/doc/chatkit/vue/components/component-list.md +0 -87
- package/resource/doc/chatkit/vue/components/contact-list.md +0 -271
- package/resource/doc/chatkit/vue/components/conversation-actions.md +0 -228
- package/resource/doc/chatkit/vue/components/conversation-list.md +0 -320
- package/resource/doc/chatkit/vue/components/conversation-preview.md +0 -213
- package/resource/doc/chatkit/vue/components/message-input.md +0 -1054
- package/resource/doc/chatkit/vue/components/message-list.md +0 -433
- package/resource/doc/chatkit/vue/components/tuikit.md +0 -31
- package/resource/doc/chatkit/vue/components/userpicker.md +0 -256
- package/resource/doc/chatkit/vue/faq.md +0 -36
- package/resource/doc/chatkit/vue/integration.md +0 -428
- package/resource/doc/livekit/core-sdk/live/flutter/live-host-interaction.md +0 -866
- package/resource/doc/livekit/faq/common/error-code.md +0 -88
- package/resource/doc/livekit/preset/live/vue/api-reference/index.md +0 -780
- package/resource/doc/livekit/preset/live/vue/components/co-guest-panel.md +0 -91
- package/resource/doc/livekit/preset/live/vue/components/live-scene-panel.md +0 -112
- package/resource/doc/livekit/preset/live/vue/components/stream-mixer.md +0 -215
- package/resource/doc/livekit/preset/live/vue/live-player-h5-integration.md +0 -300
- package/resource/doc/roomkit/faq/common/error-code.md +0 -67
- package/resource/doc/roomkit/vue/features/call-user-to-room.md +0 -220
- package/resource/doc/roomkit/vue/features/device-state.md +0 -460
- package/resource/doc/roomkit/vue/features/free-beauty-panel.md +0 -215
- package/resource/doc/roomkit/vue/features/room-chat.md +0 -369
- package/resource/doc/roomkit/vue/features/room-state.md +0 -282
- package/resource/doc/roomkit/vue/features/schedule-room.md +0 -318
- package/resource/doc/roomkit/vue/features/screen-share.md +0 -265
- package/resource/doc/roomkit/vue/features/virtual-background.md +0 -271
- package/resource/doc/roomkit/vue/integration.md +0 -315
- package/resource/doc/rtcengine/faq/common/error_code.md +0 -1
- package/resource/doc/rtcengine/faq/web_sdk/.gitkeep +0 -0
- package/resource/doc/rtcengine/web/.gitkeep +0 -0
- package/resource/doc/rtcengine/web/how_to_run_web_sdk_demo.md +0 -59
- package/resource/doc/trtc/C++/ITRTCCloud.md +0 -1970
- package/resource/doc/trtc/C++/ITRTCStatistics.md +0 -70
- package/resource/doc/trtc/C++/ITXAudioEffectManager.md +0 -469
- package/resource/doc/trtc/C++/ITXDeviceManager.md +0 -387
- package/resource/doc/trtc/C++/TRTCCloudCallback.md +0 -1082
- package/resource/doc/trtc/C++/TRTCTypeDef.md +0 -925
- package/resource/doc/trtc/C++/TXLiteAVCode.md +0 -129
- package/resource/doc/trtc/android/TRTCCloud.md +0 -1815
- package/resource/doc/trtc/android/TRTCCloudDef.md +0 -992
- package/resource/doc/trtc/android/TRTCCloudListener.md +0 -1004
- package/resource/doc/trtc/android/TRTCStatistics.md +0 -65
- package/resource/doc/trtc/android/TXAudioEffectManager.md +0 -469
- package/resource/doc/trtc/android/TXBeautyManager.md +0 -402
- package/resource/doc/trtc/android/TXDeviceManager.md +0 -173
- package/resource/doc/trtc/android/TXLiteAVCode.md +0 -127
- package/resource/doc/trtc/iOS/TRTCCloud.md +0 -2028
- package/resource/doc/trtc/iOS/TRTCCloudDef.md +0 -958
- package/resource/doc/trtc/iOS/TRTCCloudDelegate.md +0 -1046
- package/resource/doc/trtc/iOS/TRTCStatistics.md +0 -65
- package/resource/doc/trtc/iOS/TXAudioEffectManager.md +0 -397
- package/resource/doc/trtc/iOS/TXBeautyManager.md +0 -403
- package/resource/doc/trtc/iOS/TXDeviceManager.md +0 -381
- package/resource/doc/trtc/iOS/TXLiteAVCode.md +0 -130
- package/tools/call/get_callkit_api.js +0 -33
- package/tools/call/get_callkit_api.js.map +0 -1
- package/tools/chat/get_native_chat_uikit_feature_detail.js +0 -35
- package/tools/chat/get_native_chat_uikit_feature_detail.js.map +0 -1
- package/tools/chat/get_web_chat_uikit_component_detail.js +0 -35
- package/tools/chat/get_web_chat_uikit_component_detail.js.map +0 -1
- package/tools/common/get_faq.js +0 -266
- package/tools/common/get_faq.js.map +0 -1
- package/tools/common/record_skill_session.js +0 -69
- package/tools/common/record_skill_session.js.map +0 -1
- package/tools/definitions/get_callkit_api_def.js +0 -29
- package/tools/definitions/get_callkit_api_def.js.map +0 -1
- package/tools/definitions/get_faq_def.js +0 -49
- package/tools/definitions/get_faq_def.js.map +0 -1
- package/tools/definitions/get_native_chat_uikit_feature_detail_def.js +0 -31
- package/tools/definitions/get_native_chat_uikit_feature_detail_def.js.map +0 -1
- package/tools/definitions/get_native_livekit_core_features_def.js +0 -34
- package/tools/definitions/get_native_livekit_core_features_def.js.map +0 -1
- package/tools/definitions/get_native_trtc_sdk_docs_def.js +0 -32
- package/tools/definitions/get_native_trtc_sdk_docs_def.js.map +0 -1
- package/tools/definitions/get_web_chat_uikit_component_detail_def.js +0 -31
- package/tools/definitions/get_web_chat_uikit_component_detail_def.js.map +0 -1
- package/tools/definitions/get_web_livekit_api_def.js +0 -30
- package/tools/definitions/get_web_livekit_api_def.js.map +0 -1
- package/tools/definitions/get_web_livekit_component_detail_def.js +0 -32
- package/tools/definitions/get_web_livekit_component_detail_def.js.map +0 -1
- package/tools/definitions/get_web_roomkit_feature_detail_def.js +0 -31
- package/tools/definitions/get_web_roomkit_feature_detail_def.js.map +0 -1
- package/tools/definitions/get_web_trtc_sdk_api_def.js +0 -27
- package/tools/definitions/get_web_trtc_sdk_api_def.js.map +0 -1
- package/tools/definitions/get_web_trtc_sdk_integration_def.js +0 -27
- package/tools/definitions/get_web_trtc_sdk_integration_def.js.map +0 -1
- package/tools/definitions/get_web_trtc_sdk_plugin_def.js +0 -27
- package/tools/definitions/get_web_trtc_sdk_plugin_def.js.map +0 -1
- package/tools/definitions/record_skill_session_def.js +0 -31
- package/tools/definitions/record_skill_session_def.js.map +0 -1
- package/tools/live/get_native_livekit_core_features.js +0 -68
- package/tools/live/get_native_livekit_core_features.js.map +0 -1
- package/tools/live/get_web_livekit_api.js +0 -33
- package/tools/live/get_web_livekit_api.js.map +0 -1
- package/tools/live/get_web_livekit_component_detail.js +0 -35
- package/tools/live/get_web_livekit_component_detail.js.map +0 -1
- package/tools/room/get_web_roomkit_feature_detail.js +0 -69
- package/tools/room/get_web_roomkit_feature_detail.js.map +0 -1
- package/tools/rtcengine/get_web_trtc_sdk_api.js +0 -32
- package/tools/rtcengine/get_web_trtc_sdk_api.js.map +0 -1
- package/tools/rtcengine/get_web_trtc_sdk_integration.js +0 -32
- package/tools/rtcengine/get_web_trtc_sdk_integration.js.map +0 -1
- package/tools/rtcengine/get_web_trtc_sdk_plugin.js +0 -32
- package/tools/rtcengine/get_web_trtc_sdk_plugin.js.map +0 -1
- package/tools/trtc/get_native_trtc_sdk_docs.js +0 -74
- package/tools/trtc/get_native_trtc_sdk_docs.js.map +0 -1
- package/utils/build-session-directives.js +0 -120
- package/utils/build-session-directives.js.map +0 -1
- package/utils/handle-framework.js +0 -9
- package/utils/handle-framework.js.map +0 -1
- package/utils/handle-state-name.js +0 -29
- package/utils/handle-state-name.js.map +0 -1
- package/utils/report-runtime-error-cls-client.js +0 -91
- package/utils/report-runtime-error-cls-client.js.map +0 -1
- /package/resource/{doc/livekit/preset/live/vue/faq.md → knowledge/push/config/donut.md} +0 -0
- /package/resource/{doc/roomkit/vue/faq.md → knowledge/push/integration/donut.md} +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/api.md +0 -0
- /package/resource/{doc/rtcengine/faq/web/web.md → knowledge/rtcengine/web/faq.md} +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/how_to_integrated_web_sdk.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/20-advanced-customized-capture-rendering.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/28-advanced-beauty.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/30-advanced-cross-room-link.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/36-advanced-virtual-background.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/37-advanced-voice-changer.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/39-advanced-video-decoder.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/40-advanced-video-mixer.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/41-advanced-small-stream-auto-switcher.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/42-advanced-realtime-transcriber.md +0 -0
- /package/resource/{doc → knowledge}/rtcengine/web/plugin/43-advanced-face-detection.md +0 -0
|
@@ -1,1090 +0,0 @@
|
|
|
1
|
-
This guide walks you through implementing the "answer call" feature using the **AtomicXCore SDK**, leveraging its **DeviceStore**, **CallStore**, and the core UI component **CallCoreView**.
|
|
2
|
-
|
|
3
|
-
## Core Features
|
|
4
|
-
|
|
5
|
-
To build multi-party Audio/Video Call scenarios with **AtomicXCore**, you'll use the following core modules:
|
|
6
|
-
|
|
7
|
-
| **Module** | **Description** |
|
|
8
|
-
| --- | --- |
|
|
9
|
-
| [CallCoreView](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview) | The main call UI component. It automatically observes `CallStore` data, renders video streams, and supports UI customization such as layout switching, avatar, and icon configuration. |
|
|
10
|
-
| [CallStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstore) | Manages the call lifecycle: make call, answer call, reject call, hang up. Provides real-time access to participant audio/video status, call timer, call records, and related data. |
|
|
11
|
-
| [DeviceStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/devicestore) | Controls audio/video devices: microphone (toggle/volume), camera (toggle/switch/quality), screen sharing, and real-time device status monitoring. |
|
|
12
|
-
|
|
13
|
-
## Getting Started
|
|
14
|
-
|
|
15
|
-
### Step 1: Activate the Service
|
|
16
|
-
|
|
17
|
-
Visit Activate the Service to obtain either a trial or paid version of the SDK.
|
|
18
|
-
|
|
19
|
-
### Step 2: Integrate the SDK
|
|
20
|
-
|
|
21
|
-
1. **Add Pod Dependency:** Add `pod 'AtomicXCore'` to your project's `Podfile`.
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
target 'YourProjectTarget' do
|
|
25
|
-
pod 'AtomicXCore'
|
|
26
|
-
end
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
> **Tips:**
|
|
30
|
-
>
|
|
31
|
-
> If your project does not have a Podfile, navigate to your `.xcodeproj` directory in the terminal and run `pod init` to generate one.
|
|
32
|
-
|
|
33
|
-
2. **Install Components:** In the terminal, navigate to the directory containing your `Podfile` and run:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
pod install --repo-update
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
> **Tips:**
|
|
40
|
-
>
|
|
41
|
-
> After installation, open your project using the `YourProjectName.xcworkspace` file.
|
|
42
|
-
|
|
43
|
-
### Step 3: Initialize and Log In
|
|
44
|
-
|
|
45
|
-
To start the call service, initialize `CallStore` and log in the user. `CallStore` will automatically sync user info after a successful login and enter the ready state. See the sample code below:
|
|
46
|
-
|
|
47
|
-
```swift
|
|
48
|
-
import UIKit
|
|
49
|
-
import AtomicXCore
|
|
50
|
-
import Combine
|
|
51
|
-
|
|
52
|
-
class ViewController: UIViewController {
|
|
53
|
-
var cancellables = Set<AnyCancellable>()
|
|
54
|
-
|
|
55
|
-
override func viewDidLoad() {
|
|
56
|
-
super.viewDidLoad()
|
|
57
|
-
// Initialize CallStore
|
|
58
|
-
let _ = CallStore.shared
|
|
59
|
-
|
|
60
|
-
// Set up user information
|
|
61
|
-
let userID = "test_001" // Replace with your UserID
|
|
62
|
-
let sdkAppID: Int = 1400000001 // Replace with your SDKAppID from the console
|
|
63
|
-
let secretKey = "**************" // Replace with your SecretKey from the console; for development only — never ship the SDKSecretKey
|
|
64
|
-
|
|
65
|
-
// Generate UserSig (for local testing only; always generate UserSig on your server in production).
|
|
66
|
-
// When Tencent RTC MCP Server is configured with sdkAppID and sdkSecretKey, the tool can issue it for you automatically.
|
|
67
|
-
let userSig = GenerateTestUserSig.genTestUserSig(
|
|
68
|
-
userID: userID,
|
|
69
|
-
sdkAppID: sdkAppID,
|
|
70
|
-
secretKey: secretKey
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
// Log in
|
|
74
|
-
LoginStore.shared.login(
|
|
75
|
-
sdkAppID: sdkAppID,
|
|
76
|
-
userID: userID,
|
|
77
|
-
userSig: userSig
|
|
78
|
-
) { result in
|
|
79
|
-
switch result {
|
|
80
|
-
case .success:
|
|
81
|
-
Log.info("login success")
|
|
82
|
-
// Initialize TUICallEngine
|
|
83
|
-
TUICallEngine.createInstance().`init`(Int32(sdkAppID), userId: userID, userSig: userSig) {
|
|
84
|
-
Log.info("TUICallEngine init success")
|
|
85
|
-
} fail: { code, message in
|
|
86
|
-
Log.error("TUICallEngine init failed, code: \(code), message: \(message ?? "")")
|
|
87
|
-
}
|
|
88
|
-
case .failure(let error):
|
|
89
|
-
Log.error("login failed, code: \(error.code), error: \(error.message)")
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**Login parameters:**
|
|
97
|
-
|
|
98
|
-
| **Parameter** | **Type** | **Description** |
|
|
99
|
-
| --- | --- | --- |
|
|
100
|
-
| `userID` | `String` | Unique identifier for the current user. Only letters, numbers, hyphens, and underscores are allowed. Avoid simple IDs like `1` or `123` to prevent multi-device login conflicts. |
|
|
101
|
-
| `sdkAppID` | `int` | Obtain from the Tencent RTC console; typically a 10-digit integer starting with `140` or `160`. |
|
|
102
|
-
| `secretKey` | `String` | SDKSecretKey paired with the `sdkAppID`, available in the Tencent RTC console. Used **only** to locally compute `UserSig` during development; never ship the SDKSecretKey with a release build. When **Tencent RTC MCP Server** is configured with both `sdkAppID` and `sdkSecretKey`, the tool can issue `UserSig` for you automatically. |
|
|
103
|
-
| `userSig` | `String` | Authentication token for TRTC. **Development**: use [GenerateTestUserSig.genTestUserSig](https://github.com/Tencent-RTC/TUIKit_iOS/blob/main/application/Debug/GenerateTestUserSig.swift) or the UserSig Tool to generate a temporary `UserSig`. When **Tencent RTC MCP Server** is configured with both `sdkAppID` and `sdkSecretKey`, the tool can issue a `UserSig` for you automatically. **Production**: always generate `UserSig` server-side with the SDKSecretKey; never embed or distribute the SDKSecretKey in the client. |
|
|
104
|
-
|
|
105
|
-
## Implement Answer Call
|
|
106
|
-
|
|
107
|
-
> **Important:** Make sure the user is logged in before answering a call. This is required for the service to work. Follow these 6 steps to implement the answer call feature.
|
|
108
|
-
|
|
109
|
-
### Step 1: Create Call Screen
|
|
110
|
-
|
|
111
|
-
You need a call screen that appears when a call is received.
|
|
112
|
-
|
|
113
|
-
1. **Create the call screen:** Implement a new `UIViewController` to serve as the call screen. This screen will be presented when an incoming call arrives.
|
|
114
|
-
2. **Attach [CallCoreView](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview/) to the call screen:** This core component observes `CallStore` data, renders video, and supports UI customization for layout, avatars, and icons.
|
|
115
|
-
|
|
116
|
-
```swift
|
|
117
|
-
import UIKit
|
|
118
|
-
import AtomicXCore
|
|
119
|
-
|
|
120
|
-
class CallViewController: UIViewController {
|
|
121
|
-
private var callCoreView: CallCoreView?
|
|
122
|
-
|
|
123
|
-
// 1. Create the call screen
|
|
124
|
-
override func viewDidLoad() {
|
|
125
|
-
super.viewDidLoad()
|
|
126
|
-
view.backgroundColor = .black
|
|
127
|
-
// 2. Attach CallCoreView to the call screen
|
|
128
|
-
callCoreView = CallCoreView(frame: view.bounds)
|
|
129
|
-
callCoreView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
130
|
-
if let callCoreView = callCoreView {
|
|
131
|
-
view.addSubview(callCoreView)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**CallCoreView Feature Overview:**
|
|
138
|
-
|
|
139
|
-
| **Feature** | **Description** | **Reference** |
|
|
140
|
-
| --- | --- | --- |
|
|
141
|
-
| **Set Layout Mode** | Switch between different layout modes. If not set, layout adapts automatically based on participant count. | Switch Layout Mode |
|
|
142
|
-
| **Set Avatar** | Set custom avatars for specific users by providing avatar resource paths. | Customize Default Avatar |
|
|
143
|
-
| **Set Volume Indicator Icon** | Display custom volume indicator icons for different volume levels. | Customize Volume Indicator Icon |
|
|
144
|
-
| **Set Network Status Icon** | Show network status icons based on real-time network quality. | Customize Network Status Icon |
|
|
145
|
-
| **Set Waiting Animation for Users** | In multi-party calls, display a GIF animation for users in the waiting state. | Customize Waiting Animation |
|
|
146
|
-
|
|
147
|
-
### Step 2: Add Answer and Reject Controls
|
|
148
|
-
|
|
149
|
-
Use the APIs from [DeviceStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/devicestore) and [CallStore](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstore) to implement your call controls.
|
|
150
|
-
|
|
151
|
-
- **DeviceStore:** Controls microphone (toggle/volume), camera (toggle/switch/quality), screen sharing, and monitors real-time device status. Bind these methods to button actions and update the UI in real time by listening for device status changes.
|
|
152
|
-
- **CallStore:** Provides core call controls such as answer, hang up, and reject. Bind these methods to button actions and listen for call status changes to keep the UI in sync with the call state.
|
|
153
|
-
|
|
154
|
-
**Icon resources:** Download button icons from the [GitHub icon folder](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call). These icons are designed for TUICallKit, copyright-free, and safe to use.
|
|
155
|
-
|
|
156
|
-
| **Resource** | **Description** | **Download** |
|
|
157
|
-
| --- | --- | --- |
|
|
158
|
-
| `icon_dialing` | Dial / accept call icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_dialing.imageset) |
|
|
159
|
-
| `icon_hangup` | Hang up / reject call icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_hangup.imageset) |
|
|
160
|
-
| `icon_camera_off` | Camera off icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_camera_off.imageset) |
|
|
161
|
-
| `icon_camera_on` | Camera on icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_camera_on.imageset) |
|
|
162
|
-
| `icon_mute_on` | Mute toggle (on) icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_mute_on.imageset) |
|
|
163
|
-
| `icon_mute` | Mute icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_mute.imageset) |
|
|
164
|
-
| `icon_handsfree` | Handsfree off icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_handsfree.imageset) |
|
|
165
|
-
| `icon_handsfree_on` | Handsfree on icon. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_handsfree_on.imageset) |
|
|
166
|
-
|
|
167
|
-
**Sample implementation for adding Answer and Reject buttons:**
|
|
168
|
-
|
|
169
|
-
1.1 **Add Answer and Reject Buttons:** Add "Answer" and "Reject" buttons, and bind their actions to the [accept](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstore/accept(completion:)) and [reject](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstore/reject(completion:)) methods.
|
|
170
|
-
|
|
171
|
-
```swift
|
|
172
|
-
import UIKit
|
|
173
|
-
import AtomicXCore
|
|
174
|
-
|
|
175
|
-
class CallViewController: UIViewController {
|
|
176
|
-
private var buttonReject: UIButton?
|
|
177
|
-
private var buttonAccept: UIButton?
|
|
178
|
-
|
|
179
|
-
override func viewDidLoad() {
|
|
180
|
-
super.viewDidLoad()
|
|
181
|
-
view.backgroundColor = .black
|
|
182
|
-
addControlButtons()
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private func addControlButtons() {
|
|
186
|
-
let buttonWidth: CGFloat = 80
|
|
187
|
-
let buttonHeight: CGFloat = 80
|
|
188
|
-
let spacing: CGFloat = 60
|
|
189
|
-
let bottomMargin: CGFloat = 100
|
|
190
|
-
let totalWidth = buttonWidth * 2 + spacing
|
|
191
|
-
let startX = (view.bounds.width - totalWidth) / 2
|
|
192
|
-
let buttonY = view.bounds.height - bottomMargin - buttonHeight
|
|
193
|
-
|
|
194
|
-
// Answer button
|
|
195
|
-
buttonAccept = createButton(
|
|
196
|
-
frame: CGRect(x: startX, y: buttonY, width: buttonWidth, height: buttonHeight),
|
|
197
|
-
title: "Answer",
|
|
198
|
-
backgroundColor: .systemGreen
|
|
199
|
-
)
|
|
200
|
-
buttonAccept?.addTarget(self, action: #selector(touchAcceptButton), for: .touchUpInside)
|
|
201
|
-
view.addSubview(buttonAccept!)
|
|
202
|
-
|
|
203
|
-
// Reject button
|
|
204
|
-
buttonReject = createButton(
|
|
205
|
-
frame: CGRect(x: startX + buttonWidth + spacing, y: buttonY, width: buttonWidth, height: buttonHeight),
|
|
206
|
-
title: "Reject",
|
|
207
|
-
backgroundColor: .systemRed
|
|
208
|
-
)
|
|
209
|
-
buttonReject?.addTarget(self, action: #selector(touchRejectButton), for: .touchUpInside)
|
|
210
|
-
view.addSubview(buttonReject!)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
@objc private func touchAcceptButton() {
|
|
214
|
-
CallStore.shared.accept(completion: nil)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
@objc private func touchRejectButton() {
|
|
218
|
-
CallStore.shared.reject(completion: nil)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
private func createButton(frame: CGRect, title: String, backgroundColor: UIColor) -> UIButton {
|
|
222
|
-
let button = UIButton(type: .system)
|
|
223
|
-
button.frame = frame
|
|
224
|
-
button.setTitle(title, for: .normal)
|
|
225
|
-
button.setTitleColor(.white, for: .normal)
|
|
226
|
-
button.backgroundColor = backgroundColor
|
|
227
|
-
button.layer.cornerRadius = frame.width / 2
|
|
228
|
-
button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
|
|
229
|
-
return button
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
1.2 **Close the call screen when the call ends:** Whether the caller cancels or the callee rejects, the `onCallEnded` event is triggered. Listen for this event and close (dismiss) the call screen when the call ends.
|
|
235
|
-
|
|
236
|
-
```swift
|
|
237
|
-
import UIKit
|
|
238
|
-
import AtomicXCore
|
|
239
|
-
import Combine
|
|
240
|
-
|
|
241
|
-
class CallViewController: UIViewController {
|
|
242
|
-
private var cancellables = Set<AnyCancellable>()
|
|
243
|
-
|
|
244
|
-
override func viewDidLoad() {
|
|
245
|
-
super.viewDidLoad()
|
|
246
|
-
addListener()
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
private func addListener() {
|
|
250
|
-
CallStore.shared.callEventPublisher
|
|
251
|
-
.receive(on: DispatchQueue.main)
|
|
252
|
-
.sink { [weak self] event in
|
|
253
|
-
if case .onCallEnded = event {
|
|
254
|
-
self?.dismiss(animated: true)
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
.store(in: &cancellables)
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Step 3: Request Audio/Video Permissions
|
|
263
|
-
|
|
264
|
-
Check audio and video permissions before connecting the call. If permissions are missing, prompt the user to grant them.
|
|
265
|
-
|
|
266
|
-
1. **Declare permissions:** Add the following entries to your `Info.plist` file with appropriate usage descriptions. These will be displayed when the system requests permissions.
|
|
267
|
-
|
|
268
|
-
```xml
|
|
269
|
-
<key>NSCameraUsageDescription</key>
|
|
270
|
-
<string>Camera access is required for video calls and group video calls.</string>
|
|
271
|
-
<key>NSMicrophoneUsageDescription</key>
|
|
272
|
-
<string>Microphone access is required for audio calls, group audio calls, video calls, and group video calls.</string>
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
2. **Request permissions dynamically:** Request audio/video permissions when an incoming call is received, or as needed by your business logic.
|
|
276
|
-
|
|
277
|
-
```swift
|
|
278
|
-
import AVFoundation
|
|
279
|
-
import UIKit
|
|
280
|
-
|
|
281
|
-
extension UIViewController {
|
|
282
|
-
// Check microphone permission
|
|
283
|
-
func checkMicrophonePermission(completion: @escaping (Bool) -> Void) {
|
|
284
|
-
let status = AVCaptureDevice.authorizationStatus(for: .audio)
|
|
285
|
-
switch status {
|
|
286
|
-
case .authorized:
|
|
287
|
-
completion(true)
|
|
288
|
-
case .notDetermined:
|
|
289
|
-
AVCaptureDevice.requestAccess(for: .audio) { granted in
|
|
290
|
-
DispatchQueue.main.async {
|
|
291
|
-
completion(granted)
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
case .denied, .restricted:
|
|
295
|
-
completion(false)
|
|
296
|
-
@unknown default:
|
|
297
|
-
completion(false)
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Check camera permission
|
|
302
|
-
func checkCameraPermission(completion: @escaping (Bool) -> Void) {
|
|
303
|
-
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
|
304
|
-
switch status {
|
|
305
|
-
case .authorized:
|
|
306
|
-
completion(true)
|
|
307
|
-
case .notDetermined:
|
|
308
|
-
AVCaptureDevice.requestAccess(for: .video) { granted in
|
|
309
|
-
DispatchQueue.main.async {
|
|
310
|
-
completion(granted)
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
case .denied, .restricted:
|
|
314
|
-
completion(false)
|
|
315
|
-
@unknown default:
|
|
316
|
-
completion(false)
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Show permission alert
|
|
321
|
-
func showPermissionAlert(message: String) {
|
|
322
|
-
let alert = UIAlertController(
|
|
323
|
-
title: "Permission Request",
|
|
324
|
-
message: message,
|
|
325
|
-
preferredStyle: .alert
|
|
326
|
-
)
|
|
327
|
-
alert.addAction(UIAlertAction(title: "Go to Settings", style: .default) { _ in
|
|
328
|
-
if let url = URL(string: UIApplication.openSettingsURLString) {
|
|
329
|
-
UIApplication.shared.open(url)
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
|
|
333
|
-
present(alert, animated: true)
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### Step 4: Handle Incoming Call Notifications
|
|
339
|
-
|
|
340
|
-
Listen for the current user's call status and play a ringtone or vibration when a call is incoming. Stop the notification when the call is answered or ends.
|
|
341
|
-
|
|
342
|
-
1. **Subscribe to user status:** Subscribe to `CallStore.shared.state.value.selfInfo` to reactively monitor the current user's status.
|
|
343
|
-
2. **Play/stop ringtone or vibration:** If `selfInfo.status` is `.waiting`, play a ringtone or vibration. If the status changes to `.accept`, stop the notification.
|
|
344
|
-
|
|
345
|
-
```swift
|
|
346
|
-
import UIKit
|
|
347
|
-
import AtomicXCore
|
|
348
|
-
import Combine
|
|
349
|
-
import AVFoundation
|
|
350
|
-
|
|
351
|
-
class MainViewController: UIViewController {
|
|
352
|
-
private var audioPlayer: AVAudioPlayer?
|
|
353
|
-
private var cancellables = Set<AnyCancellable>()
|
|
354
|
-
|
|
355
|
-
override func viewDidLoad() {
|
|
356
|
-
super.viewDidLoad()
|
|
357
|
-
observeSelfStatus()
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
private func observeSelfStatus() {
|
|
361
|
-
CallStore.shared.state
|
|
362
|
-
.subscribe(StatePublisherSelector<CallState, CallParticipantStatus>(keyPath: \.selfInfo.status))
|
|
363
|
-
.removeDuplicates()
|
|
364
|
-
.receive(on: DispatchQueue.main)
|
|
365
|
-
.sink { [weak self] status in
|
|
366
|
-
self?.handleRingtoneByStatus(status)
|
|
367
|
-
}
|
|
368
|
-
.store(in: &cancellables)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
private func handleRingtoneByStatus(_ status: CallParticipantStatus) {
|
|
372
|
-
switch status {
|
|
373
|
-
case .waiting:
|
|
374
|
-
// Start ringtone while waiting to answer
|
|
375
|
-
// playRingtone()
|
|
376
|
-
break
|
|
377
|
-
case .accept:
|
|
378
|
-
// Stop ringtone after answering
|
|
379
|
-
// stopRingtone()
|
|
380
|
-
break
|
|
381
|
-
default:
|
|
382
|
-
// Stop ringtone for other statuses
|
|
383
|
-
// stopRingtone()
|
|
384
|
-
break
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### Step 5: Enable Media Devices on Incoming Call
|
|
391
|
-
|
|
392
|
-
When an incoming call arrives, determine the media type via the [onCallReceived](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callevent/oncallreceived(callid:mediatype:userdata:)) event. Enable the appropriate media devices when the call UI is displayed.
|
|
393
|
-
|
|
394
|
-
1. **Listen for incoming call event:** Subscribe to the `onCallReceived` event.
|
|
395
|
-
2. **Enable devices based on media type:** For audio calls, enable the microphone only. For video calls, enable both the microphone and camera.
|
|
396
|
-
|
|
397
|
-
```swift
|
|
398
|
-
import UIKit
|
|
399
|
-
import AtomicXCore
|
|
400
|
-
import Combine
|
|
401
|
-
|
|
402
|
-
class MainViewController: UIViewController {
|
|
403
|
-
private var cancellables = Set<AnyCancellable>()
|
|
404
|
-
|
|
405
|
-
override func viewDidLoad() {
|
|
406
|
-
super.viewDidLoad()
|
|
407
|
-
addListener()
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
private func addListener() {
|
|
411
|
-
CallStore.shared.callEventPublisher
|
|
412
|
-
.receive(on: DispatchQueue.main)
|
|
413
|
-
.sink { [weak self] event in
|
|
414
|
-
if case .onCallReceived(_, let mediaType, _) = event {
|
|
415
|
-
self?.openDeviceForMediaType(mediaType)
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
.store(in: &cancellables)
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
private func openDeviceForMediaType(_ mediaType: CallMediaType) {
|
|
422
|
-
DeviceStore.shared.openLocalMicrophone(completion: nil)
|
|
423
|
-
if mediaType == .video {
|
|
424
|
-
let isFront = true
|
|
425
|
-
DeviceStore.shared.openLocalCamera(isFront: isFront, completion: nil)
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
**openLocalCamera API Parameters:**
|
|
432
|
-
|
|
433
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
434
|
-
| --- | --- | --- | --- |
|
|
435
|
-
| `isFront` | `Bool` | Yes | Whether to use the front camera.<br>- `true`: Front camera.<br>- `false`: Rear camera. |
|
|
436
|
-
| `completion` | `CompletionHandler` | No | Completion callback; returns the result of enabling the camera. If it fails, returns error code and message. |
|
|
437
|
-
|
|
438
|
-
**openLocalMicrophone API Parameters:**
|
|
439
|
-
|
|
440
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
441
|
-
| --- | --- | --- | --- |
|
|
442
|
-
| `completion` | `CompletionHandler` | No | Completion callback; returns the result of enabling the microphone. If it fails, returns error code and message. |
|
|
443
|
-
|
|
444
|
-
### Step 6: Present Call UI on Incoming Call
|
|
445
|
-
|
|
446
|
-
Listen for the [onCallReceived](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callevent/oncallreceived(callid:mediatype:userdata:)) event. When an incoming call is received, present the call screen.
|
|
447
|
-
|
|
448
|
-
1. **Subscribe to the incoming call event:** Listen for `onCallReceived`.
|
|
449
|
-
2. **Present the call screen:** Show the call UI when an incoming call is detected.
|
|
450
|
-
|
|
451
|
-
```swift
|
|
452
|
-
import UIKit
|
|
453
|
-
import AtomicXCore
|
|
454
|
-
import Combine
|
|
455
|
-
|
|
456
|
-
class MainViewController: UIViewController {
|
|
457
|
-
private var cancellables = Set<AnyCancellable>()
|
|
458
|
-
|
|
459
|
-
override func viewDidLoad() {
|
|
460
|
-
super.viewDidLoad()
|
|
461
|
-
addListener()
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
private func addListener() {
|
|
465
|
-
CallStore.shared.callEventPublisher
|
|
466
|
-
.receive(on: DispatchQueue.main)
|
|
467
|
-
.sink { [weak self] event in
|
|
468
|
-
if case .onCallReceived(_, _, _) = event {
|
|
469
|
-
let callVC = CallViewController()
|
|
470
|
-
callVC.modalPresentationStyle = .fullScreen
|
|
471
|
-
self?.present(callVC, animated: true)
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
.store(in: &cancellables)
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
**onCallReceived Event Parameters:**
|
|
480
|
-
|
|
481
|
-
| **Parameter** | **Type** | **Description** |
|
|
482
|
-
| --- | --- | --- |
|
|
483
|
-
| `callId` | `String` | Unique identifier for the call. |
|
|
484
|
-
| `mediaType` | `CallMediaType` | Specifies whether the call is audio or video.<br>- `CallMediaType.video`: Video call.<br>- `CallMediaType.audio`: Audio call. |
|
|
485
|
-
|
|
486
|
-
### Demo Effect
|
|
487
|
-
|
|
488
|
-
After completing the above 6 steps, your answer call feature is wired up end-to-end.
|
|
489
|
-
|
|
490
|
-
## Customize the Call UI
|
|
491
|
-
|
|
492
|
-
`CallCoreView` offers extensive UI customization, including support for custom avatars and volume indicator icons. To speed up your integration, you can download ready-to-use resources from the [GitHub icon folder](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call). All resources are copyright-free.
|
|
493
|
-
|
|
494
|
-
### Custom Volume Indicator Icons
|
|
495
|
-
|
|
496
|
-
Use [setVolumeLevelIcons](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview/setvolumelevelicons(icons:)) to assign different icons for each volume level.
|
|
497
|
-
|
|
498
|
-
```swift
|
|
499
|
-
// Set volume indicator icons
|
|
500
|
-
let volumeLevelIcons: [VolumeLevel: String] = [
|
|
501
|
-
.mute: "path to the corresponding icon resource"
|
|
502
|
-
]
|
|
503
|
-
callCoreView.setVolumeLevelIcons(icons: volumeLevelIcons)
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
**setVolumeLevelIcons API Parameters:**
|
|
507
|
-
|
|
508
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
509
|
-
| --- | --- | --- | --- |
|
|
510
|
-
| `icons` | `[VolumeLevel: String]` | Yes | A dictionary mapping volume levels to icon resources.<br>**Key (`VolumeLevel`):**<br>- `VolumeLevel.mute`: Microphone muted.<br>- `VolumeLevel.low`: Volume (0, 25].<br>- `VolumeLevel.medium`: Volume (25, 50].<br>- `VolumeLevel.high`: Volume (50, 75].<br>- `VolumeLevel.peak`: Volume (75, 100].<br>**Value (`String`):** Path to the icon resource for each level. |
|
|
511
|
-
|
|
512
|
-
**Volume Indicator Icons:**
|
|
513
|
-
|
|
514
|
-
| **Resource** | **Description** | **Download** |
|
|
515
|
-
| --- | --- | --- |
|
|
516
|
-
| `icon_volume` | Volume indicator icon. Recommended for `VolumeLevel.low` or `VolumeLevel.medium`. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_volume.imageset) |
|
|
517
|
-
| `icon_mic_off` | Mute icon. Recommended for `VolumeLevel.mute`. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/icon_mic_off.imageset) |
|
|
518
|
-
|
|
519
|
-
### Custom Network Status Icons
|
|
520
|
-
|
|
521
|
-
Use [setNetworkQualityIcons](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview/setnetworkqualityicons(icons:)) to set custom icons for different network states.
|
|
522
|
-
|
|
523
|
-
```swift
|
|
524
|
-
// Set network quality icons
|
|
525
|
-
let networkQualityIcons: [NetworkQuality: String] = [
|
|
526
|
-
.bad: "path to the corresponding icon"
|
|
527
|
-
]
|
|
528
|
-
callCoreView.setNetworkQualityIcons(icons: networkQualityIcons)
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
**setNetworkQualityIcons API Parameters:**
|
|
532
|
-
|
|
533
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
534
|
-
| --- | --- | --- | --- |
|
|
535
|
-
| `icons` | `[NetworkQuality: String]` | Yes | Network Quality Icon mapping table.<br>**Key (`NetworkQuality`):**<br>- `NetworkQuality.unknown`: Network status undetermined.<br>- `NetworkQuality.excellent`: Outstanding network connection.<br>- `NetworkQuality.good`: Stable and good network connection.<br>- `NetworkQuality.poor`: Weak network signal.<br>- `NetworkQuality.bad`: Very weak or unstable network.<br>- `NetworkQuality.veryBad`: Extremely poor network, near disconnection.<br>- `NetworkQuality.down`: Network disconnected.<br>**Value (`String`):** Absolute path or resource name of the icon corresponding to each network status level. |
|
|
536
|
-
|
|
537
|
-
**Poor Network Indicator Icon:**
|
|
538
|
-
|
|
539
|
-
| **Resource** | **Description** | **Download** |
|
|
540
|
-
| --- | --- | --- |
|
|
541
|
-
| `group_network_low_quality` | Poor network indicator icon. Recommended for `NetworkQuality.bad`, `NetworkQuality.veryBad`, or `NetworkQuality.down`. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/group_network_low_quality.imageset) |
|
|
542
|
-
|
|
543
|
-
### Custom Default Avatar
|
|
544
|
-
|
|
545
|
-
Use [setParticipantAvatars](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview/setparticipantavatars(avatars:)) to set user avatars. Listen to the [allParticipants](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstate/allparticipants) data to update avatars as needed. If an avatar is not set or fails to load, the default avatar is displayed.
|
|
546
|
-
|
|
547
|
-
```swift
|
|
548
|
-
// Set user avatars
|
|
549
|
-
var avatars: [String: String] = [:]
|
|
550
|
-
let userId = "" // User ID
|
|
551
|
-
let avatarPath = "" // Path to user's default avatar resource
|
|
552
|
-
avatars[userId] = avatarPath
|
|
553
|
-
|
|
554
|
-
callCoreView.setParticipantAvatars(avatars: avatars)
|
|
555
|
-
```
|
|
556
|
-
|
|
557
|
-
**setParticipantAvatars API Parameters:**
|
|
558
|
-
|
|
559
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
560
|
-
| --- | --- | --- | --- |
|
|
561
|
-
| `avatars` | `[String: String]` | Yes | A dictionary mapping `userID` to the absolute path of the user's avatar resource. |
|
|
562
|
-
|
|
563
|
-
**Default Avatar Resource:**
|
|
564
|
-
|
|
565
|
-
| **Resource** | **Description** | **Download** |
|
|
566
|
-
| --- | --- | --- |
|
|
567
|
-
| `default_participant_icon` | Default avatar. Use as the fallback when a user's avatar fails to load or is not set. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/tree/main/atomic_x/Resources/AtomicX.xcassets/icon/call/default_participant_icon.imageset) |
|
|
568
|
-
|
|
569
|
-
### Custom Waiting Animation
|
|
570
|
-
|
|
571
|
-
Use [setWaitingAnimation](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview/setwaitinganimation(path:)) to display a waiting animation for users in the waiting state.
|
|
572
|
-
|
|
573
|
-
```swift
|
|
574
|
-
// Set waiting animation
|
|
575
|
-
let waitingAnimationPath = "" // Path to the waiting animation GIF resource
|
|
576
|
-
callCoreView.setWaitingAnimation(path: waitingAnimationPath)
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
**setWaitingAnimation API Parameters:**
|
|
580
|
-
|
|
581
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
582
|
-
| --- | --- | --- | --- |
|
|
583
|
-
| `path` | `String` | Yes | Absolute path to the GIF animation resource. |
|
|
584
|
-
|
|
585
|
-
**Waiting Animation:**
|
|
586
|
-
|
|
587
|
-
| **Resource** | **Description** | **Download** |
|
|
588
|
-
| --- | --- | --- |
|
|
589
|
-
| `loading.gif` | User waiting animation. Recommended for group calls; display when a user's status is waiting. | [GitHub](https://github.com/Tencent-RTC/TUIKit_iOS/blob/main/atomic_x/Resources/CallResource/loading.gif) |
|
|
590
|
-
|
|
591
|
-
### Add Call Timer
|
|
592
|
-
|
|
593
|
-
You can display the call duration in real time by subscribing to the [activeCall](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstate/activecall) `duration` field.
|
|
594
|
-
|
|
595
|
-
1. **Subscribe to the active call:** Listen to `CallStore.shared.state` for updates.
|
|
596
|
-
2. **Bind duration to your UI:** Bind `activeCall.duration` to your timer UI. This field is reactive and updates automatically; you do not need to manage a timer manually.
|
|
597
|
-
|
|
598
|
-
```swift
|
|
599
|
-
import UIKit
|
|
600
|
-
import AtomicXCore
|
|
601
|
-
import Combine
|
|
602
|
-
|
|
603
|
-
class TimerView: UILabel {
|
|
604
|
-
private var cancellables = Set<AnyCancellable>()
|
|
605
|
-
|
|
606
|
-
override init(frame: CGRect) {
|
|
607
|
-
super.init(frame: frame)
|
|
608
|
-
setupView()
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
required init?(coder: NSCoder) {
|
|
612
|
-
super.init(coder: coder)
|
|
613
|
-
setupView()
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
private func setupView() {
|
|
617
|
-
textColor = .white
|
|
618
|
-
textAlignment = .center
|
|
619
|
-
font = .systemFont(ofSize: 16)
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
override func didMoveToWindow() {
|
|
623
|
-
super.didMoveToWindow()
|
|
624
|
-
if window != nil {
|
|
625
|
-
registerActiveCallObserver()
|
|
626
|
-
} else {
|
|
627
|
-
cancellables.removeAll()
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
private func registerActiveCallObserver() {
|
|
632
|
-
CallStore.shared.state.subscribe()
|
|
633
|
-
.map { $0.activeCall }
|
|
634
|
-
.removeDuplicates { $0.duration == $1.duration }
|
|
635
|
-
.receive(on: DispatchQueue.main)
|
|
636
|
-
.sink { [weak self] activeCall in
|
|
637
|
-
self?.updateDurationView(activeCall: activeCall)
|
|
638
|
-
}
|
|
639
|
-
.store(in: &cancellables)
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
private func updateDurationView(activeCall: CallInfo) {
|
|
643
|
-
let currentDuration = activeCall.duration
|
|
644
|
-
let minutes = currentDuration / 60
|
|
645
|
-
let seconds = currentDuration % 60
|
|
646
|
-
text = String(format: "%02d:%02d", minutes, seconds)
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
```
|
|
650
|
-
|
|
651
|
-
> **Note:**
|
|
652
|
-
>
|
|
653
|
-
> For more reactive call status data, see [CallState](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callstate).
|
|
654
|
-
|
|
655
|
-
## More Features
|
|
656
|
-
|
|
657
|
-
### Set User Avatar and Nickname
|
|
658
|
-
|
|
659
|
-
Before a call starts, set your own nickname and avatar using [setSelfInfo](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/loginstore/setselfinfo(userprofile:completion:)).
|
|
660
|
-
|
|
661
|
-
```swift
|
|
662
|
-
import AtomicXCore
|
|
663
|
-
|
|
664
|
-
var userProfile = UserProfile()
|
|
665
|
-
userProfile.userID = "" // Your userId
|
|
666
|
-
userProfile.avatarURL = "" // Avatar URL
|
|
667
|
-
userProfile.nickname = "" // Nickname
|
|
668
|
-
|
|
669
|
-
LoginStore.shared.setSelfInfo(userProfile: userProfile) { result in
|
|
670
|
-
switch result {
|
|
671
|
-
case .success:
|
|
672
|
-
// Successfully set
|
|
673
|
-
break
|
|
674
|
-
case .failure(let error):
|
|
675
|
-
// Failed to set
|
|
676
|
-
break
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
```
|
|
680
|
-
|
|
681
|
-
**setSelfInfo API Parameters:**
|
|
682
|
-
|
|
683
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
684
|
-
| --- | --- | --- | --- |
|
|
685
|
-
| `userProfile` | `UserProfile` | Yes | User info struct:<br>- `userID`: User ID.<br>- `avatarURL`: User avatar URL.<br>- `nickname`: User nickname.<br>For more field details, see the [UserProfile](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/userprofile) class. |
|
|
686
|
-
| `completion` | `CompletionHandler` | No | Completion callback; returns the result of the operation. |
|
|
687
|
-
|
|
688
|
-
### Switch Layout Modes
|
|
689
|
-
|
|
690
|
-
`CallCoreView` supports three built-in layout modes. Use [setLayoutTemplate](https://tencent-rtc.github.io/TUIKit_iOS/documentation/atomicxcore/callcoreview/setlayouttemplate(_:)) to set the layout. If not set, `CallCoreView` will automatically use `Float` mode for 1v1 calls and `Grid` mode for multi-party calls.
|
|
691
|
-
|
|
692
|
-
| **Mode** | **Layout** | **Interaction** |
|
|
693
|
-
| --- | --- | --- |
|
|
694
|
-
| **Float Mode** | While waiting, display your own video full screen. After answering, show the remote video full screen and your own video as a floating window. | Drag the small window or tap to swap big/small video. |
|
|
695
|
-
| **Grid Mode** | All participant videos are tiled in a grid. Best for 2+ participants. Tap to enlarge a video. | Tap a participant to enlarge their video. |
|
|
696
|
-
| **PIP Mode** | In 1v1, remote video is fixed; in multi-party, the active speaker is shown full screen. | Shows your own video while waiting; displays the call timer after answering. |
|
|
697
|
-
|
|
698
|
-
```swift
|
|
699
|
-
// Create CallCoreView
|
|
700
|
-
let callCoreView = CallCoreView(frame: view.bounds)
|
|
701
|
-
callCoreView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
702
|
-
|
|
703
|
-
// Set layout mode
|
|
704
|
-
let template = CallLayoutTemplate.grid
|
|
705
|
-
callCoreView.setLayoutTemplate(template)
|
|
706
|
-
```
|
|
707
|
-
|
|
708
|
-
**setLayoutTemplate API Parameters:**
|
|
709
|
-
|
|
710
|
-
| **Parameter** | **Type** | **Required** | **Description** |
|
|
711
|
-
| --- | --- | --- | --- |
|
|
712
|
-
| `template` | `CallLayoutTemplate` | Yes | `CallCoreView`'s layout mode.<br>- `CallLayoutTemplate.float`: While waiting, display your own video full screen; after answering, show the remote video full screen and your own video as a floating window.<br>- `CallLayoutTemplate.grid`: All participant videos are tiled in a grid; best for 2+ participants.<br>- `CallLayoutTemplate.pip`: In 1v1, remote video is fixed; in multi-party, the active speaker is shown full screen. |
|
|
713
|
-
|
|
714
|
-
### Implement In-App Floating Window
|
|
715
|
-
|
|
716
|
-
The AtomicXCore SDK provides a `CallPipView` component for in-app floating windows. If your call UI is covered by other pages (e.g., user presses back while a call is ongoing), a floating window can be shown so users can always see call status and quickly return to the call UI.
|
|
717
|
-
|
|
718
|
-
**Step 1:** Create the floating window controller.
|
|
719
|
-
|
|
720
|
-
```swift
|
|
721
|
-
import UIKit
|
|
722
|
-
import AtomicXCore
|
|
723
|
-
import Combine
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* Floating Window Controller
|
|
727
|
-
*
|
|
728
|
-
* Used to display the call floating window, containing a CallCoreView internally.
|
|
729
|
-
*/
|
|
730
|
-
class FloatWindowViewController: UIViewController {
|
|
731
|
-
var tapGestureAction: (() -> Void)?
|
|
732
|
-
private var cancellables = Set<AnyCancellable>()
|
|
733
|
-
|
|
734
|
-
private lazy var callCoreView: CallCoreView = {
|
|
735
|
-
let view = CallCoreView(frame: self.view.bounds)
|
|
736
|
-
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
737
|
-
view.setLayoutTemplate(.pip) // Set to Picture-in-Picture (PiP) layout mode
|
|
738
|
-
view.isUserInteractionEnabled = false // Disable interaction to allow touch events to pass through to the parent view
|
|
739
|
-
return view
|
|
740
|
-
}()
|
|
741
|
-
|
|
742
|
-
override func viewDidLoad() {
|
|
743
|
-
super.viewDidLoad()
|
|
744
|
-
view.backgroundColor = UIColor(white: 0.1, alpha: 1.0)
|
|
745
|
-
view.layer.cornerRadius = 10
|
|
746
|
-
view.layer.masksToBounds = true
|
|
747
|
-
view.addSubview(callCoreView)
|
|
748
|
-
|
|
749
|
-
// Add tap gesture recognizer
|
|
750
|
-
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
|
|
751
|
-
view.addGestureRecognizer(tapGesture)
|
|
752
|
-
|
|
753
|
-
// Delay observing state changes to prevent the window from closing immediately upon creation
|
|
754
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
|
|
755
|
-
self?.observeCallStatus()
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
@objc private func handleTap() {
|
|
760
|
-
tapGestureAction?()
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
/**
|
|
764
|
-
* Observe call status changes.
|
|
765
|
-
* Automatically closes the floating window when the call ends.
|
|
766
|
-
*/
|
|
767
|
-
private func observeCallStatus() {
|
|
768
|
-
CallStore.shared.state
|
|
769
|
-
.subscribe(StatePublisherSelector<CallState, CallParticipantStatus>(keyPath: \.selfInfo.status))
|
|
770
|
-
.removeDuplicates()
|
|
771
|
-
.receive(on: DispatchQueue.main)
|
|
772
|
-
.sink { [weak self] status in
|
|
773
|
-
if status == .none {
|
|
774
|
-
// Call ended, post a notification to hide the floating window
|
|
775
|
-
NotificationCenter.default.post(name: NSNotification.Name("HideFloatingWindow"), object: nil)
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
.store(in: &cancellables)
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
deinit {
|
|
782
|
-
cancellables.removeAll()
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
```
|
|
786
|
-
|
|
787
|
-
**Step 2:** Add floating window management logic to your main UI.
|
|
788
|
-
|
|
789
|
-
```swift
|
|
790
|
-
import UIKit
|
|
791
|
-
import AtomicXCore
|
|
792
|
-
|
|
793
|
-
class MainViewController: UIViewController {
|
|
794
|
-
private var floatWindow: UIWindow?
|
|
795
|
-
|
|
796
|
-
override func viewDidLoad() {
|
|
797
|
-
super.viewDidLoad()
|
|
798
|
-
// Observe notification to display the floating window
|
|
799
|
-
NotificationCenter.default.addObserver(
|
|
800
|
-
self,
|
|
801
|
-
selector: #selector(showFloatingWindow),
|
|
802
|
-
name: NSNotification.Name("ShowFloatingWindow"),
|
|
803
|
-
object: nil
|
|
804
|
-
)
|
|
805
|
-
// Observe notification to hide the floating window
|
|
806
|
-
NotificationCenter.default.addObserver(
|
|
807
|
-
self,
|
|
808
|
-
selector: #selector(hideFloatingWindow),
|
|
809
|
-
name: NSNotification.Name("HideFloatingWindow"),
|
|
810
|
-
object: nil
|
|
811
|
-
)
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
/**
|
|
815
|
-
* Displays the in-app floating window.
|
|
816
|
-
*/
|
|
817
|
-
@objc private func showFloatingWindow() {
|
|
818
|
-
// Check if a call is currently active/accepted
|
|
819
|
-
let selfStatus = CallStore.shared.state.value.selfInfo.status
|
|
820
|
-
guard selfStatus == .accept else {
|
|
821
|
-
return
|
|
822
|
-
}
|
|
823
|
-
// Prevent duplicate creation if the floating window already exists
|
|
824
|
-
guard floatWindow == nil else { return }
|
|
825
|
-
// CRITICAL: The window must be created using the current windowScene
|
|
826
|
-
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
|
|
827
|
-
return
|
|
828
|
-
}
|
|
829
|
-
// Define floating window dimensions (9:16 aspect ratio)
|
|
830
|
-
let pipWidth: CGFloat = 100
|
|
831
|
-
let pipHeight: CGFloat = pipWidth * 16 / 9
|
|
832
|
-
let pipX = UIScreen.main.bounds.width - pipWidth - 20
|
|
833
|
-
let pipY: CGFloat = 100
|
|
834
|
-
|
|
835
|
-
// Initialize the floating UIWindow and associate it with the windowScene
|
|
836
|
-
let window = UIWindow(windowScene: windowScene)
|
|
837
|
-
window.windowLevel = .alert + 1 // Ensure it stays on top of the main UI
|
|
838
|
-
window.backgroundColor = .clear
|
|
839
|
-
window.frame = CGRect(x: pipX, y: pipY, width: pipWidth, height: pipHeight)
|
|
840
|
-
|
|
841
|
-
// Initialize the floating window controller
|
|
842
|
-
let floatVC = FloatWindowViewController()
|
|
843
|
-
floatVC.tapGestureAction = { [weak self] in
|
|
844
|
-
self?.openCallViewController()
|
|
845
|
-
}
|
|
846
|
-
window.rootViewController = floatVC
|
|
847
|
-
self.floatWindow = window
|
|
848
|
-
|
|
849
|
-
// Make the window visible
|
|
850
|
-
window.isHidden = false
|
|
851
|
-
window.makeKeyAndVisible()
|
|
852
|
-
|
|
853
|
-
// Immediately restore the main window as the key window to maintain proper focus
|
|
854
|
-
if let mainWindow = windowScene.windows.first(where: { $0 != window }) {
|
|
855
|
-
mainWindow.makeKey()
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
/**
|
|
860
|
-
* Hides the in-app floating window.
|
|
861
|
-
*/
|
|
862
|
-
@objc private func hideFloatingWindow() {
|
|
863
|
-
floatWindow?.isHidden = true
|
|
864
|
-
floatWindow = nil
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
/**
|
|
868
|
-
* Opens the call interface (triggered by tapping the floating window).
|
|
869
|
-
*/
|
|
870
|
-
private func openCallViewController() {
|
|
871
|
-
// Dismiss the floating window first
|
|
872
|
-
hideFloatingWindow()
|
|
873
|
-
// Retrieve the current top-most ViewController
|
|
874
|
-
guard let topVC = getTopViewController() else {
|
|
875
|
-
return
|
|
876
|
-
}
|
|
877
|
-
let callVC = CallViewController()
|
|
878
|
-
callVC.modalPresentationStyle = .fullScreen
|
|
879
|
-
topVC.present(callVC, animated: true)
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
/**
|
|
883
|
-
* Helper method to find the top-most ViewController in the current view hierarchy.
|
|
884
|
-
*/
|
|
885
|
-
private func getTopViewController() -> UIViewController? {
|
|
886
|
-
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
|
887
|
-
let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow }),
|
|
888
|
-
let rootVC = keyWindow.rootViewController else {
|
|
889
|
-
return nil
|
|
890
|
-
}
|
|
891
|
-
var topVC = rootVC
|
|
892
|
-
while let presentedVC = topVC.presentedViewController {
|
|
893
|
-
topVC = presentedVC
|
|
894
|
-
}
|
|
895
|
-
return topVC
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
deinit {
|
|
899
|
-
NotificationCenter.default.removeObserver(self)
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
```
|
|
903
|
-
|
|
904
|
-
**Step 3:** Add floating window trigger logic in the call UI.
|
|
905
|
-
|
|
906
|
-
```swift
|
|
907
|
-
import UIKit
|
|
908
|
-
import AtomicXCore
|
|
909
|
-
|
|
910
|
-
class CallViewController: UIViewController {
|
|
911
|
-
override func viewWillAppear(_ animated: Bool) {
|
|
912
|
-
super.viewWillAppear(animated)
|
|
913
|
-
// Post a notification to hide the floating window when entering the call interface
|
|
914
|
-
NotificationCenter.default.post(name: NSNotification.Name("HideFloatingWindow"), object: nil)
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
override func viewWillDisappear(_ animated: Bool) {
|
|
918
|
-
super.viewWillDisappear(animated)
|
|
919
|
-
// When leaving the call interface, check if the call is still active
|
|
920
|
-
let selfStatus = CallStore.shared.state.value.selfInfo.status
|
|
921
|
-
if selfStatus == .accept {
|
|
922
|
-
// If the call is still ongoing, post a notification to display the floating window
|
|
923
|
-
NotificationCenter.default.post(name: NSNotification.Name("ShowFloatingWindow"), object: nil)
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
```
|
|
928
|
-
|
|
929
|
-
### Implement System Picture-in-Picture (PiP)
|
|
930
|
-
|
|
931
|
-
AtomicXCore SDK supports system PiP via the underlying TRTC engine. When the app goes to the background, the call video can float as a system PiP window above other apps, allowing users to continue video calls while multitasking.
|
|
932
|
-
|
|
933
|
-
> **Note:**
|
|
934
|
-
>
|
|
935
|
-
> 1. Add the `Background Modes` capability in Xcode's `Signing & Capabilities` and enable `Audio, AirPlay, and Picture in Picture`.
|
|
936
|
-
> 2. Requires iOS 15.0 or later.
|
|
937
|
-
|
|
938
|
-
1. **Configure PiP parameters:** Set fill mode, user video regions, canvas parameters, etc.
|
|
939
|
-
|
|
940
|
-
```swift
|
|
941
|
-
import AtomicXCore
|
|
942
|
-
|
|
943
|
-
// Fill Mode Enumeration
|
|
944
|
-
enum PictureInPictureFillMode: Int, Codable {
|
|
945
|
-
case fill = 0 // Aspect Fill: Scales the content to fill the view (may crop)
|
|
946
|
-
case fit = 1 // Aspect Fit: Scales the content to fit the view (no cropping)
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
// User Video Region
|
|
950
|
-
struct PictureInPictureRegion: Codable {
|
|
951
|
-
let userId: String // Unique User ID
|
|
952
|
-
let width: Double // Width (0.0 - 1.0, relative to the canvas)
|
|
953
|
-
let height: Double // Height (0.0 - 1.0, relative to the canvas)
|
|
954
|
-
let x: Double // X-coordinate (0.0 - 1.0, relative to the top-left of the canvas)
|
|
955
|
-
let y: Double // Y-coordinate (0.0 - 1.0, relative to the top-left of the canvas)
|
|
956
|
-
let fillMode: PictureInPictureFillMode // Content fill mode
|
|
957
|
-
let streamType: String // Stream type ("high" for HD or "low" for SD)
|
|
958
|
-
let backgroundColor: String // Background color (e.g., Hex string)
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
// Canvas Configuration
|
|
962
|
-
struct PictureInPictureCanvas: Codable {
|
|
963
|
-
let width: Int // Canvas width in pixels
|
|
964
|
-
let height: Int // Canvas height in pixels
|
|
965
|
-
let backgroundColor: String // Background color
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
// Picture-in-Picture Parameters
|
|
969
|
-
struct PictureInPictureParams: Codable {
|
|
970
|
-
let enable: Bool // Toggle PiP functionality
|
|
971
|
-
let cameraBackgroundCapture: Bool? // Whether to continue camera capture in the background
|
|
972
|
-
let canvas: PictureInPictureCanvas? // Canvas configuration (Optional)
|
|
973
|
-
let regions: [PictureInPictureRegion]? // List of user video regions (Optional)
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// Picture-in-Picture Request
|
|
977
|
-
struct PictureInPictureRequest: Codable {
|
|
978
|
-
let api: String // API name/identifier
|
|
979
|
-
let params: PictureInPictureParams // Parameter payload
|
|
980
|
-
}
|
|
981
|
-
```
|
|
982
|
-
|
|
983
|
-
2. **Enable PiP:** Use `configPictureInPicture` to enable or disable PiP.
|
|
984
|
-
|
|
985
|
-
```swift
|
|
986
|
-
let params = PictureInPictureParams(
|
|
987
|
-
enable: true,
|
|
988
|
-
cameraBackgroundCapture: true,
|
|
989
|
-
canvas: nil,
|
|
990
|
-
regions: nil
|
|
991
|
-
)
|
|
992
|
-
|
|
993
|
-
let request = PictureInPictureRequest(
|
|
994
|
-
api: "configPictureInPicture",
|
|
995
|
-
params: params
|
|
996
|
-
)
|
|
997
|
-
|
|
998
|
-
// Encode the request into a JSON string
|
|
999
|
-
let encoder = JSONEncoder()
|
|
1000
|
-
if let data = try? encoder.encode(request),
|
|
1001
|
-
let jsonString = String(data: data, encoding: .utf8) {
|
|
1002
|
-
// Invoke the experimental API via the TUICallEngine instance
|
|
1003
|
-
TUICallEngine.createInstance().callExperimentalAPI(jsonObject: jsonString)
|
|
1004
|
-
}
|
|
1005
|
-
```
|
|
1006
|
-
|
|
1007
|
-
### Keep Screen Awake During Calls
|
|
1008
|
-
|
|
1009
|
-
To prevent the screen from sleeping during a call, set `UIApplication.shared.isIdleTimerDisabled = true` when the call UI appears, and restore it when the UI disappears.
|
|
1010
|
-
|
|
1011
|
-
```swift
|
|
1012
|
-
class CallViewController: UIViewController {
|
|
1013
|
-
override func viewDidLoad() {
|
|
1014
|
-
super.viewDidLoad()
|
|
1015
|
-
UIApplication.shared.isIdleTimerDisabled = true
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
override func viewWillDisappear(_ animated: Bool) {
|
|
1019
|
-
super.viewWillDisappear(animated)
|
|
1020
|
-
UIApplication.shared.isIdleTimerDisabled = false
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
```
|
|
1024
|
-
|
|
1025
|
-
### Background Audio/Video Capture Issues
|
|
1026
|
-
|
|
1027
|
-
To allow your app to capture audio and video in the background (e.g., when locked or switched to another app), you must:
|
|
1028
|
-
|
|
1029
|
-
1. **Configure iOS background modes:** In Xcode, open your project, select your target, go to `Signing & Capabilities`, add `Background Modes`, and enable:
|
|
1030
|
-
- `Audio, AirPlay, and Picture in Picture`
|
|
1031
|
-
- `Voice over IP`
|
|
1032
|
-
- `Remote notifications` (optional, for offline push)
|
|
1033
|
-
|
|
1034
|
-
Your `Info.plist` will include:
|
|
1035
|
-
|
|
1036
|
-
```xml
|
|
1037
|
-
<key>UIBackgroundModes</key>
|
|
1038
|
-
<array>
|
|
1039
|
-
<string>audio</string>
|
|
1040
|
-
<string>voip</string>
|
|
1041
|
-
<string>remote-notification</string>
|
|
1042
|
-
</array>
|
|
1043
|
-
```
|
|
1044
|
-
|
|
1045
|
-
2. **Configure AVAudioSession:** Set up the audio session before the call starts (e.g., in the call UI's `viewDidLoad` or before making/answering a call).
|
|
1046
|
-
|
|
1047
|
-
```swift
|
|
1048
|
-
import AVFoundation
|
|
1049
|
-
|
|
1050
|
-
private func setupAudioSession() {
|
|
1051
|
-
let audioSession = AVAudioSession.sharedInstance()
|
|
1052
|
-
do {
|
|
1053
|
-
try audioSession.setCategory(.playAndRecord, options: [.allowBluetooth, .allowBluetoothA2DP])
|
|
1054
|
-
try audioSession.setActive(true)
|
|
1055
|
-
} catch {
|
|
1056
|
-
// Handle audio session configuration failure
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
```
|
|
1060
|
-
|
|
1061
|
-
3. **Special handling for ringtone playback (optional):** To play the ringtone through the speaker, temporarily switch the audio session to `.playback` mode.
|
|
1062
|
-
|
|
1063
|
-
```swift
|
|
1064
|
-
private func setAudioSessionForRingtone() {
|
|
1065
|
-
let audioSession = AVAudioSession.sharedInstance()
|
|
1066
|
-
do {
|
|
1067
|
-
try audioSession.setCategory(.playback, options: [.allowBluetooth, .allowBluetoothA2DP])
|
|
1068
|
-
try audioSession.overrideOutputAudioPort(.speaker)
|
|
1069
|
-
try audioSession.setActive(true)
|
|
1070
|
-
} catch {
|
|
1071
|
-
// Handle configuration failure
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
private func restoreAudioSessionForCall() {
|
|
1076
|
-
let audioSession = AVAudioSession.sharedInstance()
|
|
1077
|
-
do {
|
|
1078
|
-
try audioSession.setCategory(.playAndRecord, options: [.allowBluetooth, .allowBluetoothA2DP])
|
|
1079
|
-
try audioSession.setActive(true)
|
|
1080
|
-
} catch {
|
|
1081
|
-
// Handle restore failure
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
```
|
|
1085
|
-
|
|
1086
|
-
## FAQs
|
|
1087
|
-
|
|
1088
|
-
### If the callee is offline and comes online within the call invitation timeout, will they receive the incoming call event?
|
|
1089
|
-
|
|
1090
|
-
For one-on-one calls, if the callee comes online within the timeout, they will receive the incoming call invitation. For group calls, if the callee comes online within the timeout, up to 20 unprocessed group messages will be retrieved, and if there is a call invitation, the incoming call event will be triggered.
|