rns-nativecall 1.3.2 → 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 +1 -1
- package/package.json +2 -4
- package/withNativeCallVoip.js +56 -42
package/README.md
CHANGED
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",
|
|
@@ -48,8 +48,6 @@
|
|
|
48
48
|
"react-native": ">=0.60.0"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@expo/config-plugins": "^9.0.0"
|
|
52
|
-
"react-native-uuid": "^2.0.3",
|
|
53
|
-
"expo-build-properties": "~0.14.8"
|
|
51
|
+
"@expo/config-plugins": "^9.0.0"
|
|
54
52
|
}
|
|
55
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',
|
|
@@ -110,16 +124,21 @@ function withAndroidConfig(config) {
|
|
|
110
124
|
'android.permission.MANAGE_OWN_CALLS',
|
|
111
125
|
];
|
|
112
126
|
|
|
113
|
-
|
|
127
|
+
// Initialize uses-permission if it doesn't exist
|
|
128
|
+
if (!Array.isArray(manifest.manifest['uses-permission'])) {
|
|
129
|
+
manifest.manifest['uses-permission'] = [];
|
|
130
|
+
}
|
|
131
|
+
|
|
114
132
|
permissions.forEach((perm) => {
|
|
115
|
-
if (!manifest.manifest['uses-permission'].some((p) => p.$['android:name'] === perm)) {
|
|
133
|
+
if (!manifest.manifest['uses-permission'].some((p) => p.$ && p.$['android:name'] === perm)) {
|
|
116
134
|
manifest.manifest['uses-permission'].push({ $: { 'android:name': perm } });
|
|
117
135
|
}
|
|
118
136
|
});
|
|
119
137
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
138
|
+
// 3. Fix Services
|
|
139
|
+
if (!Array.isArray(application.service)) {
|
|
140
|
+
application.service = [];
|
|
141
|
+
}
|
|
123
142
|
|
|
124
143
|
const services = [
|
|
125
144
|
{ name: 'com.rnsnativecall.CallMessagingService', exported: 'false', filter: 'com.google.firebase.MESSAGING_EVENT' },
|
|
@@ -129,7 +148,7 @@ function withAndroidConfig(config) {
|
|
|
129
148
|
];
|
|
130
149
|
|
|
131
150
|
services.forEach(svc => {
|
|
132
|
-
if (!application.service.some(s => s.$['android:name'] === svc.name)) {
|
|
151
|
+
if (!application.service.some(s => s.$ && s.$['android:name'] === svc.name)) {
|
|
133
152
|
const entry = { $: { 'android:name': svc.name, 'android:exported': svc.exported || 'false' } };
|
|
134
153
|
if (svc.type) entry.$['android:foregroundServiceType'] = svc.type;
|
|
135
154
|
if (svc.filter) {
|
|
@@ -139,13 +158,18 @@ function withAndroidConfig(config) {
|
|
|
139
158
|
}
|
|
140
159
|
});
|
|
141
160
|
|
|
161
|
+
// 4. Fix Activities
|
|
162
|
+
if (!Array.isArray(application.activity)) {
|
|
163
|
+
application.activity = [];
|
|
164
|
+
}
|
|
165
|
+
|
|
142
166
|
const activities = [
|
|
143
167
|
{ name: 'com.rnsnativecall.AcceptCallActivity', theme: '@android:style/Theme.Translucent.NoTitleBar', launchMode: 'singleInstance' },
|
|
144
168
|
{ name: 'com.rnsnativecall.NotificationOverlayActivity', theme: '@android:style/Theme.NoTitleBar.Fullscreen', launchMode: 'singleInstance' }
|
|
145
169
|
];
|
|
146
170
|
|
|
147
171
|
activities.forEach(act => {
|
|
148
|
-
if (!application.activity.some(a => a.$['android:name'] === act.name)) {
|
|
172
|
+
if (!application.activity.some(a => a.$ && a.$['android:name'] === act.name)) {
|
|
149
173
|
application.activity.push({
|
|
150
174
|
$: {
|
|
151
175
|
'android:name': act.name,
|
|
@@ -161,28 +185,28 @@ function withAndroidConfig(config) {
|
|
|
161
185
|
}
|
|
162
186
|
});
|
|
163
187
|
|
|
164
|
-
|
|
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')) {
|
|
165
194
|
application.receiver.push({ $: { 'android:name': 'com.rnsnativecall.CallActionReceiver', 'android:exported': 'false' } });
|
|
166
195
|
}
|
|
167
196
|
|
|
168
197
|
return config;
|
|
169
198
|
});
|
|
170
199
|
}
|
|
171
|
-
|
|
200
|
+
|
|
172
201
|
function withIosAppDelegateMod(config) {
|
|
173
202
|
return withAppDelegate(config, (config) => {
|
|
174
203
|
let contents = config.modResults.contents;
|
|
175
|
-
|
|
176
|
-
// 1. Surgical Import: Add 'import React' at the very top if missing
|
|
177
204
|
if (!contents.includes('import React')) {
|
|
178
205
|
contents = 'import React\n' + contents;
|
|
179
206
|
}
|
|
180
207
|
|
|
181
|
-
// 2. Check for the continue userActivity method
|
|
182
208
|
if (!contents.includes('continue userActivity')) {
|
|
183
|
-
// Method is missing, inject it before the final closing brace of the class
|
|
184
209
|
const swiftLinkingCode = `
|
|
185
|
-
// Universal Links
|
|
186
210
|
public override func application(
|
|
187
211
|
_ application: UIApplication,
|
|
188
212
|
continue userActivity: NSUserActivity,
|
|
@@ -192,36 +216,26 @@ function withIosAppDelegateMod(config) {
|
|
|
192
216
|
return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
|
|
193
217
|
}
|
|
194
218
|
`;
|
|
195
|
-
// This regex finds the last '}' in the file (closing the AppDelegate class)
|
|
196
219
|
contents = contents.replace(/\n}\s*$/, `\n${swiftLinkingCode}\n}`);
|
|
197
|
-
} else if (!contents.includes('RCTLinkingManager.application')) {
|
|
198
|
-
// Method exists but is missing our logic, inject it inside
|
|
199
|
-
contents = contents.replace(
|
|
200
|
-
/continue userActivity: NSUserActivity,[\s\S]*?\) -> Bool \{/,
|
|
201
|
-
`continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {\n let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)`
|
|
202
|
-
);
|
|
203
220
|
}
|
|
204
|
-
|
|
205
221
|
config.modResults.contents = contents;
|
|
206
222
|
return config;
|
|
207
223
|
});
|
|
208
224
|
}
|
|
209
|
-
|
|
225
|
+
|
|
210
226
|
function withIosConfig(config, props = {}) {
|
|
211
227
|
return withInfoPlist(config, (config) => {
|
|
212
228
|
const infoPlist = config.modResults;
|
|
213
229
|
if (!infoPlist.UIBackgroundModes) infoPlist.UIBackgroundModes = [];
|
|
214
|
-
|
|
215
230
|
['voip', 'remote-notification'].forEach(mode => {
|
|
216
231
|
if (!infoPlist.UIBackgroundModes.includes(mode)) {
|
|
217
232
|
infoPlist.UIBackgroundModes.push(mode);
|
|
218
233
|
}
|
|
219
234
|
});
|
|
220
|
-
|
|
221
235
|
return config;
|
|
222
236
|
});
|
|
223
237
|
}
|
|
224
|
-
|
|
238
|
+
|
|
225
239
|
module.exports = (config, props) => {
|
|
226
240
|
return withPlugins(config, [
|
|
227
241
|
withAndroidConfig,
|