rns-nativecall 0.3.8 → 0.3.9
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.
|
@@ -23,7 +23,7 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
23
23
|
writableMap
|
|
24
24
|
}
|
|
25
25
|
promise.resolve(data)
|
|
26
|
-
pendingCallDataMap = null
|
|
26
|
+
pendingCallDataMap = null
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
@ReactMethod
|
|
@@ -48,7 +48,7 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
48
48
|
pendingCallDataMap = null
|
|
49
49
|
|
|
50
50
|
val notificationManager = reactApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
51
|
-
notificationManager.cancel(
|
|
51
|
+
notificationManager.cancel(uuid.hashCode())
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
@ReactMethod
|
|
@@ -14,7 +14,6 @@ import android.graphics.Color
|
|
|
14
14
|
object NativeCallManager {
|
|
15
15
|
|
|
16
16
|
private var ringtone: Ringtone? = null
|
|
17
|
-
const val INCOMING_CALL_ID = 101
|
|
18
17
|
const val CALL_CHANNEL_ID = "CALL_CHANNEL_ID"
|
|
19
18
|
|
|
20
19
|
fun handleIncomingPush(context: Context, data: Map<String, String>) {
|
|
@@ -50,9 +49,10 @@ object NativeCallManager {
|
|
|
50
49
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
51
50
|
|
|
52
51
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
53
|
-
val channel = NotificationChannel(CALL_CHANNEL_ID, "Incoming
|
|
52
|
+
val channel = NotificationChannel(CALL_CHANNEL_ID, "Incoming Call", NotificationManager.IMPORTANCE_HIGH).apply {
|
|
54
53
|
setBypassDnd(true)
|
|
55
54
|
lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
|
|
55
|
+
enableVibration(true) //can be removed
|
|
56
56
|
setSound(null, null)
|
|
57
57
|
}
|
|
58
58
|
notificationManager.createNotificationChannel(channel)
|
|
@@ -62,11 +62,13 @@ object NativeCallManager {
|
|
|
62
62
|
.setSmallIcon(context.applicationInfo.icon)
|
|
63
63
|
.setContentTitle("Incoming $callType call")
|
|
64
64
|
.setContentText(name)
|
|
65
|
-
|
|
65
|
+
|
|
66
|
+
.setPriority(NotificationCompat.PRIORITY_HIGH) //old was PRIORITY_MAX
|
|
66
67
|
.setCategory(NotificationCompat.CATEGORY_CALL)
|
|
67
68
|
.setOngoing(true)
|
|
68
69
|
.setAutoCancel(false)
|
|
69
|
-
|
|
70
|
+
|
|
71
|
+
.setFullScreenIntent(fullScreenPendingIntent, false) //can be true
|
|
70
72
|
.addAction(0, "Answer", fullScreenPendingIntent)
|
|
71
73
|
.addAction(0, "Decline", rejectPendingIntent)
|
|
72
74
|
|
package/app.plugin.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
///app.plugin.js
|
|
2
|
+
const { withPlugins } = require('@expo/config-plugins');
|
|
2
3
|
const withNativeCallVoip = require('./withNativeCallVoip');
|
|
4
|
+
const withCallNativeConfig = require('./withCallNativeConfig');
|
|
5
|
+
const withCallPermissions = require('./withCallPermissions');
|
|
3
6
|
|
|
4
|
-
module.exports = function (config) {
|
|
5
|
-
return
|
|
7
|
+
module.exports = function (config, props) {
|
|
8
|
+
return withPlugins(config, [
|
|
9
|
+
[withNativeCallVoip, props],
|
|
10
|
+
[withCallNativeConfig, props],
|
|
11
|
+
[withCallPermissions, props],
|
|
12
|
+
]);
|
|
6
13
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rns-nativecall",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "RNS nativecall component with native Android/iOS for handling native call ui, when app is not open or open.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"README.md",
|
|
45
45
|
"rns-nativecall.podspec",
|
|
46
46
|
"withCallNativeConfig.js",
|
|
47
|
+
"withCallPermissions.js",
|
|
47
48
|
"withNativeCallVoip.js"
|
|
48
49
|
],
|
|
49
50
|
"peerDependencies": {
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const { withAndroidManifest } = require("@expo/config-plugins");
|
|
2
|
+
|
|
3
|
+
/** 2. ANDROID MANIFEST MOD **/
|
|
4
|
+
function withCallPermissions(config) {
|
|
5
|
+
return withAndroidManifest(config, async (config) => {
|
|
6
|
+
const androidManifest = config.modResults.manifest;
|
|
7
|
+
|
|
8
|
+
// 1. Add the Full Screen Intent Permission
|
|
9
|
+
if (!androidManifest["uses-permission"]) {
|
|
10
|
+
androidManifest["uses-permission"] = [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const hasPermission = androidManifest["uses-permission"].some(
|
|
14
|
+
(p) => p.$["android:name"] === "android.permission.USE_FULL_SCREEN_INTENT"
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
if (!hasPermission) {
|
|
18
|
+
androidManifest["uses-permission"].push({
|
|
19
|
+
$: { "android:name": "android.permission.USE_FULL_SCREEN_INTENT" },
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 2. Ensure the Activity has the correct flags to appear over lockscreen
|
|
24
|
+
const mainApplication = androidManifest.application[0];
|
|
25
|
+
const mainActivity = mainApplication.activity.find(
|
|
26
|
+
(a) => a.$["android:name"] === ".MainActivity"
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
if (mainActivity) {
|
|
30
|
+
mainActivity.$["android:showOnLockScreen"] = "true";
|
|
31
|
+
mainActivity.$["android:lockTaskMode"] = "if_whitelisted";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return config;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = (config) => {
|
|
39
|
+
return withPlugins(config, [withCallPermissions]);
|
|
40
|
+
};
|
package/withNativeCallVoip.js
CHANGED
|
@@ -1,46 +1,140 @@
|
|
|
1
1
|
const { withAndroidManifest, withInfoPlist, withPlugins, withMainActivity } = require('@expo/config-plugins');
|
|
2
2
|
|
|
3
|
+
/** 1. ANDROID MAIN ACTIVITY MOD **/
|
|
4
|
+
// function withMainActivityDataFix(config) {
|
|
5
|
+
// return withMainActivity(config, (config) => {
|
|
6
|
+
// let contents = config.modResults.contents;
|
|
7
|
+
|
|
8
|
+
// // 1. Ensure necessary Imports are present
|
|
9
|
+
// if (!contents.includes('import android.content.Intent')) {
|
|
10
|
+
// contents = contents.replace(/package .*/, (match) => `${match}\n\nimport android.content.Intent`);
|
|
11
|
+
// }
|
|
12
|
+
// if (!contents.includes('import android.os.Bundle')) {
|
|
13
|
+
// contents = contents.replace(/package .*/, (match) => `${match}\n\nimport android.os.Bundle`);
|
|
14
|
+
// }
|
|
15
|
+
|
|
16
|
+
// // 2. Define the code blocks
|
|
17
|
+
// const onNewIntentCode = `
|
|
18
|
+
// override fun onNewIntent(intent: Intent) {
|
|
19
|
+
// super.onNewIntent(intent)
|
|
20
|
+
// setIntent(intent)
|
|
21
|
+
// }
|
|
22
|
+
// `;
|
|
23
|
+
|
|
24
|
+
// const onCreateCode = `
|
|
25
|
+
// override fun onCreate(savedInstanceState: Bundle?) {
|
|
26
|
+
// super.onCreate(savedInstanceState)
|
|
27
|
+
// // If woken up silently, move to back to prevent UI flicker
|
|
28
|
+
// if (intent.getBooleanExtra("background_wake", false)) {
|
|
29
|
+
// moveTaskToBack(true)
|
|
30
|
+
// }
|
|
31
|
+
// }
|
|
32
|
+
// `;
|
|
33
|
+
|
|
34
|
+
// // 3. Insert the codes before the last closing brace of the class
|
|
35
|
+
// if (!contents.includes('override fun onNewIntent')) {
|
|
36
|
+
// const lastBraceIndex = contents.lastIndexOf('}');
|
|
37
|
+
// contents = contents.slice(0, lastBraceIndex) + onNewIntentCode + contents.slice(lastBraceIndex);
|
|
38
|
+
// }
|
|
39
|
+
|
|
40
|
+
// if (!contents.includes('override fun onCreate')) {
|
|
41
|
+
// // Re-calculate lastBraceIndex because contents string has changed
|
|
42
|
+
// const lastBraceIndex = contents.lastIndexOf('}');
|
|
43
|
+
// contents = contents.slice(0, lastBraceIndex) + onCreateCode + contents.slice(lastBraceIndex);
|
|
44
|
+
// }
|
|
45
|
+
|
|
46
|
+
// config.modResults.contents = contents;
|
|
47
|
+
// return config;
|
|
48
|
+
// });
|
|
49
|
+
// }
|
|
50
|
+
|
|
3
51
|
/** 1. ANDROID MAIN ACTIVITY MOD **/
|
|
4
52
|
function withMainActivityDataFix(config) {
|
|
5
53
|
return withMainActivity(config, (config) => {
|
|
6
54
|
let contents = config.modResults.contents;
|
|
7
55
|
|
|
8
|
-
// 1.
|
|
9
|
-
|
|
10
|
-
|
|
56
|
+
// --- 1. Imports ---
|
|
57
|
+
const neededImports = [
|
|
58
|
+
'import android.view.WindowManager',
|
|
59
|
+
'import android.os.Build',
|
|
60
|
+
'import android.os.Bundle'
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
neededImports.forEach(imp => {
|
|
64
|
+
if (!contents.includes(imp)) {
|
|
65
|
+
contents = contents.replace(/package .*/, (match) => `${match}\n${imp}`);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// --- 2. Replace onCreate ---
|
|
70
|
+
// We look for the existing onCreate and replace the entire block with your version
|
|
71
|
+
const editedOnCreate = `
|
|
72
|
+
// override fun onCreate(savedInstanceState: Bundle?) {
|
|
73
|
+
// setTheme(R.style.AppTheme)
|
|
74
|
+
// super.onCreate(savedInstanceState)
|
|
75
|
+
|
|
76
|
+
// // --- LOCK SCREEN WAKE LOGIC ---
|
|
77
|
+
// // This allows the Activity to appear over the lock screen when Answer is pressed
|
|
78
|
+
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
79
|
+
// setShowWhenLocked(true)
|
|
80
|
+
// setTurnScreenOn(true)
|
|
81
|
+
// } else {
|
|
82
|
+
// @Suppress("DEPRECATION")
|
|
83
|
+
// window.addFlags(
|
|
84
|
+
// WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
85
|
+
// WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
86
|
+
// WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
87
|
+
// )
|
|
88
|
+
// }
|
|
89
|
+
// }
|
|
90
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
91
|
+
setTheme(R.style.AppTheme)
|
|
92
|
+
super.onCreate(savedInstanceState)
|
|
93
|
+
|
|
94
|
+
// Only wake the screen/bypass lock if we are coming from a notification interaction
|
|
95
|
+
// Otherwise, let the notification pill handle the UI.
|
|
96
|
+
if (intent?.action?.startsWith("ACTION_SHOW_UI") == true) {
|
|
97
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
98
|
+
setShowWhenLocked(true)
|
|
99
|
+
setTurnScreenOn(true)
|
|
100
|
+
} else {
|
|
101
|
+
@Suppress("DEPRECATION")
|
|
102
|
+
window.addFlags(
|
|
103
|
+
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
104
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
105
|
+
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
106
|
+
)
|
|
107
|
+
}
|
|
11
108
|
}
|
|
12
|
-
|
|
13
|
-
|
|
109
|
+
}
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
// Regex to find the existing onCreate block (including the setTheme and super calls)
|
|
116
|
+
const onCreateRegex = /override fun onCreate\(savedInstanceState: Bundle\?\).*?\{[\s\S]*?super\.onCreate\(null\)\n\s*\}/;
|
|
117
|
+
if (contents.match(onCreateRegex)) {
|
|
118
|
+
contents = contents.replace(onCreateRegex, editedOnCreate);
|
|
14
119
|
}
|
|
15
120
|
|
|
16
|
-
//
|
|
121
|
+
// --- 3. Update createReactActivityDelegate ---
|
|
122
|
+
// Removing the "object :" and the empty trailing block "{})" to match your edited version
|
|
123
|
+
contents = contents.replace(
|
|
124
|
+
/return ReactActivityDelegateWrapper\([\s\S]*?object : (DefaultReactActivityDelegate\([\s\S]*?\))\{\}\)/,
|
|
125
|
+
'return ReactActivityDelegateWrapper($1)'
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// --- 4. Ensure onNewIntent exists ---
|
|
17
129
|
const onNewIntentCode = `
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`;
|
|
23
|
-
|
|
24
|
-
const onCreateCode = `
|
|
25
|
-
override fun onCreate(savedInstanceState: Bundle?) {
|
|
26
|
-
super.onCreate(savedInstanceState)
|
|
27
|
-
// If woken up silently, move to back to prevent UI flicker
|
|
28
|
-
if (intent.getBooleanExtra("background_wake", false)) {
|
|
29
|
-
moveTaskToBack(true)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
`;
|
|
130
|
+
override fun onNewIntent(intent: Intent) {
|
|
131
|
+
super.onNewIntent(intent)
|
|
132
|
+
setIntent(intent)
|
|
133
|
+
}`;
|
|
33
134
|
|
|
34
|
-
// 3. Insert the codes before the last closing brace of the class
|
|
35
135
|
if (!contents.includes('override fun onNewIntent')) {
|
|
36
136
|
const lastBraceIndex = contents.lastIndexOf('}');
|
|
37
|
-
contents = contents.slice(0, lastBraceIndex) + onNewIntentCode + contents.slice(lastBraceIndex);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!contents.includes('override fun onCreate')) {
|
|
41
|
-
// Re-calculate lastBraceIndex because contents string has changed
|
|
42
|
-
const lastBraceIndex = contents.lastIndexOf('}');
|
|
43
|
-
contents = contents.slice(0, lastBraceIndex) + onCreateCode + contents.slice(lastBraceIndex);
|
|
137
|
+
contents = contents.slice(0, lastBraceIndex) + onNewIntentCode + "\n" + contents.slice(lastBraceIndex);
|
|
44
138
|
}
|
|
45
139
|
|
|
46
140
|
config.modResults.contents = contents;
|