rns-nativecall 1.3.1 → 1.3.3
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 +89 -68
- package/package.json +4 -5
- package/withNativeCallVoip.js +57 -42
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# rns-nativecall
|
|
2
2
|
|
|
3
|
-
A professional VoIP incoming call handler for React Native
|
|
3
|
+
A **professional VoIP incoming call handler for React Native** with full **Android & iOS native UI integration**.
|
|
4
|
+
Designed for production-grade apps requiring **CallKit**, **lockscreen handling**, **headless execution**, and **single-call enforcement**.
|
|
5
|
+
|
|
6
|
+
---
|
|
4
7
|
|
|
5
8
|
## 🚀 Highlights
|
|
6
|
-
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
+
|
|
10
|
+
- 📦 **Expo Ready** – Zero manual native setup via config plugin
|
|
11
|
+
- ☎️ **Single Call Gate** – Automatically blocks concurrent calls and emits `BUSY` events
|
|
12
|
+
- 🧠 **Headless Mode** – Works when the app is killed, backgrounded, or screen locked
|
|
13
|
+
- 📱 **Native UI** – Full-screen Android Activity & iOS CallKit
|
|
14
|
+
- 🔔 **System-Level Reliability** – No JS race conditions, no ghost calls
|
|
9
15
|
|
|
10
16
|
---
|
|
11
17
|
|
|
@@ -13,15 +19,20 @@ A professional VoIP incoming call handler for React Native. Features a "Single C
|
|
|
13
19
|
|
|
14
20
|
```bash
|
|
15
21
|
npx expo install rns-nativecall expo-build-properties react-native-uuid
|
|
16
|
-
|
|
17
22
|
```
|
|
23
|
+
|
|
18
24
|
or
|
|
25
|
+
|
|
19
26
|
```bash
|
|
20
27
|
npm install rns-nativecall expo-build-properties react-native-uuid
|
|
21
|
-
|
|
22
28
|
```
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## ⚙️ Expo Configuration
|
|
33
|
+
|
|
34
|
+
Add the plugin to **app.json** or **app.config.js**:
|
|
35
|
+
|
|
25
36
|
```json
|
|
26
37
|
{
|
|
27
38
|
"expo": {
|
|
@@ -54,11 +65,15 @@ Add the plugin to your app.json or app.config.js:
|
|
|
54
65
|
}
|
|
55
66
|
}
|
|
56
67
|
```
|
|
68
|
+
|
|
57
69
|
---
|
|
58
|
-
### 🛠 Usage
|
|
59
70
|
|
|
60
|
-
|
|
61
|
-
|
|
71
|
+
## 🛠 Usage
|
|
72
|
+
|
|
73
|
+
### 1️⃣ Register Headless Task (index.js)
|
|
74
|
+
|
|
75
|
+
This enables background handling, busy-state signaling, and cold-start execution.
|
|
76
|
+
|
|
62
77
|
```javascript
|
|
63
78
|
import { AppRegistry } from 'react-native';
|
|
64
79
|
import App from './App';
|
|
@@ -66,51 +81,41 @@ import { CallHandler } from 'rns-nativecall';
|
|
|
66
81
|
|
|
67
82
|
CallHandler.registerHeadlessTask(async (data, eventType) => {
|
|
68
83
|
if (eventType === 'BUSY') {
|
|
69
|
-
|
|
70
|
-
console.log("System Busy for UUID:", data.callUuid);
|
|
84
|
+
console.log("User already in call:", data.callUuid);
|
|
71
85
|
return;
|
|
72
86
|
}
|
|
73
87
|
|
|
74
88
|
if (eventType === 'INCOMING_CALL') {
|
|
75
|
-
|
|
76
|
-
// Trigger your custom UI or logic here.
|
|
89
|
+
console.log("Incoming call payload:", data);
|
|
77
90
|
}
|
|
78
91
|
});
|
|
79
92
|
|
|
80
93
|
AppRegistry.registerComponent('main', () => App);
|
|
81
94
|
```
|
|
82
|
-
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 🎧 Foreground Event Handling (index.js)
|
|
83
99
|
|
|
84
100
|
```javascript
|
|
85
|
-
// Index.js Setup Foreground Listeners
|
|
86
101
|
CallHandler.subscribe(
|
|
87
|
-
|
|
88
102
|
async (data) => {
|
|
89
|
-
|
|
90
|
-
console.log("APP IS OPEN", data)
|
|
91
|
-
// navigate here
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.log("pending_call_uuid", error)
|
|
94
|
-
}
|
|
103
|
+
console.log("CALL ACCEPTED", data);
|
|
95
104
|
},
|
|
96
|
-
|
|
97
105
|
async (data) => {
|
|
98
|
-
|
|
99
|
-
console.log("CALL DECLINE", data)
|
|
100
|
-
// update the caller here call decline
|
|
101
|
-
} catch (error) {
|
|
102
|
-
console.log("Onreject/ cancel call error", error)
|
|
103
|
-
}
|
|
106
|
+
console.log("CALL REJECTED", data);
|
|
104
107
|
},
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
(data) => {
|
|
109
|
+
console.log("CALL FAILED", data);
|
|
110
|
+
}
|
|
107
111
|
);
|
|
108
|
-
|
|
109
112
|
```
|
|
110
|
-
## Handling Events (App.js)
|
|
111
113
|
|
|
112
|
-
|
|
114
|
+
---
|
|
113
115
|
|
|
116
|
+
## 🎬 App-Level Integration (App.js)
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
114
119
|
import React, { useEffect } from 'react';
|
|
115
120
|
import { CallHandler } from 'rns-nativecall';
|
|
116
121
|
|
|
@@ -119,18 +124,15 @@ export default function App() {
|
|
|
119
124
|
const unsubscribe = CallHandler.subscribe(
|
|
120
125
|
(data) => {
|
|
121
126
|
console.log("Call Accepted:", data.callUuid);
|
|
122
|
-
// Navigate to your call screen
|
|
123
127
|
},
|
|
124
128
|
(data) => {
|
|
125
129
|
console.log("Call Rejected:", data.callUuid);
|
|
126
|
-
// Send 'Hangup' signal to your server
|
|
127
130
|
}
|
|
128
131
|
);
|
|
129
132
|
|
|
130
133
|
return () => unsubscribe();
|
|
131
134
|
}, []);
|
|
132
135
|
|
|
133
|
-
// To manually trigger the UI (e.g., from an FCM data message)
|
|
134
136
|
const showCall = () => {
|
|
135
137
|
CallHandler.displayCall("unique-uuid", "Caller Name", "video");
|
|
136
138
|
};
|
|
@@ -138,51 +140,62 @@ export default function App() {
|
|
|
138
140
|
return <YourUI />;
|
|
139
141
|
}
|
|
140
142
|
```
|
|
143
|
+
|
|
141
144
|
---
|
|
142
|
-
## 📖 rns-nativecall API Reference
|
|
143
145
|
|
|
146
|
+
## 📖 API Reference
|
|
144
147
|
|
|
145
148
|
### Core Methods
|
|
149
|
+
|
|
146
150
|
| Method | Platform | Description |
|
|
147
|
-
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
|
|
|
153
|
-
|
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
|------|---------|-------------|
|
|
152
|
+
| `registerHeadlessTask(cb)` | All | Registers background task (`INCOMING_CALL`, `BUSY`, `ABORTED_CALL`) |
|
|
153
|
+
| `displayCall(uuid, name, type)` | All | Shows native incoming call UI |
|
|
154
|
+
| `destroyNativeCallUI(uuid)` | All | Ends native UI / CallKit session |
|
|
155
|
+
| `subscribe(onAccept, onReject, onFail)` | All | Listen to call actions |
|
|
156
|
+
| `showMissedCall(uuid, name, type)` | Android | Persistent missed call notification |
|
|
157
|
+
| `showOnGoingCall(uuid, name, type)` | Android | Persistent ongoing call notification |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### Data & State
|
|
162
|
+
|
|
156
163
|
| Method | Platform | Description |
|
|
157
|
-
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
|
|
|
164
|
+
|------|---------|-------------|
|
|
165
|
+
| `getInitialCallData()` | All | Retrieve payload from cold start |
|
|
166
|
+
| `checkCallValidity(uuid)` | All | Prevent ghost calls |
|
|
167
|
+
| `checkCallStatus(uuid)` | All | Sync UI with native state |
|
|
168
|
+
|
|
169
|
+
---
|
|
161
170
|
|
|
162
171
|
### Android Permissions
|
|
163
|
-
|
|
164
|
-
|
|
|
165
|
-
|
|
166
|
-
|
|
|
167
|
-
|
|
|
168
|
-
|
|
|
172
|
+
|
|
173
|
+
| Method | Description |
|
|
174
|
+
|------|-------------|
|
|
175
|
+
| `checkOverlayPermission()` | Check lockscreen overlay permission |
|
|
176
|
+
| `requestOverlayPermission()` | Open overlay settings |
|
|
177
|
+
| `checkFullScreenPermission()` | Android 14+ full screen intent |
|
|
178
|
+
| `requestFullScreenSettings()` | Android 14+ permission screen |
|
|
169
179
|
|
|
170
180
|
---
|
|
171
181
|
|
|
172
|
-
|
|
182
|
+
## 🧠 Implementation Notes
|
|
173
183
|
|
|
174
|
-
|
|
175
|
-
|
|
184
|
+
### Android Overlay
|
|
185
|
+
Overlay permission is required to display calls on the lockscreen.
|
|
186
|
+
Request during onboarding or before first call.
|
|
176
187
|
|
|
177
|
-
|
|
178
|
-
|
|
188
|
+
### iOS CallKit
|
|
189
|
+
Uses system CallKit UI. Works automatically in background and lockscreen.
|
|
190
|
+
|
|
191
|
+
### Single Call Gate
|
|
192
|
+
If a call is active, all subsequent calls emit `BUSY` via headless task.
|
|
179
193
|
|
|
180
|
-
3. Single Call Gate:
|
|
181
|
-
The library automatically prevents multiple overlapping native UIs. If a call is already active, subsequent calls will trigger the 'BUSY' event in your Headless Task.
|
|
182
194
|
---
|
|
183
195
|
|
|
184
|
-
##
|
|
185
|
-
|
|
196
|
+
## 🧪 Full Example
|
|
197
|
+
|
|
198
|
+
```js
|
|
186
199
|
import React, { useEffect, useState } from 'react';
|
|
187
200
|
import { StyleSheet, Text, View, TouchableOpacity, Alert } from 'react-native';
|
|
188
201
|
import { CallHandler } from 'rns-nativecall';
|
|
@@ -275,5 +288,13 @@ const styles = StyleSheet.create({
|
|
|
275
288
|
btnText: { color: 'white', fontWeight: 'bold' }
|
|
276
289
|
});
|
|
277
290
|
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
278
294
|
## 🛡 License
|
|
295
|
+
|
|
296
|
+
MIT License
|
|
297
|
+
|
|
279
298
|
---
|
|
299
|
+
|
|
300
|
+
Built for **production VoIP apps**, not demos.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rns-nativecall",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
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",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"url": "git+https://github.com/raiidr/rns-nativecall.git"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"p": "npm publish --access public"
|
|
23
|
+
"p": "npm publish --access public",
|
|
24
|
+
"i": "npm publish --access public"
|
|
24
25
|
},
|
|
25
26
|
"keywords": [
|
|
26
27
|
"react-native",
|
|
@@ -47,8 +48,6 @@
|
|
|
47
48
|
"react-native": ">=0.60.0"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
|
-
"@expo/config-plugins": "^9.0.0"
|
|
51
|
-
"react-native-uuid": "^2.0.3",
|
|
52
|
-
"expo-build-properties": "~0.14.8"
|
|
51
|
+
"@expo/config-plugins": "^9.0.0"
|
|
53
52
|
}
|
|
54
53
|
}
|
package/withNativeCallVoip.js
CHANGED
|
@@ -13,7 +13,6 @@ function withMainActivityDataFix(config) {
|
|
|
13
13
|
'import android.Manifest'
|
|
14
14
|
];
|
|
15
15
|
|
|
16
|
-
// Add imports if they don't exist
|
|
17
16
|
imports.forEach(imp => {
|
|
18
17
|
if (!contents.includes(imp)) {
|
|
19
18
|
contents = contents.replace(/package .*/, (match) => `${match}\n${imp}`);
|
|
@@ -21,16 +20,21 @@ function withMainActivityDataFix(config) {
|
|
|
21
20
|
});
|
|
22
21
|
|
|
23
22
|
const onCreateCode = `
|
|
24
|
-
|
|
23
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
25
24
|
super.onCreate(savedInstanceState)
|
|
26
25
|
|
|
27
|
-
// Request
|
|
26
|
+
// Request Permissions for Android 13+ and Calling Roles
|
|
27
|
+
val permissions = mutableListOf<String>()
|
|
28
28
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
29
|
+
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
|
|
30
|
+
}
|
|
31
|
+
// MANAGE_OWN_CALLS is required for Foreground Service Type 'phoneCall' on SDK 34+
|
|
32
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
33
|
+
permissions.add(Manifest.permission.MANAGE_OWN_CALLS)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (permissions.isNotEmpty()) {
|
|
37
|
+
ActivityCompat.requestPermissions(this, permissions.toTypedArray(), 101)
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
@@ -69,35 +73,45 @@ function withMainActivityDataFix(config) {
|
|
|
69
73
|
return config;
|
|
70
74
|
});
|
|
71
75
|
}
|
|
76
|
+
|
|
72
77
|
function withNotificationColor(config) {
|
|
73
78
|
// 1. Find the color in app.json (fallback to #218aff)
|
|
74
79
|
const notificationPlugin = config.plugins?.find(p => Array.isArray(p) && p[0] === 'expo-notifications');
|
|
75
80
|
const iconColor = notificationPlugin?.[1]?.color || '#218aff';
|
|
76
81
|
|
|
77
82
|
return withAndroidStyles(config, (config) => {
|
|
83
|
+
// Corrected from config.config.modResults to config.modResults
|
|
78
84
|
config.modResults = AndroidConfig.Styles.assignStylesValue(config.modResults, {
|
|
79
85
|
name: 'notification_icon_color',
|
|
80
86
|
value: iconColor,
|
|
81
|
-
parent: 'AppTheme',
|
|
87
|
+
parent: 'AppTheme',
|
|
82
88
|
type: 'color',
|
|
83
89
|
});
|
|
84
90
|
return config;
|
|
85
91
|
});
|
|
86
92
|
}
|
|
87
|
-
|
|
93
|
+
|
|
88
94
|
function withAndroidConfig(config) {
|
|
89
95
|
return withAndroidManifest(config, (config) => {
|
|
90
96
|
const manifest = config.modResults;
|
|
97
|
+
|
|
98
|
+
// Ensure manifest structure exists
|
|
99
|
+
if (!manifest.manifest) manifest.manifest = {};
|
|
100
|
+
if (!manifest.manifest.application) manifest.manifest.application = [{}];
|
|
101
|
+
|
|
91
102
|
const application = manifest.manifest.application[0];
|
|
92
103
|
|
|
93
|
-
// Ensure MainActivity flags
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
mainActivity
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
// 1. Ensure MainActivity flags
|
|
105
|
+
if (application.activity) {
|
|
106
|
+
const mainActivity = application.activity.find((a) => a.$['android:name'] === '.MainActivity');
|
|
107
|
+
if (mainActivity) {
|
|
108
|
+
mainActivity.$['android:launchMode'] = 'singleTop';
|
|
109
|
+
mainActivity.$['android:showWhenLocked'] = 'true';
|
|
110
|
+
mainActivity.$['android:turnScreenOn'] = 'true';
|
|
111
|
+
}
|
|
99
112
|
}
|
|
100
113
|
|
|
114
|
+
// 2. Fix Permissions (The 'some' error fix)
|
|
101
115
|
const permissions = [
|
|
102
116
|
'android.permission.VIBRATE',
|
|
103
117
|
'android.permission.FOREGROUND_SERVICE',
|
|
@@ -107,18 +121,24 @@ function withAndroidConfig(config) {
|
|
|
107
121
|
'android.permission.POST_NOTIFICATIONS',
|
|
108
122
|
'android.permission.WAKE_LOCK',
|
|
109
123
|
'android.permission.DISABLE_KEYGUARD',
|
|
124
|
+
'android.permission.MANAGE_OWN_CALLS',
|
|
110
125
|
];
|
|
111
126
|
|
|
112
|
-
|
|
127
|
+
// Initialize uses-permission if it doesn't exist
|
|
128
|
+
if (!Array.isArray(manifest.manifest['uses-permission'])) {
|
|
129
|
+
manifest.manifest['uses-permission'] = [];
|
|
130
|
+
}
|
|
131
|
+
|
|
113
132
|
permissions.forEach((perm) => {
|
|
114
|
-
if (!manifest.manifest['uses-permission'].some((p) => p.$['android:name'] === perm)) {
|
|
133
|
+
if (!manifest.manifest['uses-permission'].some((p) => p.$ && p.$['android:name'] === perm)) {
|
|
115
134
|
manifest.manifest['uses-permission'].push({ $: { 'android:name': perm } });
|
|
116
135
|
}
|
|
117
136
|
});
|
|
118
137
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
// 3. Fix Services
|
|
139
|
+
if (!Array.isArray(application.service)) {
|
|
140
|
+
application.service = [];
|
|
141
|
+
}
|
|
122
142
|
|
|
123
143
|
const services = [
|
|
124
144
|
{ name: 'com.rnsnativecall.CallMessagingService', exported: 'false', filter: 'com.google.firebase.MESSAGING_EVENT' },
|
|
@@ -128,7 +148,7 @@ function withAndroidConfig(config) {
|
|
|
128
148
|
];
|
|
129
149
|
|
|
130
150
|
services.forEach(svc => {
|
|
131
|
-
if (!application.service.some(s => s.$['android:name'] === svc.name)) {
|
|
151
|
+
if (!application.service.some(s => s.$ && s.$['android:name'] === svc.name)) {
|
|
132
152
|
const entry = { $: { 'android:name': svc.name, 'android:exported': svc.exported || 'false' } };
|
|
133
153
|
if (svc.type) entry.$['android:foregroundServiceType'] = svc.type;
|
|
134
154
|
if (svc.filter) {
|
|
@@ -138,13 +158,18 @@ function withAndroidConfig(config) {
|
|
|
138
158
|
}
|
|
139
159
|
});
|
|
140
160
|
|
|
161
|
+
// 4. Fix Activities
|
|
162
|
+
if (!Array.isArray(application.activity)) {
|
|
163
|
+
application.activity = [];
|
|
164
|
+
}
|
|
165
|
+
|
|
141
166
|
const activities = [
|
|
142
167
|
{ name: 'com.rnsnativecall.AcceptCallActivity', theme: '@android:style/Theme.Translucent.NoTitleBar', launchMode: 'singleInstance' },
|
|
143
168
|
{ name: 'com.rnsnativecall.NotificationOverlayActivity', theme: '@android:style/Theme.NoTitleBar.Fullscreen', launchMode: 'singleInstance' }
|
|
144
169
|
];
|
|
145
170
|
|
|
146
171
|
activities.forEach(act => {
|
|
147
|
-
if (!application.activity.some(a => a.$['android:name'] === act.name)) {
|
|
172
|
+
if (!application.activity.some(a => a.$ && a.$['android:name'] === act.name)) {
|
|
148
173
|
application.activity.push({
|
|
149
174
|
$: {
|
|
150
175
|
'android:name': act.name,
|
|
@@ -160,28 +185,28 @@ function withAndroidConfig(config) {
|
|
|
160
185
|
}
|
|
161
186
|
});
|
|
162
187
|
|
|
163
|
-
|
|
188
|
+
// 5. Fix Receiver (The other likely 'some' error source)
|
|
189
|
+
if (!Array.isArray(application.receiver)) {
|
|
190
|
+
application.receiver = [];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!application.receiver.some(r => r.$ && r.$['android:name'] === 'com.rnsnativecall.CallActionReceiver')) {
|
|
164
194
|
application.receiver.push({ $: { 'android:name': 'com.rnsnativecall.CallActionReceiver', 'android:exported': 'false' } });
|
|
165
195
|
}
|
|
166
196
|
|
|
167
197
|
return config;
|
|
168
198
|
});
|
|
169
199
|
}
|
|
170
|
-
|
|
200
|
+
|
|
171
201
|
function withIosAppDelegateMod(config) {
|
|
172
202
|
return withAppDelegate(config, (config) => {
|
|
173
203
|
let contents = config.modResults.contents;
|
|
174
|
-
|
|
175
|
-
// 1. Surgical Import: Add 'import React' at the very top if missing
|
|
176
204
|
if (!contents.includes('import React')) {
|
|
177
205
|
contents = 'import React\n' + contents;
|
|
178
206
|
}
|
|
179
207
|
|
|
180
|
-
// 2. Check for the continue userActivity method
|
|
181
208
|
if (!contents.includes('continue userActivity')) {
|
|
182
|
-
// Method is missing, inject it before the final closing brace of the class
|
|
183
209
|
const swiftLinkingCode = `
|
|
184
|
-
// Universal Links
|
|
185
210
|
public override func application(
|
|
186
211
|
_ application: UIApplication,
|
|
187
212
|
continue userActivity: NSUserActivity,
|
|
@@ -191,36 +216,26 @@ function withIosAppDelegateMod(config) {
|
|
|
191
216
|
return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
|
|
192
217
|
}
|
|
193
218
|
`;
|
|
194
|
-
// This regex finds the last '}' in the file (closing the AppDelegate class)
|
|
195
219
|
contents = contents.replace(/\n}\s*$/, `\n${swiftLinkingCode}\n}`);
|
|
196
|
-
} else if (!contents.includes('RCTLinkingManager.application')) {
|
|
197
|
-
// Method exists but is missing our logic, inject it inside
|
|
198
|
-
contents = contents.replace(
|
|
199
|
-
/continue userActivity: NSUserActivity,[\s\S]*?\) -> Bool \{/,
|
|
200
|
-
`continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {\n let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)`
|
|
201
|
-
);
|
|
202
220
|
}
|
|
203
|
-
|
|
204
221
|
config.modResults.contents = contents;
|
|
205
222
|
return config;
|
|
206
223
|
});
|
|
207
224
|
}
|
|
208
|
-
|
|
225
|
+
|
|
209
226
|
function withIosConfig(config, props = {}) {
|
|
210
227
|
return withInfoPlist(config, (config) => {
|
|
211
228
|
const infoPlist = config.modResults;
|
|
212
229
|
if (!infoPlist.UIBackgroundModes) infoPlist.UIBackgroundModes = [];
|
|
213
|
-
|
|
214
230
|
['voip', 'remote-notification'].forEach(mode => {
|
|
215
231
|
if (!infoPlist.UIBackgroundModes.includes(mode)) {
|
|
216
232
|
infoPlist.UIBackgroundModes.push(mode);
|
|
217
233
|
}
|
|
218
234
|
});
|
|
219
|
-
|
|
220
235
|
return config;
|
|
221
236
|
});
|
|
222
237
|
}
|
|
223
|
-
|
|
238
|
+
|
|
224
239
|
module.exports = (config, props) => {
|
|
225
240
|
return withPlugins(config, [
|
|
226
241
|
withAndroidConfig,
|