rns-nativecall 1.1.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -132,16 +132,18 @@ export default function App() {
132
132
 
133
133
  | Method | Platform | Description |
134
134
  | :--- | :--- | :--- |
135
- | **registerHeadlessTask(callback)** | Android | Registers background logic. `eventType` is `INCOMING_CALL` or `BUSY`. |
136
- | **checkOverlayPermission()** | Android | Returns true if the app can draw over other apps (Required for Android Lockscreen). |
135
+ | **registerHeadlessTask(callback)** | Android | Registers background logic. `eventType` is `INCOMING_CALL`, `BUSY`, or `ABORTED_CALL`. |
136
+ | **checkOverlayPermission()** | Android | Returns true if the app can draw over other apps (Required for overlay UI). |
137
137
  | **requestOverlayPermission()** | Android | Opens System Settings to let the user enable "Draw over other apps". |
138
- | **displayCall(uuid, name, type)** | All | Shows the native call UI (Standard Notification on Android / CallKit on iOS). |
139
- | **checkCallValidity(uuid)** | All | Returns boolean values for `isValid` and `isCanceled`. |
140
- | **stopForegroundService()** | Android | Stops the ongoing service and clears the persistent notification/pill. |
141
- | **destroyNativeCallUI(uuid)** | All | Dismisses the native call interface and stops the ringtone. |
142
- | **getInitialCallData()** | All | Returns call data if the app was launched by clicking `Answer` from a killed state. |
143
- | **subscribe(onAccept, onReject)** | All | Listens for native button presses (Answer/End). |
144
-
138
+ | **checkFullScreenPermission()** | Android | [Android 14+] Checks if the app is allowed to show full-screen intents on the lockscreen. |
139
+ | **requestFullScreenSettings()** | Android | [Android 14+] Opens System Settings to enable the Full Screen Intent permission. |
140
+ | **displayCall(uuid, name, type)** | Android | Shows the native full-screen call UI and starts the ringtone. |
141
+ | **checkCallValidity(uuid)** | Android | Returns `{isValid, isCanceled}` based on persistent state and CANCEL signals. |
142
+ | **checkCallStatus(uuid)** | Android | Returns `{isCanceled, isActive, shouldDisplay}` for UI synchronization. |
143
+ | **reportRemoteEnded(uuid, reason)** | Android | Tells the native side the caller hung up so the UI can dismiss automatically. |
144
+ | **destroyNativeCallUI(uuid)** | Android | Forcefully dismisses the native interface, stops audio, and clears the current call state. |
145
+ | **getInitialCallData()** | Android | Returns the call payload if the app was cold-started by a notification interaction. |
146
+ | **subscribe(onAccept, onReject, onFailed)** | Android | Listens for native Answer/Decline button presses and system errors. |
145
147
  ---
146
148
 
147
149
  # Implementation Notes
@@ -61,7 +61,6 @@ class CallModule(
61
61
  }
62
62
  }
63
63
 
64
- // Inside your CallModule class
65
64
  @ReactMethod
66
65
  fun checkOverlayPermission(promise: Promise) {
67
66
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -71,6 +70,16 @@ class CallModule(
71
70
  }
72
71
  }
73
72
 
73
+ @ReactMethod
74
+ fun reportRemoteEnded(
75
+ uuid: String,
76
+ reason: String,
77
+ promise: Promise,
78
+ ) {
79
+ NativeCallManager.dismissIncomingCall(reactApplicationContext, uuid)
80
+ promise.resolve(true)
81
+ }
82
+
74
83
  @ReactMethod
75
84
  fun requestOverlayPermission() {
76
85
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -86,10 +95,39 @@ class CallModule(
86
95
  }
87
96
  }
88
97
 
89
- /**
90
- * Combined Validity Check:
91
- * Used by Headless Task to see if it should proceed with the UI.
92
- */
98
+ @ReactMethod
99
+ fun checkFullScreenIntentPermission(promise: Promise) {
100
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
101
+ val notificationManager = reactApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
102
+ promise.resolve(notificationManager.canUseFullScreenIntent())
103
+ } else {
104
+ // Automatically true for Android 13 and below
105
+ promise.resolve(true)
106
+ }
107
+ }
108
+
109
+ @ReactMethod
110
+ fun requestFullScreenSettings() {
111
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
112
+ try {
113
+ val intent =
114
+ Intent(Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT).apply {
115
+ data = Uri.fromParts("package", reactApplicationContext.packageName, null)
116
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
117
+ }
118
+ reactApplicationContext.startActivity(intent)
119
+ } catch (e: Exception) {
120
+ // Fallback for some OEM skins that might not support the direct intent
121
+ val intent =
122
+ Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
123
+ data = Uri.fromParts("package", reactApplicationContext.packageName, null)
124
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
125
+ }
126
+ reactApplicationContext.startActivity(intent)
127
+ }
128
+ }
129
+ }
130
+
93
131
  @ReactMethod
