expo-callkit-telecom 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +197 -0
- package/android/build.gradle +32 -0
- package/android/src/main/AndroidManifest.xml +33 -0
- package/android/src/main/java/expo/modules/callkittelecom/ExpoCallKitTelecomModule.kt +384 -0
- package/android/src/main/java/expo/modules/callkittelecom/IncomingCallActivity.kt +275 -0
- package/android/src/main/java/expo/modules/callkittelecom/events/CallEventEmitter.kt +151 -0
- package/android/src/main/java/expo/modules/callkittelecom/events/CallEvents.kt +59 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CallAudioManager.kt +361 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CallManager.kt +891 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CallNotificationManager.kt +445 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/CaptureSessionManager.kt +27 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/DialtonePlayer.kt +171 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/FulfillRequestManager.kt +150 -0
- package/android/src/main/java/expo/modules/callkittelecom/managers/VoIPPushManager.kt +54 -0
- package/android/src/main/java/expo/modules/callkittelecom/models/CallModels.kt +269 -0
- package/android/src/main/java/expo/modules/callkittelecom/services/CallNotificationReceiver.kt +54 -0
- package/android/src/main/java/expo/modules/callkittelecom/services/ExpoCallKitTelecomMessagingService.kt +161 -0
- package/android/src/main/java/expo/modules/callkittelecom/store/CallStore.kt +181 -0
- package/android/src/main/java/expo/modules/callkittelecom/utils/CallKitTelecomLog.kt +52 -0
- package/android/src/main/java/expo/modules/callkittelecom/utils/PermissionUtils.kt +28 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_bg_answer.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_bg_avatar.xml +5 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_bg_decline.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_ic_answer.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_ic_decline.xml +9 -0
- package/android/src/main/res/drawable/expo_callkit_telecom_ic_videocam.xml +9 -0
- package/android/src/main/res/layout/activity_incoming_call.xml +169 -0
- package/app.json +8 -0
- package/app.plugin.js +1 -0
- package/build/Calls.d.ts +577 -0
- package/build/Calls.d.ts.map +1 -0
- package/build/Calls.js +715 -0
- package/build/Calls.js.map +1 -0
- package/build/Calls.types.d.ts +203 -0
- package/build/Calls.types.d.ts.map +1 -0
- package/build/Calls.types.js +2 -0
- package/build/Calls.types.js.map +1 -0
- package/build/ExpoCallKitTelecomModule.d.ts +3 -0
- package/build/ExpoCallKitTelecomModule.d.ts.map +1 -0
- package/build/ExpoCallKitTelecomModule.js +4 -0
- package/build/ExpoCallKitTelecomModule.js.map +1 -0
- package/build/hooks/index.d.ts +2 -0
- package/build/hooks/index.d.ts.map +1 -0
- package/build/hooks/index.js +2 -0
- package/build/hooks/index.js.map +1 -0
- package/build/hooks/useVoIPPushToken.d.ts +14 -0
- package/build/hooks/useVoIPPushToken.d.ts.map +1 -0
- package/build/hooks/useVoIPPushToken.js +26 -0
- package/build/hooks/useVoIPPushToken.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +10 -0
- package/ios/AppDelegateSubscriber.swift +93 -0
- package/ios/ExpoCallKitTelecom.podspec +31 -0
- package/ios/ExpoCallKitTelecomLogger.swift +55 -0
- package/ios/ExpoCallKitTelecomModule.swift +503 -0
- package/ios/Managers/AudioManager.swift +363 -0
- package/ios/Managers/CallEventEmitter.swift +199 -0
- package/ios/Managers/CallManager+CXProviderDelegate.swift +195 -0
- package/ios/Managers/CallManager.swift +714 -0
- package/ios/Managers/CaptureSessionManager.swift +54 -0
- package/ios/Managers/DialtonePlayer.swift +126 -0
- package/ios/Managers/FulfillRequestManager.swift +154 -0
- package/ios/Managers/VoIPPushManager+PKPushRegistryDelegate.swift +123 -0
- package/ios/Managers/VoIPPushManager.swift +58 -0
- package/ios/Models/CallEvents.swift +263 -0
- package/ios/Models/CallOptions.swift +15 -0
- package/ios/Models/CallParticipant.swift +37 -0
- package/ios/Models/CallSession.swift +80 -0
- package/ios/Models/IncomingCallEvent.swift +196 -0
- package/ios/Stores/CallStore.swift +149 -0
- package/package.json +56 -0
- package/plugin/build/constants.d.ts +3 -0
- package/plugin/build/constants.js +7 -0
- package/plugin/build/withExpoCallKitTelecom.d.ts +67 -0
- package/plugin/build/withExpoCallKitTelecom.js +16 -0
- package/plugin/build/withExpoCallKitTelecomAndroid.d.ts +3 -0
- package/plugin/build/withExpoCallKitTelecomAndroid.js +177 -0
- package/plugin/build/withExpoCallKitTelecomIos.d.ts +3 -0
- package/plugin/build/withExpoCallKitTelecomIos.js +195 -0
- package/plugin/src/constants.ts +4 -0
- package/plugin/src/withExpoCallKitTelecom.ts +83 -0
- package/plugin/src/withExpoCallKitTelecomAndroid.ts +293 -0
- package/plugin/src/withExpoCallKitTelecomIos.ts +276 -0
- package/src/Calls.ts +848 -0
- package/src/Calls.types.ts +275 -0
- package/src/ExpoCallKitTelecomModule.ts +4 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useVoIPPushToken.ts +34 -0
- package/src/index.ts +3 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calls.js","sourceRoot":"","sources":["../src/Calls.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @module Calls\n *\n * This module provides APIs for managing VoIP calls with native system integration.\n * Functions are organized into three categories:\n *\n * ## Requests (Imperative)\n * Functions that initiate actions from the app. These request the system to perform\n * an operation on behalf of the user:\n * - {@link startOutgoingCall} - Start a new outgoing call\n * - {@link answerCall} - Answer an incoming call\n * - {@link endCall} - End or decline an active call\n * - {@link setMuted} - Mute/unmute the call\n * - {@link setHeld} - Hold/unhold the call\n * - {@link playDTMF} - Play DTMF tones\n *\n * ## Reporters\n * Functions that report state changes to the system. Use these to inform the system\n * about events that occurred outside of its control (e.g., from your backend or\n * media connection):\n * - {@link reportIncomingCall} - Report a new incoming call (e.g., from push notification)\n * - {@link reportOutgoingCallConnected} - Report that an outgoing call's media is connected\n * - {@link reportCallEnded} - Report that a call ended externally (e.g., remote hangup)\n * - {@link reportVideo} - Report video state changes\n *\n * ## Fulfillers\n * Functions that complete pending system requests. When the system requests an action\n * (via event listeners), your app must perform the action and then call the corresponding\n * fulfiller to confirm completion:\n * - {@link fulfillIncomingCallConnected} - Confirm that incoming call media is connected\n *\n * ## Typical Flow\n *\n * **Outgoing Call:**\n * 1. Call {@link startOutgoingCall} to initiate\n * 2. Listen for {@link addCallStartedListener} to know when to connect media\n * 3. Connect your media (e.g., WebRTC)\n * 4. Call {@link reportOutgoingCallConnected} when media is ready\n *\n * **Incoming Call:**\n * 1. Receive push notification with call data\n * 2. Call {@link reportIncomingCall} to show the incoming call UI\n * 3. Listen for {@link addCallAnsweredListener} to know when user answered\n * 4. Connect your media (e.g., WebRTC)\n * 5. Call {@link fulfillIncomingCallConnected} when media is ready\n *\n * **Ending a Call:**\n * - If user ends: Call {@link endCall} and clean up media\n * - If remote ends: Clean up media, then call {@link reportCallEnded}\n */\n\nimport type { EventSubscription } from \"expo-modules-core\";\nimport { Platform } from \"react-native\";\n\nimport type {\n AudioRouteChangedEvent,\n AudioSession,\n AudioSessionActivatedEvent,\n AudioSessionDeactivatedEvent,\n CallAnsweredEvent,\n CallEndedEvent,\n CallEndedReason,\n CallIntentReceivedEvent,\n CallOptions,\n CallParticipant,\n CallReportedEnded,\n CallSession,\n CallSessionAddedEvent,\n CallSessionRemovedEvent,\n CallSessionUpdatedEvent,\n CaptureSession,\n DTMFEvent,\n IncomingCallEvent,\n IncomingCallReportedEvent,\n OutgoingCallStartedEvent,\n SetHeldActionEvent,\n SetMutedActionEvent,\n VideoChangedEvent,\n VoIPPushToken,\n VoIPPushTokenUpdatedEvent,\n} from \"./Calls.types\";\nimport type { PushTokenType } from \"./Calls.types\";\nimport ExpoCallKitTelecomModule from \"./ExpoCallKitTelecomModule\";\n\n// ============================================================================\n// Call Session\n// ============================================================================\n\n/**\n * Gets the currently active call session, if any.\n *\n * @returns The active call session, or `null` if no call is in progress.\n *\n * @example\n * ```typescript\n * const session = await getActiveCallSession();\n * if (session) {\n * console.log('Active call with:', session.remoteParticipants[0]?.displayName);\n * }\n * ```\n */\nexport async function getActiveCallSession(): Promise<CallSession | null> {\n const session = await ExpoCallKitTelecomModule.getActiveCallSession();\n if (session) {\n }\n return session;\n}\n\n/**\n * Subscribes to call session added events.\n *\n * Fired when a new call session is created, either from an outgoing call request\n * or an incoming call report.\n *\n * @param listener - Callback invoked when a session is added.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @example\n * ```typescript\n * const subscription = addCallSessionAddedListener((event) => {\n * console.log('New call session:', event.session.id);\n * });\n *\n * // Later, to unsubscribe:\n * subscription.remove();\n * ```\n */\nexport function addCallSessionAddedListener(\n listener: (event: CallSessionAddedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\n \"onCallSessionAdded\",\n (event: CallSessionAddedEvent) => {\n listener(event);\n },\n );\n}\n\n/**\n * Subscribes to call session updated events.\n *\n * Fired when an existing call session's state changes (e.g., status, mute state).\n *\n * @param listener - Callback invoked when a session is updated.\n * @returns A subscription that can be removed by calling `.remove()`.\n */\nexport function addCallSessionUpdatedListener(\n listener: (event: CallSessionUpdatedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\n \"onCallSessionUpdated\",\n (event: CallSessionUpdatedEvent) => {\n listener(event);\n },\n );\n}\n\n/**\n * Subscribes to call session removed events.\n *\n * Fired when a call session is removed after the call has ended and been cleaned up.\n *\n * @param listener - Callback invoked when a session is removed.\n * @returns A subscription that can be removed by calling `.remove()`.\n */\nexport function addCallSessionRemovedListener(\n listener: (event: CallSessionRemovedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onCallSessionRemoved\", listener);\n}\n\n// ============================================================================\n// Audio Session\n// ============================================================================\n\n/**\n * Gets the current audio session state.\n *\n * Returns information about the audio session including whether it's active,\n * the current category/mode, and the audio route (speaker, earpiece, etc.).\n *\n * @returns The current audio session state.\n *\n * @category Audio\n */\nexport function getAudioSession(): AudioSession {\n return ExpoCallKitTelecomModule.getAudioSessionState();\n}\n\n/**\n * Gets the current capture session state.\n *\n * Returns information about the capture session including camera permission status.\n *\n * @returns The current capture session state.\n *\n * @category Capture\n */\nexport function getCaptureSession(): CaptureSession {\n return ExpoCallKitTelecomModule.getCaptureSessionState();\n}\n\n/**\n * Sets the RTC audio session configuration (iOS only).\n *\n * This sets up WebRTC's RTCAudioSession default configuration and enables manual\n * audio management. On Android this is a no-op — audio configuration is handled\n * by {@link prepareAudioSessionForCall}.\n *\n * @param hasVideo - Whether to configure for video calls (uses speaker by default)\n * or audio-only calls (uses earpiece by default).\n *\n * @category Audio\n */\nexport function setRTCAudioSessionConfiguration(hasVideo: boolean): void {\n if (Platform.OS === \"ios\") {\n ExpoCallKitTelecomModule.setRTCAudioSessionConfiguration(hasVideo);\n }\n}\n\n/**\n * Prepares the audio session for an upcoming call.\n *\n * This snapshots the current audio configuration (for later restoration) and\n * pre-configures the audio session for the call. Called automatically when\n * reporting/starting a call, but can be called manually for early preparation.\n *\n * @param hasVideo - Whether to configure for video calls (uses speaker by default)\n * or audio-only calls (uses earpiece by default).\n *\n * @category Audio\n */\nexport function prepareAudioSessionForCall(hasVideo: boolean): void {\n ExpoCallKitTelecomModule.prepareAudioSessionForCall(hasVideo);\n}\n\n/**\n * Restores the audio session to its pre-call configuration.\n *\n * Call this if a call fails to start after prepareAudioSessionForCall was called,\n * or to manually restore the audio session. This is called automatically when\n * the audio session is deactivated after a call ends.\n *\n * @category Audio\n */\nexport function restoreAudioSession(): void {\n ExpoCallKitTelecomModule.restoreAudioSession();\n}\n\n/**\n * Sets the audio session port override.\n *\n * Use this to route audio to the speaker instead of the earpiece, or vice versa.\n *\n * @param enabled - If `true`, routes audio to the speaker. If `false`, uses\n * the default route (typically earpiece for voice calls).\n *\n * @category Audio\n */\nexport function setAudioSessionPortOverride(enabled: boolean): void {\n ExpoCallKitTelecomModule.setAudioSessionPortOverride(enabled);\n}\n\n/**\n * Subscribes to audio session activated events.\n *\n * Fired when the audio session is activated for a call. This is when your\n * app gains exclusive access to audio hardware.\n *\n * @param listener - Callback invoked when audio session activates.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Audio Event Listener\n */\nexport function addAudioSessionActivatedListener(\n listener: (event: AudioSessionActivatedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onAudioSessionActivated\", listener);\n}\n\n/**\n * Subscribes to audio session deactivated events.\n *\n * Fired when the audio session is deactivated after a call ends.\n *\n * @param listener - Callback invoked when audio session deactivates.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Audio Event Listener\n */\nexport function addAudioSessionDeactivatedListener(\n listener: (event: AudioSessionDeactivatedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onAudioSessionDeactivated\", listener);\n}\n\n/**\n * Subscribes to audio route changed events.\n *\n * Fired when the audio route changes (e.g., user connects Bluetooth headphones,\n * toggles speaker mode).\n *\n * @param listener - Callback invoked when audio route changes.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Audio Event Listener\n */\nexport function addAudioRouteChangedListener(\n listener: (event: AudioRouteChangedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onAudioRouteChanged\", listener);\n}\n\n// ============================================================================\n// Call Intent Event Listeners\n// ============================================================================\n\n/**\n * Subscribes to call intent received events.\n *\n * Fired when the user initiates a call from outside the app, such as tapping\n * a contact in the iOS Recents list or via Siri. The event contains the handle\n * (phone number/email) and whether video is requested.\n *\n * The app should resolve the handle to a known recipient and call\n * {@link startOutgoingCall} to fulfill the intent.\n *\n * @param listener - Callback invoked when a call intent is received.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addCallIntentReceivedListener(\n listener: (event: CallIntentReceivedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onCallIntentReceived\", listener);\n}\n\n// ============================================================================\n// Start Outgoing Call\n// ============================================================================\n\n/**\n * Starts an outgoing call to the specified recipient.\n *\n * This requests the system to initiate a call. The system will display the\n * appropriate call UI and emit an {@link OutgoingCallStartedEvent} when you should\n * begin connecting your media.\n *\n * @param recipient - The participant to call.\n * @param options - Call configuration options (e.g., video enabled).\n * @returns The unique identifier for this call session.\n *\n * @example\n * ```typescript\n * const callId = await startOutgoingCall(\n * { id: 'user-123', displayName: 'John Doe' },\n * { hasVideo: true }\n * );\n * ```\n *\n * @category Request\n */\nexport async function startOutgoingCall(\n recipient: CallParticipant,\n options: CallOptions,\n): Promise<string> {\n return await ExpoCallKitTelecomModule.startOutgoingCall(recipient, options);\n}\n\n/**\n * Subscribes to outgoing call started events.\n *\n * Fired when an outgoing call (initiated via {@link startOutgoingCall}) has\n * been accepted by the system. You should provision your media connection\n * and begin connecting.\n *\n * @param listener - Callback invoked when an outgoing call starts.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addOutgoingCallStartedListener(\n listener: (event: OutgoingCallStartedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onOutgoingCallStarted\", listener);\n}\n\n// ============================================================================\n// Report Incoming Call\n// ============================================================================\n\n/**\n * Reports an incoming call to the system.\n *\n * Call this when you receive a push notification or other signal indicating\n * an incoming call. The system will display the incoming call UI.\n *\n * @param event - The incoming call event containing caller information.\n *\n * @example\n * ```typescript\n * await reportIncomingCall({\n * callId: '550e8400-e29b-41d4-a716-446655440000',\n * caller: {\n * id: 'user-456',\n * displayName: 'Jane Smith',\n * phoneNumber: '+1234567890',\n * },\n * hasVideo: false,\n * startedAt: new Date(),\n * });\n * ```\n *\n * @category Reporter\n */\nexport async function reportIncomingCall(\n event: IncomingCallEvent,\n): Promise<void> {\n await ExpoCallKitTelecomModule.reportIncomingCall(event);\n}\n\n/**\n * Subscribes to incoming call reported events.\n *\n * Fired after an incoming call has been successfully reported to the system\n * and the call session has been added to the store. Use this to set up\n * early subscriptions (e.g., call signaling) before the call is answered.\n *\n * @param listener - Callback invoked when an incoming call is reported.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addIncomingCallReportedListener(\n listener: (event: IncomingCallReportedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onIncomingCallReported\", listener);\n}\n\n// ============================================================================\n// Answer Call\n// ============================================================================\n\n/**\n * Answers an incoming call.\n *\n * Use this when the user taps an answer button in your app's custom UI.\n * The system will emit a {@link CallAnsweredEvent} to confirm the answer.\n *\n * @param id - The call session ID to answer.\n *\n * @category Request\n */\nexport async function answerCall(id: string): Promise<void> {\n await ExpoCallKitTelecomModule.answerCall(id);\n}\n\n/**\n * Subscribes to call answered events.\n *\n * Fired when the user answers an incoming call (either from the system UI or\n * via {@link answerCall}). You should begin connecting your media.\n *\n * @param listener - Callback invoked when a call is answered.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addCallAnsweredListener(\n listener: (event: CallAnsweredEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onCallAnswered\", listener);\n}\n\n// ============================================================================\n// Fulfill Incoming Call\n// ============================================================================\n\n/**\n * Fulfills an incoming call by confirming the media connection is established.\n *\n * Call this after the user answers an incoming call and your media connection\n * (e.g., WebRTC) is fully connected and ready for audio/video.\n *\n * @param requestId - The request ID from the CallAnsweredEvent.\n *\n * @category Fulfiller\n */\nexport async function fulfillIncomingCallConnected(\n requestId: string,\n): Promise<void> {\n await ExpoCallKitTelecomModule.fulfillIncomingCallAnswered(requestId);\n}\n\n/**\n * Fails a pending incoming call connection request.\n *\n * Call this when the answer flow fails before media is connected\n * (e.g., API error). On iOS, causes CXAnswerCallAction to fail, which\n * triggers CallKit to end the call via CXEndCallAction. On Android,\n * ends the call via {@link reportCallEnded} which also cancels any\n * pending fulfill request.\n *\n * @param id - The call session ID.\n * @param requestId - The request ID from the CallAnsweredEvent.\n *\n * @category Fulfiller\n */\nexport async function failIncomingCallConnected(\n id: string,\n requestId: string,\n): Promise<void> {\n if (Platform.OS === \"ios\") {\n await ExpoCallKitTelecomModule.failIncomingCallConnected(requestId);\n } else {\n await ExpoCallKitTelecomModule.reportCallEnded(id, \"failed\");\n }\n}\n\n// ============================================================================\n// Report Outgoing Call Connected\n// ============================================================================\n\n/**\n * Reports that an outgoing call's media connection is established.\n *\n * Call this after starting an outgoing call and your media connection\n * (e.g., WebRTC) is fully connected and the remote party has answered.\n *\n * @param id - The call session ID.\n *\n * @category Reporter\n */\nexport async function reportOutgoingCallConnected(id: string): Promise<void> {\n await ExpoCallKitTelecomModule.reportOutgoingCallConnected(id);\n}\n\n// ============================================================================\n// End Call\n// ============================================================================\n\n/**\n * Ends an active call.\n *\n * Requests the system to end the call. The system will emit a {@link CallEndedEvent}\n * to notify that the call has ended. Clean up your media connection when you receive\n * this event.\n *\n * @param id - The call session ID to end.\n *\n * @category Request\n */\nexport async function endCall(id: string): Promise<void> {\n await ExpoCallKitTelecomModule.endCall(id);\n}\n\n/**\n * Subscribes to call ended events.\n *\n * Fired when a call has ended (e.g., user pressed end button).\n * Clean up your media connection when you receive this event.\n *\n * @param listener - Callback invoked when a call ends.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addCallEndedListener(\n listener: (event: CallEndedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onCallEnded\", listener);\n}\n\n/**\n * Reports that a call has ended for an external reason.\n *\n * Use this when a call ends due to reasons outside the local user's control,\n * such as: remote party hung up, network failure, call declined elsewhere, etc.\n *\n * @param id - The call session ID.\n * @param reason - The reason the call ended.\n *\n * @example\n * ```typescript\n * // Remote party hung up\n * await reportCallEnded(callId, 'remoteEnded');\n *\n * // Call failed due to network error\n * await reportCallEnded(callId, 'failed');\n * ```\n *\n * @category Reporter\n */\nexport async function reportCallEnded(\n id: string,\n reason: CallEndedReason,\n): Promise<void> {\n await ExpoCallKitTelecomModule.reportCallEnded(id, reason);\n}\n\n/**\n * Subscribes to reported call ended events.\n *\n * Fired after {@link reportCallEnded} is called, confirming the system has\n * been notified of the externally-ended call.\n *\n * @param listener - Callback invoked when a call end is reported.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addReportedCallEndedListener(\n listener: (event: CallReportedEnded) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onCallReportedEnded\", listener);\n}\n\n// ============================================================================\n// Mute Support\n// ============================================================================\n\n/**\n * Changes the mute state of a call.\n *\n * The system will emit a {@link SetMutedActionEvent}. Apply the mute state to\n * your media connection when you receive this event.\n *\n * @param id - The call session ID.\n * @param muted - Whether the microphone should be muted.\n *\n * @category Request\n */\nexport async function setMuted(id: string, muted: boolean): Promise<void> {\n await ExpoCallKitTelecomModule.setMuted(id, muted);\n}\n\n/**\n * Subscribes to set muted action events.\n *\n * Fired when the system requests to set the mute state (e.g., user pressed mute button).\n * Apply the change to your media connection when you receive this event.\n *\n * @param listener - Callback invoked when set muted action is requested.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addSetMutedActionListener(\n listener: (event: SetMutedActionEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onSetMutedAction\", listener);\n}\n\n// ============================================================================\n// Video Support\n// ============================================================================\n\n/**\n * Reports a video state change for a call.\n *\n * Use this to inform the system when video is enabled or disabled.\n *\n * @param id - The call session ID.\n * @param enabled - Whether video is enabled.\n *\n * @category Reporter\n */\nexport async function reportVideo(id: string, enabled: boolean): Promise<void> {\n await ExpoCallKitTelecomModule.reportVideo(id, enabled);\n}\n\n/**\n * Subscribes to video state change events.\n *\n * Fired when the video state changes for a call.\n *\n * @param listener - Callback invoked when video state changes.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addVideoChangedListener(\n listener: (event: VideoChangedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onVideoChanged\", listener);\n}\n\n// ============================================================================\n// Hold Support\n// ============================================================================\n\n/**\n * Changes the hold state of a call.\n *\n * The system will emit a {@link SetHeldActionEvent}. Apply the hold state to\n * your media connection when you receive this event.\n *\n * @param id - The call session ID.\n * @param onHold - Whether the call should be on hold.\n *\n * @category Request\n */\nexport async function setHeld(id: string, onHold: boolean): Promise<void> {\n await ExpoCallKitTelecomModule.setHeld(id, onHold);\n}\n\n/**\n * Subscribes to set held action events.\n *\n * Fired when the system requests to set the hold state. Apply the change to\n * your media connection when you receive this event.\n *\n * @param listener - Callback invoked when set held action is requested.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addSetHeldActionListener(\n listener: (event: SetHeldActionEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onSetHeldAction\", listener);\n}\n\n// ============================================================================\n// DTMF Support\n// ============================================================================\n\n/**\n * Plays DTMF tones during a call.\n *\n * The system will emit a {@link DTMFEvent}. Send the tones through your media\n * connection when you receive this event.\n *\n * @param id - The call session ID.\n * @param digits - The DTMF digits to play (0-9, *, #).\n *\n * @category Request\n */\nexport async function playDTMF(id: string, digits: string): Promise<void> {\n await ExpoCallKitTelecomModule.playDTMF(id, digits);\n}\n\n/**\n * Subscribes to DTMF events.\n *\n * Fired when DTMF tones should be played. Send the tones through your media\n * connection when you receive this event.\n *\n * @param listener - Callback invoked when DTMF tones should be played.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @category Event Listener\n */\nexport function addDTMFListener(\n listener: (event: DTMFEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onDTMF\", listener);\n}\n\n// ============================================================================\n// VoIP Push\n// ============================================================================\n\n/**\n * Registers for VoIP push notifications.\n *\n * Call this early in your app lifecycle to receive VoIP push notifications\n * for incoming calls. Once registered, the device token will be available\n * via {@link getVoIPPushToken} and token updates will be emitted via\n * {@link addVoIPPushTokenUpdatedListener}.\n *\n * @example\n * ```typescript\n * // Register early in app initialization\n * registerVoIPPush();\n *\n * // Listen for token updates\n * addVoIPPushTokenUpdatedListener((event) => {\n * if (event.token) {\n * // Send token to your backend\n * sendTokenToBackend(event.token);\n * }\n * });\n * ```\n *\n * @category VoIP Push\n */\nexport function registerVoIPPush(): void {\n ExpoCallKitTelecomModule.registerVoIPPush();\n}\n\n/**\n * Gets the current VoIP push token and its type.\n *\n * The token should be sent to your backend along with the token type\n * so the server knows how to deliver incoming call pushes.\n *\n * @returns The VoIP push token bundled with its type, or null if not yet registered.\n *\n * @example\n * ```typescript\n * const voip = getVoIPPushToken();\n * if (voip) {\n * await sendTokenToBackend(voip.token, voip.type);\n * }\n * ```\n *\n * @category VoIP Push\n */\nexport function getVoIPPushToken(): VoIPPushToken | null {\n const result = ExpoCallKitTelecomModule.getVoIPPushToken();\n if (!result.token) return null;\n return {\n token: result.token,\n type: result.type as PushTokenType,\n };\n}\n\n/**\n * Subscribes to VoIP token updated events.\n *\n * Fired when the VoIP push token is received or updated after calling\n * {@link registerVoIPPush}. Also fired if the token is invalidated (with\n * `token` being `undefined`).\n *\n * @param listener - Callback invoked when the VoIP token updates.\n * @returns A subscription that can be removed by calling `.remove()`.\n *\n * @example\n * ```typescript\n * const subscription = addVoIPPushTokenUpdatedListener((event) => {\n * if (event.token) {\n * console.log('New VoIP token:', event.token);\n * sendTokenToBackend(event.token);\n * } else {\n * console.log('VoIP token invalidated');\n * }\n * });\n * ```\n *\n * @category VoIP Push Event Listener\n */\nexport function addVoIPPushTokenUpdatedListener(\n listener: (event: VoIPPushTokenUpdatedEvent) => void,\n): EventSubscription {\n return ExpoCallKitTelecomModule.addListener(\"onVoIPPushTokenUpdated\", listener);\n}\n"]}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type of VoIP push token reported by `getVoIPPushToken`.
|
|
3
|
+
*
|
|
4
|
+
* - `"APNS_VOIP"` — Apple Push Notification service VoIP channel (iOS)
|
|
5
|
+
* - `"FCM"` — Firebase Cloud Messaging (Android)
|
|
6
|
+
*/
|
|
7
|
+
export type PushTokenType = "APNS_VOIP" | "FCM";
|
|
8
|
+
/** Metadata attached to all native events */
|
|
9
|
+
export interface NativeEventMeta {
|
|
10
|
+
/** Whether the event was flushed from queue (true) or sent in real-time (false) */
|
|
11
|
+
flushed: boolean;
|
|
12
|
+
/** ISO8601 timestamp of when the event was created */
|
|
13
|
+
timestamp: string;
|
|
14
|
+
}
|
|
15
|
+
/** Base type for all native events with metadata */
|
|
16
|
+
export interface NativeEvent {
|
|
17
|
+
meta: NativeEventMeta;
|
|
18
|
+
}
|
|
19
|
+
export interface CallSession {
|
|
20
|
+
id: string;
|
|
21
|
+
options: CallOptions;
|
|
22
|
+
origin: CallSessionOrigin;
|
|
23
|
+
remoteParticipants: CallParticipant[];
|
|
24
|
+
incomingCallEvent?: IncomingCallEvent;
|
|
25
|
+
status: CallSessionStatus;
|
|
26
|
+
connectedAt?: string;
|
|
27
|
+
isMuted: boolean;
|
|
28
|
+
isOnHold: boolean;
|
|
29
|
+
dtmfDigits?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface CallOptions {
|
|
32
|
+
hasVideo: boolean;
|
|
33
|
+
}
|
|
34
|
+
export type CallSessionOrigin = "incoming" | "outgoingApp" | "outgoingSystem";
|
|
35
|
+
export interface CallParticipant {
|
|
36
|
+
/** Opaque, stable app identifier for this participant. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Display name. */
|
|
39
|
+
displayName?: string;
|
|
40
|
+
/** Avatar URL. */
|
|
41
|
+
avatarUrl?: string;
|
|
42
|
+
/** Phone number in E.164 (e.g. "+14155551234"). When present on iOS, the
|
|
43
|
+
* CallKit handle is set to this number, enabling Recents and Siri. */
|
|
44
|
+
phoneNumber?: string;
|
|
45
|
+
/** Email address. */
|
|
46
|
+
email?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Call session status representing the lifecycle of a call.
|
|
50
|
+
*
|
|
51
|
+
* Outgoing call flow: requesting → connecting → connected → ended
|
|
52
|
+
* Incoming call flow: ringing → connecting → connected → ended
|
|
53
|
+
*
|
|
54
|
+
* - `requesting` — Outgoing only. The call request has been submitted to
|
|
55
|
+
* CallKit/Telecom and is awaiting system acceptance.
|
|
56
|
+
* - `ringing` — Incoming only. The call has been reported to CallKit/Telecom
|
|
57
|
+
* and the user sees the native incoming call UI or notification.
|
|
58
|
+
* - `connecting` — Both directions. For outgoing calls, the system accepted the
|
|
59
|
+
* call and the dialtone is playing while waiting for the remote party to answer.
|
|
60
|
+
* For incoming calls, the user answered and media is being established.
|
|
61
|
+
* - `connected` — Both directions. Media is flowing and the call is active.
|
|
62
|
+
* - `ended` — Both directions. Transient state during teardown before the
|
|
63
|
+
* session is removed from the store.
|
|
64
|
+
*/
|
|
65
|
+
export type CallSessionStatus = "requesting" | "connecting" | "ringing" | "connected" | "ended";
|
|
66
|
+
export interface CallSessionAddedEvent extends NativeEvent {
|
|
67
|
+
session: CallSession;
|
|
68
|
+
}
|
|
69
|
+
export interface CallSessionUpdatedEvent extends NativeEvent {
|
|
70
|
+
session: CallSession;
|
|
71
|
+
}
|
|
72
|
+
export interface CallSessionRemovedEvent extends NativeEvent {
|
|
73
|
+
id: string;
|
|
74
|
+
}
|
|
75
|
+
export type PermissionStatus = "granted" | "denied" | "undetermined" | "restricted" | "unknown";
|
|
76
|
+
export interface AudioSession {
|
|
77
|
+
isActive: boolean;
|
|
78
|
+
/** iOS only: whether the WebRTC RTCAudioSession is active. */
|
|
79
|
+
rtcSessionIsActive?: boolean;
|
|
80
|
+
/** iOS only: whether the AVAudioSession is active. */
|
|
81
|
+
avSessionIsActive?: boolean;
|
|
82
|
+
/** iOS only: whether the RTCAudioSession audio track is enabled. */
|
|
83
|
+
isAudioEnabled?: boolean;
|
|
84
|
+
/** iOS only: whether manual audio mode is enabled on RTCAudioSession. */
|
|
85
|
+
useManualAudio?: boolean;
|
|
86
|
+
isOtherAudioPlaying: boolean;
|
|
87
|
+
category: string;
|
|
88
|
+
mode: string;
|
|
89
|
+
/** iOS only: AVAudioSession category options. */
|
|
90
|
+
categoryOptions?: string[];
|
|
91
|
+
sampleRate: number;
|
|
92
|
+
ioBufferDuration: number;
|
|
93
|
+
inputNumberOfChannels: number;
|
|
94
|
+
outputNumberOfChannels: number;
|
|
95
|
+
microphonePermission: PermissionStatus;
|
|
96
|
+
currentRoute: AudioRoute;
|
|
97
|
+
/** Available audio output devices. Populated on Android; undefined on iOS. */
|
|
98
|
+
availableRoutes?: AudioPort[];
|
|
99
|
+
}
|
|
100
|
+
export interface AudioRoute {
|
|
101
|
+
inputs: AudioPort[];
|
|
102
|
+
outputs: AudioPort[];
|
|
103
|
+
}
|
|
104
|
+
export interface AudioPort {
|
|
105
|
+
portType: AudioOutputPortType;
|
|
106
|
+
portName: string;
|
|
107
|
+
uid: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Cross-platform audio output port type identifiers.
|
|
111
|
+
* Both iOS and Android map their native audio device types to these shared values.
|
|
112
|
+
*/
|
|
113
|
+
export type AudioOutputPortType = "builtInReceiver" | "builtInSpeaker" | "headphones" | "bluetoothA2DP" | "bluetoothLE" | "bluetoothHFP" | "airPlay" | "hdmi" | "carAudio" | "usbAudio" | "lineOut" | (string & {});
|
|
114
|
+
export interface AudioSessionCallInfo {
|
|
115
|
+
id: string;
|
|
116
|
+
status: CallSessionStatus;
|
|
117
|
+
}
|
|
118
|
+
export interface AudioSessionActivatedEvent extends NativeEvent {
|
|
119
|
+
calls: AudioSessionCallInfo[];
|
|
120
|
+
}
|
|
121
|
+
export interface AudioSessionDeactivatedEvent extends NativeEvent {
|
|
122
|
+
calls: AudioSessionCallInfo[];
|
|
123
|
+
}
|
|
124
|
+
export interface AudioRouteChangedEvent extends NativeEvent {
|
|
125
|
+
currentRoute: AudioRoute;
|
|
126
|
+
/** Available audio output devices. Populated on Android; undefined on iOS. */
|
|
127
|
+
availableRoutes?: AudioPort[];
|
|
128
|
+
}
|
|
129
|
+
export interface CaptureSession {
|
|
130
|
+
cameraPermission: PermissionStatus;
|
|
131
|
+
/** Whether the device supports multitasking camera access (iOS 16+). */
|
|
132
|
+
isMultitaskingCameraAccessSupported?: boolean;
|
|
133
|
+
}
|
|
134
|
+
export interface CallActionEvent extends NativeEvent {
|
|
135
|
+
id: string;
|
|
136
|
+
}
|
|
137
|
+
export interface OutgoingCallStartedEvent extends CallActionEvent {
|
|
138
|
+
}
|
|
139
|
+
export interface IncomingCallEvent {
|
|
140
|
+
/** Unique event identifier (UUID). Used for dedup. */
|
|
141
|
+
eventId: string;
|
|
142
|
+
/** Your backend's id for this call. Distinct from {@link CallSession.id},
|
|
143
|
+
* which is the OS-assigned native call UUID. Use this id to talk to your
|
|
144
|
+
* server about the call (e.g. POST /calls/:serverCallId/answer). */
|
|
145
|
+
serverCallId: string;
|
|
146
|
+
/** True for video calls, false for audio. */
|
|
147
|
+
hasVideo: boolean;
|
|
148
|
+
/** RFC 3339 timestamp of when the call was placed. Optional; defaults to now. */
|
|
149
|
+
startedAt?: string;
|
|
150
|
+
/** Caller identity and addressing. */
|
|
151
|
+
caller: CallParticipant;
|
|
152
|
+
/**
|
|
153
|
+
* App-defined extra fields, forwarded verbatim from the push payload.
|
|
154
|
+
*
|
|
155
|
+
* The library treats this as opaque — put whatever your app needs here
|
|
156
|
+
* (chatId, tenantId, room name, etc.). Cast to your own type at the
|
|
157
|
+
* read site.
|
|
158
|
+
*/
|
|
159
|
+
metadata?: Record<string, unknown>;
|
|
160
|
+
}
|
|
161
|
+
export interface IncomingCallReportedEvent extends CallActionEvent {
|
|
162
|
+
}
|
|
163
|
+
export interface CallAnsweredEvent extends CallActionEvent {
|
|
164
|
+
requestId: string;
|
|
165
|
+
}
|
|
166
|
+
export interface CallEndedEvent extends CallActionEvent {
|
|
167
|
+
}
|
|
168
|
+
export type CallEndedReason = "failed" | "remoteEnded" | "unanswered" | "answeredElsewhere" | "declinedElsewhere" | "unknown";
|
|
169
|
+
export interface CallReportedEnded extends CallActionEvent {
|
|
170
|
+
reason: CallEndedReason;
|
|
171
|
+
}
|
|
172
|
+
export interface SetMutedActionEvent extends CallActionEvent {
|
|
173
|
+
isMuted: boolean;
|
|
174
|
+
}
|
|
175
|
+
export interface VideoChangedEvent extends CallActionEvent {
|
|
176
|
+
hasVideo: boolean;
|
|
177
|
+
}
|
|
178
|
+
export interface SetHeldActionEvent extends CallActionEvent {
|
|
179
|
+
isOnHold: boolean;
|
|
180
|
+
}
|
|
181
|
+
export interface DTMFEvent extends CallActionEvent {
|
|
182
|
+
digits: string;
|
|
183
|
+
}
|
|
184
|
+
export type CallIntentHandleType = "phoneNumber" | "email" | "unknown";
|
|
185
|
+
export interface CallIntentReceivedEvent extends NativeEvent {
|
|
186
|
+
handle: string;
|
|
187
|
+
handleType: CallIntentHandleType;
|
|
188
|
+
hasVideo: boolean;
|
|
189
|
+
}
|
|
190
|
+
/** A VoIP push token bundled with its type. */
|
|
191
|
+
export interface VoIPPushToken {
|
|
192
|
+
/** The VoIP push token string. */
|
|
193
|
+
token: string;
|
|
194
|
+
/** The type of token this platform provides. */
|
|
195
|
+
type: PushTokenType;
|
|
196
|
+
}
|
|
197
|
+
export interface VoIPPushTokenUpdatedEvent extends NativeEvent {
|
|
198
|
+
/** The VoIP push token string, or undefined if invalidated */
|
|
199
|
+
token?: string;
|
|
200
|
+
/** The type of VoIP push token (e.g. "APNS_VOIP", "FCM"). */
|
|
201
|
+
type: PushTokenType;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=Calls.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calls.types.d.ts","sourceRoot":"","sources":["../src/Calls.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Calls.types.js","sourceRoot":"","sources":["../src/Calls.types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Type of VoIP push token reported by `getVoIPPushToken`.\n *\n * - `\"APNS_VOIP\"` — Apple Push Notification service VoIP channel (iOS)\n * - `\"FCM\"` — Firebase Cloud Messaging (Android)\n */\nexport type PushTokenType = \"APNS_VOIP\" | \"FCM\";\n\n// Native Event Metadata\n\n/** Metadata attached to all native events */\nexport interface NativeEventMeta {\n /** Whether the event was flushed from queue (true) or sent in real-time (false) */\n flushed: boolean;\n /** ISO8601 timestamp of when the event was created */\n timestamp: string;\n}\n\n/** Base type for all native events with metadata */\nexport interface NativeEvent {\n meta: NativeEventMeta;\n}\n\n// Call Session\nexport interface CallSession {\n id: string;\n options: CallOptions;\n origin: CallSessionOrigin;\n remoteParticipants: CallParticipant[];\n incomingCallEvent?: IncomingCallEvent;\n status: CallSessionStatus;\n connectedAt?: string;\n isMuted: boolean;\n isOnHold: boolean;\n dtmfDigits?: string;\n}\n\nexport interface CallOptions {\n hasVideo: boolean;\n}\n\nexport type CallSessionOrigin = \"incoming\" | \"outgoingApp\" | \"outgoingSystem\";\n\nexport interface CallParticipant {\n /** Opaque, stable app identifier for this participant. */\n id: string;\n /** Display name. */\n displayName?: string;\n /** Avatar URL. */\n avatarUrl?: string;\n /** Phone number in E.164 (e.g. \"+14155551234\"). When present on iOS, the\n * CallKit handle is set to this number, enabling Recents and Siri. */\n phoneNumber?: string;\n /** Email address. */\n email?: string;\n}\n\n/**\n * Call session status representing the lifecycle of a call.\n *\n * Outgoing call flow: requesting → connecting → connected → ended\n * Incoming call flow: ringing → connecting → connected → ended\n *\n * - `requesting` — Outgoing only. The call request has been submitted to\n * CallKit/Telecom and is awaiting system acceptance.\n * - `ringing` — Incoming only. The call has been reported to CallKit/Telecom\n * and the user sees the native incoming call UI or notification.\n * - `connecting` — Both directions. For outgoing calls, the system accepted the\n * call and the dialtone is playing while waiting for the remote party to answer.\n * For incoming calls, the user answered and media is being established.\n * - `connected` — Both directions. Media is flowing and the call is active.\n * - `ended` — Both directions. Transient state during teardown before the\n * session is removed from the store.\n */\nexport type CallSessionStatus =\n | \"requesting\"\n | \"connecting\"\n | \"ringing\"\n | \"connected\"\n | \"ended\";\n\n// Call Session events\nexport interface CallSessionAddedEvent extends NativeEvent {\n session: CallSession;\n}\n\nexport interface CallSessionUpdatedEvent extends NativeEvent {\n session: CallSession;\n}\n\nexport interface CallSessionRemovedEvent extends NativeEvent {\n id: string;\n}\n\n// Microphone/Camera Permission Status\nexport type PermissionStatus =\n | \"granted\"\n | \"denied\"\n | \"undetermined\"\n | \"restricted\"\n | \"unknown\";\n\n// Audio Session\n\nexport interface AudioSession {\n isActive: boolean;\n /** iOS only: whether the WebRTC RTCAudioSession is active. */\n rtcSessionIsActive?: boolean;\n /** iOS only: whether the AVAudioSession is active. */\n avSessionIsActive?: boolean;\n /** iOS only: whether the RTCAudioSession audio track is enabled. */\n isAudioEnabled?: boolean;\n /** iOS only: whether manual audio mode is enabled on RTCAudioSession. */\n useManualAudio?: boolean;\n isOtherAudioPlaying: boolean;\n category: string;\n mode: string;\n /** iOS only: AVAudioSession category options. */\n categoryOptions?: string[];\n sampleRate: number;\n ioBufferDuration: number;\n inputNumberOfChannels: number;\n outputNumberOfChannels: number;\n microphonePermission: PermissionStatus;\n currentRoute: AudioRoute;\n /** Available audio output devices. Populated on Android; undefined on iOS. */\n availableRoutes?: AudioPort[];\n}\n\nexport interface AudioRoute {\n inputs: AudioPort[];\n outputs: AudioPort[];\n}\n\nexport interface AudioPort {\n portType: AudioOutputPortType;\n portName: string;\n uid: string;\n}\n\n/**\n * Cross-platform audio output port type identifiers.\n * Both iOS and Android map their native audio device types to these shared values.\n */\nexport type AudioOutputPortType =\n | \"builtInReceiver\" // Earpiece\n | \"builtInSpeaker\" // Speaker\n | \"headphones\" // Wired headphones\n | \"bluetoothA2DP\" // Bluetooth A2DP audio\n | \"bluetoothLE\" // Bluetooth Low Energy audio\n | \"bluetoothHFP\" // Bluetooth Hands-Free Profile\n | \"airPlay\" // AirPlay\n | \"hdmi\" // HDMI output\n | \"carAudio\" // CarPlay\n | \"usbAudio\" // USB audio\n | \"lineOut\" // Line out\n | (string & {}); // Allow other unknown port types\n\n// Audio Session Events\nexport interface AudioSessionCallInfo {\n id: string;\n status: CallSessionStatus;\n}\n\nexport interface AudioSessionActivatedEvent extends NativeEvent {\n calls: AudioSessionCallInfo[];\n}\n\nexport interface AudioSessionDeactivatedEvent extends NativeEvent {\n calls: AudioSessionCallInfo[];\n}\n\nexport interface AudioRouteChangedEvent extends NativeEvent {\n currentRoute: AudioRoute;\n /** Available audio output devices. Populated on Android; undefined on iOS. */\n availableRoutes?: AudioPort[];\n}\n\n// Capture Session\nexport interface CaptureSession {\n cameraPermission: PermissionStatus;\n /** Whether the device supports multitasking camera access (iOS 16+). */\n isMultitaskingCameraAccessSupported?: boolean;\n}\n\n// Call Action events\nexport interface CallActionEvent extends NativeEvent {\n id: string;\n}\n\nexport interface OutgoingCallStartedEvent extends CallActionEvent {}\n\nexport interface IncomingCallEvent {\n /** Unique event identifier (UUID). Used for dedup. */\n eventId: string;\n /** Your backend's id for this call. Distinct from {@link CallSession.id},\n * which is the OS-assigned native call UUID. Use this id to talk to your\n * server about the call (e.g. POST /calls/:serverCallId/answer). */\n serverCallId: string;\n /** True for video calls, false for audio. */\n hasVideo: boolean;\n /** RFC 3339 timestamp of when the call was placed. Optional; defaults to now. */\n startedAt?: string;\n /** Caller identity and addressing. */\n caller: CallParticipant;\n /**\n * App-defined extra fields, forwarded verbatim from the push payload.\n *\n * The library treats this as opaque — put whatever your app needs here\n * (chatId, tenantId, room name, etc.). Cast to your own type at the\n * read site.\n */\n metadata?: Record<string, unknown>;\n}\n\nexport interface IncomingCallReportedEvent extends CallActionEvent {}\n\nexport interface CallAnsweredEvent extends CallActionEvent {\n requestId: string;\n}\n\nexport interface CallEndedEvent extends CallActionEvent {}\n\nexport type CallEndedReason =\n | \"failed\"\n | \"remoteEnded\"\n | \"unanswered\"\n | \"answeredElsewhere\"\n | \"declinedElsewhere\"\n | \"unknown\";\n\nexport interface CallReportedEnded extends CallActionEvent {\n reason: CallEndedReason;\n}\nexport interface SetMutedActionEvent extends CallActionEvent {\n isMuted: boolean;\n}\nexport interface VideoChangedEvent extends CallActionEvent {\n hasVideo: boolean;\n}\nexport interface SetHeldActionEvent extends CallActionEvent {\n isOnHold: boolean;\n}\nexport interface DTMFEvent extends CallActionEvent {\n digits: string;\n}\n\n// Call Intent Events\n\nexport type CallIntentHandleType = \"phoneNumber\" | \"email\" | \"unknown\";\n\nexport interface CallIntentReceivedEvent extends NativeEvent {\n handle: string;\n handleType: CallIntentHandleType;\n hasVideo: boolean;\n}\n\n// VoIP Push\n\n/** A VoIP push token bundled with its type. */\nexport interface VoIPPushToken {\n /** The VoIP push token string. */\n token: string;\n /** The type of token this platform provides. */\n type: PushTokenType;\n}\n\n// VoIP Push Events\n\nexport interface VoIPPushTokenUpdatedEvent extends NativeEvent {\n /** The VoIP push token string, or undefined if invalidated */\n token?: string;\n /** The type of VoIP push token (e.g. \"APNS_VOIP\", \"FCM\"). */\n type: PushTokenType;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoCallKitTelecomModule.d.ts","sourceRoot":"","sources":["../src/ExpoCallKitTelecomModule.ts"],"names":[],"mappings":";AAGA,wBAAyD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpoCallKitTelecomModule.js","sourceRoot":"","sources":["../src/ExpoCallKitTelecomModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAE3C,yDAAyD;AACzD,eAAe,mBAAmB,CAAC,oBAAoB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from \"expo\";\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule(\"ExpoCallKitTelecom\");\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC","sourcesContent":["export * from \"./useVoIPPushToken\";\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { VoIPPushToken } from "../Calls.types";
|
|
2
|
+
/**
|
|
3
|
+
* Hook that returns the current VoIP push token and subscribes to updates.
|
|
4
|
+
*
|
|
5
|
+
* Reads the initial token synchronously and re-renders whenever the native
|
|
6
|
+
* `onVoIPPushTokenUpdated` event fires (e.g. when the OS provides a new token
|
|
7
|
+
* or invalidates the existing one).
|
|
8
|
+
*
|
|
9
|
+
* On iOS this returns an APNs VoIP token; on Android it returns an FCM token.
|
|
10
|
+
*
|
|
11
|
+
* @returns The current token, or `null` if not yet available.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useVoIPPushToken(): VoIPPushToken | null;
|
|
14
|
+
//# sourceMappingURL=useVoIPPushToken.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVoIPPushToken.d.ts","sourceRoot":"","sources":["../../src/hooks/useVoIPPushToken.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAiBvD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { addVoIPPushTokenUpdatedListener, getVoIPPushToken } from "../Calls";
|
|
3
|
+
/**
|
|
4
|
+
* Hook that returns the current VoIP push token and subscribes to updates.
|
|
5
|
+
*
|
|
6
|
+
* Reads the initial token synchronously and re-renders whenever the native
|
|
7
|
+
* `onVoIPPushTokenUpdated` event fires (e.g. when the OS provides a new token
|
|
8
|
+
* or invalidates the existing one).
|
|
9
|
+
*
|
|
10
|
+
* On iOS this returns an APNs VoIP token; on Android it returns an FCM token.
|
|
11
|
+
*
|
|
12
|
+
* @returns The current token, or `null` if not yet available.
|
|
13
|
+
*/
|
|
14
|
+
export function useVoIPPushToken() {
|
|
15
|
+
const [token, setToken] = useState(() => getVoIPPushToken());
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const subscription = addVoIPPushTokenUpdatedListener((event) => {
|
|
18
|
+
setToken(event.token
|
|
19
|
+
? { token: event.token, type: event.type }
|
|
20
|
+
: null);
|
|
21
|
+
});
|
|
22
|
+
return () => subscription.remove();
|
|
23
|
+
}, []);
|
|
24
|
+
return token;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=useVoIPPushToken.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVoIPPushToken.js","sourceRoot":"","sources":["../../src/hooks/useVoIPPushToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG7E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAuB,GAAG,EAAE,CAC5D,gBAAgB,EAAE,CACnB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,YAAY,GAAG,+BAA+B,CAAC,CAAC,KAAK,EAAE,EAAE;YAC7D,QAAQ,CACN,KAAK,CAAC,KAAK;gBACT,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAqB,EAAE;gBAC3D,CAAC,CAAC,IAAI,CACT,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport { addVoIPPushTokenUpdatedListener, getVoIPPushToken } from \"../Calls\";\nimport type { PushTokenType, VoIPPushToken } from \"../Calls.types\";\n\n/**\n * Hook that returns the current VoIP push token and subscribes to updates.\n *\n * Reads the initial token synchronously and re-renders whenever the native\n * `onVoIPPushTokenUpdated` event fires (e.g. when the OS provides a new token\n * or invalidates the existing one).\n *\n * On iOS this returns an APNs VoIP token; on Android it returns an FCM token.\n *\n * @returns The current token, or `null` if not yet available.\n */\nexport function useVoIPPushToken(): VoIPPushToken | null {\n const [token, setToken] = useState<VoIPPushToken | null>(() =>\n getVoIPPushToken(),\n );\n\n useEffect(() => {\n const subscription = addVoIPPushTokenUpdatedListener((event) => {\n setToken(\n event.token\n ? { token: event.token, type: event.type as PushTokenType }\n : null,\n );\n });\n return () => subscription.remove();\n }, []);\n\n return token;\n}\n"]}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC","sourcesContent":["export * from \"./Calls\";\nexport * from \"./Calls.types\";\nexport * from \"./hooks\";\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"platforms": ["apple", "android"],
|
|
3
|
+
"apple": {
|
|
4
|
+
"modules": ["ExpoCallKitTelecomModule"],
|
|
5
|
+
"appDelegateSubscribers": ["ExpoCallKitTelecomAppDelegateSubscriber"]
|
|
6
|
+
},
|
|
7
|
+
"android": {
|
|
8
|
+
"modules": ["expo.modules.callkittelecom.ExpoCallKitTelecomModule"]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import Intents
|
|
3
|
+
|
|
4
|
+
public class ExpoCallKitTelecomAppDelegateSubscriber: ExpoAppDelegateSubscriber {
|
|
5
|
+
public func application(
|
|
6
|
+
_ application: UIApplication,
|
|
7
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
|
|
8
|
+
) -> Bool {
|
|
9
|
+
// Pre-warm session managers at app launch, before any calls
|
|
10
|
+
_ = AudioManager.shared
|
|
11
|
+
_ = CaptureSessionManager.shared
|
|
12
|
+
|
|
13
|
+
// Register for VoIP push so we can receive pushes when app is launched from terminated state.
|
|
14
|
+
VoIPPushManager.shared.register()
|
|
15
|
+
|
|
16
|
+
// Initialize event emitter early so it can queue events before JS is ready
|
|
17
|
+
Task { @MainActor in
|
|
18
|
+
_ = CallEventEmitter.shared
|
|
19
|
+
// Allow events to queue that may fire before JS is ready on cold start
|
|
20
|
+
CallEventEmitter.shared.setQueueLimit(for: CallIntentReceivedEvent.self, limit: 1)
|
|
21
|
+
CallEventEmitter.shared.setQueueLimit(for: AudioSessionActivatedEvent.self, limit: 1)
|
|
22
|
+
CallEventEmitter.shared.setQueueLimit(for: AudioSessionDeactivatedEvent.self, limit: 1)
|
|
23
|
+
CallEventEmitter.shared.setQueueLimit(for: IncomingCallReportedEvent.self, limit: 1)
|
|
24
|
+
CallEventEmitter.shared.setQueueLimit(for: CallAnsweredEvent.self, limit: 1)
|
|
25
|
+
CallEventEmitter.shared.setQueueLimit(for: VoIPPushTokenUpdatedEvent.self, limit: 1)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return true
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public func application(
|
|
32
|
+
_ application: UIApplication,
|
|
33
|
+
continue userActivity: NSUserActivity,
|
|
34
|
+
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
|
|
35
|
+
) -> Bool {
|
|
36
|
+
guard let interaction = userActivity.interaction else {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if let intent = interaction.intent as? INStartAudioCallIntent {
|
|
41
|
+
handleCallIntent(contacts: intent.contacts, hasVideo: false)
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if let intent = interaction.intent as? INStartCallIntent {
|
|
46
|
+
let hasVideo = intent.callCapability == .videoCall
|
|
47
|
+
handleCallIntent(contacts: intent.contacts, hasVideo: hasVideo)
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if let intent = interaction.intent as? INStartVideoCallIntent {
|
|
52
|
+
handleCallIntent(contacts: intent.contacts, hasVideo: true)
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private func handleCallIntent(contacts: [INPerson]?, hasVideo: Bool) {
|
|
60
|
+
guard let person = contacts?.first,
|
|
61
|
+
let personHandle = person.personHandle,
|
|
62
|
+
let handleValue = personHandle.value
|
|
63
|
+
else {
|
|
64
|
+
Log.call.warning("Call intent received but no valid handle found")
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let handleType: String
|
|
69
|
+
switch personHandle.type {
|
|
70
|
+
case .phoneNumber:
|
|
71
|
+
handleType = "phoneNumber"
|
|
72
|
+
case .emailAddress:
|
|
73
|
+
handleType = "email"
|
|
74
|
+
case .unknown:
|
|
75
|
+
handleType = "unknown"
|
|
76
|
+
@unknown default:
|
|
77
|
+
handleType = "unknown"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
Log.call.debug(
|
|
81
|
+
"Call intent received - type: \(handleType), hasVideo: \(hasVideo)")
|
|
82
|
+
|
|
83
|
+
Task { @MainActor in
|
|
84
|
+
CallEventEmitter.shared.send(
|
|
85
|
+
CallIntentReceivedEvent(
|
|
86
|
+
handle: handleValue,
|
|
87
|
+
handleType: handleType,
|
|
88
|
+
hasVideo: hasVideo
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ExpoCallKitTelecom'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platforms = {
|
|
14
|
+
:ios => '16.0'
|
|
15
|
+
}
|
|
16
|
+
s.swift_version = '5.9'
|
|
17
|
+
s.source = { git: package['repository']['url'] }
|
|
18
|
+
s.static_framework = true
|
|
19
|
+
|
|
20
|
+
s.dependency 'ExpoModulesCore'
|
|
21
|
+
s.dependency 'swift-collections'
|
|
22
|
+
s.dependency 'WebRTC-SDK'
|
|
23
|
+
s.dependency 'livekit-react-native-webrtc'
|
|
24
|
+
|
|
25
|
+
# Swift/Objective-C compatibility
|
|
26
|
+
s.pod_target_xcconfig = {
|
|
27
|
+
'DEFINES_MODULE' => 'YES',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
|
|
31
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
/// A wrapper around os.Logger that automatically prepends "[ExpoCallKitTelecom] [Category]" to all messages.
|
|
4
|
+
struct ExpoCallKitTelecomLogger {
|
|
5
|
+
private let logger: Logger
|
|
6
|
+
private let prefix: String
|
|
7
|
+
|
|
8
|
+
init(subsystem: String, category: String) {
|
|
9
|
+
self.logger = Logger(subsystem: subsystem, category: category)
|
|
10
|
+
self.prefix = "[ExpoCallKitTelecom] [\(category)]"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
func debug(_ message: String) {
|
|
14
|
+
logger.debug("\(prefix, privacy: .public) \(message, privacy: .public)")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func info(_ message: String) {
|
|
18
|
+
logger.info("\(prefix, privacy: .public) \(message, privacy: .public)")
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func notice(_ message: String) {
|
|
22
|
+
logger.notice("\(prefix, privacy: .public) \(message, privacy: .public)")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func warning(_ message: String) {
|
|
26
|
+
logger.warning("\(prefix, privacy: .public) \(message, privacy: .public)")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func error(_ message: String) {
|
|
30
|
+
logger.error("\(prefix, privacy: .public) \(message, privacy: .public)")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func fault(_ message: String) {
|
|
34
|
+
logger.fault("\(prefix, privacy: .public) \(message, privacy: .public)")
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// Module-wide logging for ExpoCallKitTelecom.
|
|
39
|
+
/// Uses Apple's unified logging system (os.Logger) for efficient, privacy-aware logging.
|
|
40
|
+
/// All messages are automatically prefixed with "ExpoCallKitTelecom:".
|
|
41
|
+
enum Log {
|
|
42
|
+
private static let subsystem = "expo-callkit-telecom"
|
|
43
|
+
|
|
44
|
+
/// Logger for audio session management.
|
|
45
|
+
static let audio = ExpoCallKitTelecomLogger(subsystem: subsystem, category: "Audio")
|
|
46
|
+
|
|
47
|
+
/// Logger for call management and CallKit integration.
|
|
48
|
+
static let call = ExpoCallKitTelecomLogger(subsystem: subsystem, category: "Call")
|
|
49
|
+
|
|
50
|
+
/// Logger for VoIP push notifications.
|
|
51
|
+
static let voipPush = ExpoCallKitTelecomLogger(subsystem: subsystem, category: "VoIPPush")
|
|
52
|
+
|
|
53
|
+
/// Logger for the Expo module interface.
|
|
54
|
+
static let module = ExpoCallKitTelecomLogger(subsystem: subsystem, category: "Module")
|
|
55
|
+
}
|