94
132
  fun checkCallValidity(
95
133
  uuid: String,
@@ -107,22 +145,6 @@ class CallModule(
107
145
  promise.resolve(map)
108
146
  }
109
147
 
110
- @ReactMethod
111
- fun stopForegroundService(promise: Promise) {
112
- try {
113
- // Using the current react context to stop the service
114
- val intent = Intent(reactApplicationContext, CallForegroundService::class.java)
115
- reactApplicationContext.stopService(intent)
116
- promise.resolve(true)
117
- } catch (e: Exception) {
118
- promise.reject("SERVICE_STOP_ERROR", e.message)
119
- }
120
- }
121
-
122
- /**
123
- * General Status Check:
124
- * Useful for checking if the UI is still relevant.
125
- */
126
148
  @ReactMethod
127
149
  fun checkCallStatus(
128
150
  uuid: String,
@@ -1,4 +1,3 @@
1
- /////Users/bush/Desktop/Apps/Raiidr/package/android/src/main/java/com/rnsnativecall/CallPackage.kt
2
1
  package com.rnsnativecall
3
2
 
4
3
  import com.facebook.react.ReactPackage
@@ -7,11 +6,7 @@ import com.facebook.react.bridge.ReactApplicationContext
7
6
  import com.facebook.react.uimanager.ViewManager
8
7
 
9
8
  class CallPackage : ReactPackage {
10
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
- return listOf(CallModule(reactContext))
12
- }
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> = listOf(CallModule(reactContext))
13
10
 
14
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
- return emptyList()
16
- }
17
- }
11
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> = emptyList()
12
+ }
package/index.d.ts CHANGED
@@ -48,7 +48,6 @@ export interface CallHandlerType {
48
48
  /**
49
49
  * Registers the background "Headless" task.
50
50
  * This is the bridge between a Native push notification and your React Native UI.
51
- * * @param callback Async function receiving call data and the event type.
52
51
  */
53
52
  registerHeadlessTask(
54
53
  callback: (data: CallData, eventType: CallEventType) => Promise<void>
@@ -56,58 +55,55 @@ export interface CallHandlerType {
56
55
 
57
56
  /**
58
57
  * Displays the full-screen Native Incoming Call UI.
59
- * Usually called inside registerHeadlessTask after validating the call.
60
- * * @param uuid The unique call ID.
61
- * @param name Name to display on the call screen.
62
- * @param callType Defaults to 'audio'.
63
- * @returns Promise resolving to true if the UI was successfully launched.
64
58
  */
65
59
  displayCall(
66
60
  uuid: string,
67
61
  name: string,
68
- callType: 'audio' | 'video',
62
+ callType?: 'audio' | 'video',
69
63
  ): Promise<boolean>;
70
64
 
71
65
  /** * Checks if a call is still valid and has not been canceled.
72
- * Useful for Splash screen "Interceptors" to prevent ghost calls.
73
66
  */
74
67
  checkCallValidity(uuid: string): Promise<ValidityStatus>;
75
68
 
76
69
  /** * Detailed check of a call's status.
77
- * Useful for determining if the UI should remain visible.
78
70
  */
79
71
  checkCallStatus(uuid: string): Promise<CallStatus>;
80
72
 
81
- requestOverlayPermission(): Promise<boolean>;
73
+ /**
74
+ * Checks if the app has permission to draw over other apps (Overlay).
75
+ */
76
+ checkOverlayPermission(): Promise<boolean>;
82
77
 
83
- reportRemoteEnded(uuid: string, reason: number): void;
78
+ /**
79
+ * Opens system settings to request the "Draw over other apps" (Overlay) permission.
80
+ * Note: Returns a promise that resolves to false if module is missing.
81
+ */
82
+ requestOverlayPermission(): Promise<boolean | void>;
84
83
 
85
- checkOverlayPermission(): Promise<boolean>;
84
+ /**
85
+ * [Android 14+] Opens the specific system settings page for Full Screen Intent.
86
+ */
87
+ requestFullScreenSettings(): Promise<boolean | void>;
86
88
 
87
89
  /**
88
- * Forcefully dismisses the native call UI, stops the ringtone, and clears state.
89
- * Use this when the call is hung up or timed out.
90
+ * Reports to the native side that the remote party has terminated the call.
90
91
  */
91
- destroyNativeCallUI(uuid: string): void;
92
+ reportRemoteEnded(uuid: string, reason?: string): Promise<void>;
92
93
 
93
94
  /**
94
- * Stops the "Connecting..." Foreground Service.
95
- * MUST be called after displayCall() or when a BUSY signal is handled to
96
- * remove the persistent system notification.
95
+ * Forcefully dismisses the native call UI, stops the ringtone, and clears state.
97
96
  */
98
- stopForegroundService(): Promise<void>;
97
+ destroyNativeCallUI(uuid: string): void;
99
98
 
100
99
  /**
101
- * Retrieves call data if the app was launched directly from an interaction
102
- * with a notification while the app was in a "Killed" state.
100
+ * Retrieves call data if the app was launched directly from an interaction.
101
+ * Returns the 'default' payload or the raw data object.
103
102
  */
104
103
  getInitialCallData(): Promise<any | null>;
105
104
 
106
105
  /**
107
106
  * Subscribes to user interactions on the Native Call UI.
108
- * * @param onAccept Callback when user presses the Answer button.
109
- * @param onReject Callback when user presses the Decline button.
110
- * @param onFailed Callback for system errors (optional).
111
107
  * @returns A cleanup function to unsubscribe.
112
108
  */
113
109
  subscribe(
@@ -120,5 +116,5 @@ export interface CallHandlerType {
120
116
  /**
121
117
  * Main handler for Native VoIP Call interactions.
122
118
  */
123
- declare const CallHandler: CallHandlerType;
119
+ export const CallHandler: CallHandlerType;
124
120
  export default CallHandler;
package/index.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  const { CallModule } = NativeModules;
8
8
  const callEventEmitter = CallModule ? new NativeEventEmitter(CallModule) : null;
9
9
 
10
+
10
11
  export const CallHandler = {
11
12
  registerHeadlessTask: (onAction) => {
12
13
  AppRegistry.registerHeadlessTask('ColdStartCallTask', () => async (data) => {
@@ -57,6 +58,11 @@ export const CallHandler = {
57
58
  return await CallModule.requestOverlayPermission();
58
59
  },
59
60
 
61
+ requestFullScreenSettings: async () => {
62
+ if (!CallModule?.requestFullScreenSettings) return false;
63
+ return await CallModule.requestFullScreenSettings();
64
+ },
65
+
60
66
  checkOverlayPermission: async () => {
61
67
  if (!CallModule?.checkOverlayPermission) return false;
62
68
  return await CallModule.checkOverlayPermission();
@@ -67,21 +73,19 @@ export const CallHandler = {
67
73
  return await CallModule.displayIncomingCall(uuid.toLowerCase().trim(), name, callType);
68
74
  },
69
75
 
70
- stopForegroundService: async () => {
71
- if (CallModule?.stopForegroundService) {
72
- await CallModule.stopForegroundService();
73
- }
74
- },
75
-
76
76
  destroyNativeCallUI: (uuid) => {
77
77
  if (CallModule?.endNativeCall) {
78
78
  CallModule.endNativeCall(uuid.toLowerCase().trim());
79
79
  }
80
80
  },
81
81
 
82
+
82
83
  getInitialCallData: async () => {
83
84
  if (!CallModule?.getInitialCallData) return null;
84
- return await CallModule.getInitialCallData();
85
+ const data = await CallModule.getInitialCallData();
86
+
87
+ // Return the 'default' call data if it exists, otherwise the whole object
88
+ return data?.default || data;
85
89
  },
86
90
 
87
91
  subscribe: (onAccept, onReject, onFailed) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-nativecall",
3
- "version": "1.1.8",
3
+ "version": "1.2.0",
4
4
  "description": "High-performance React Native module for handling native VoIP call UI on Android and iOS.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",