rns-nativecall 1.2.3 → 1.2.4
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/android/src/main/java/com/rnsnativecall/CallMessagingService.kt +1 -58
- package/android/src/main/java/com/rnsnativecall/NativeCallManager.kt +98 -126
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/android/src/main/res/drawable/circle_background.xml +0 -4
- package/android/src/main/res/drawable/ic_call_answer_white.xml +0 -9
- package/android/src/main/res/drawable/ic_call_end_white.xml +0 -9
- package/android/src/main/res/layout/activity_incoming_call.xml +0 -139
|
@@ -32,7 +32,7 @@ class CallMessagingService : FirebaseMessagingService() {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
NativeCallManager.dismissIncomingCall(context, uuid)
|
|
35
|
-
showMissedCallNotification(context, data
|
|
35
|
+
NativeCallManager.showMissedCallNotification(context, data)
|
|
36
36
|
return
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -73,63 +73,6 @@ class CallMessagingService : FirebaseMessagingService() {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
private fun showMissedCallNotification(
|
|
77
|
-
context: Context,
|
|
78
|
-
data: Map<String, String>,
|
|
79
|
-
uuid: String,
|
|
80
|
-
) {
|
|
81
|
-
val name = data["name"] ?: "Unknown"
|
|
82
|
-
val callType = data["callType"] ?: "video"
|
|
83
|
-
val channelId = "missed_calls"
|
|
84
|
-
|
|
85
|
-
val notificationManager =
|
|
86
|
-
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
87
|
-
|
|
88
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
89
|
-
val channel =
|
|
90
|
-
NotificationChannel(
|
|
91
|
-
channelId,
|
|
92
|
-
"Missed Calls",
|
|
93
|
-
NotificationManager.IMPORTANCE_DEFAULT,
|
|
94
|
-
).apply { description = "Missed call notifications" }
|
|
95
|
-
notificationManager.createNotificationChannel(channel)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
val iconResId =
|
|
99
|
-
context.resources
|
|
100
|
-
.getIdentifier("ic_missed_call", "drawable", context.packageName)
|
|
101
|
-
.takeIf { it != 0 } ?: android.R.drawable.sym_call_missed
|
|
102
|
-
val appName = context.applicationInfo.loadLabel(context.packageManager).toString()
|
|
103
|
-
|
|
104
|
-
val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
|
|
105
|
-
launchIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
106
|
-
val pendingIntent =
|
|
107
|
-
PendingIntent.getActivity(
|
|
108
|
-
context,
|
|
109
|
-
uuid.hashCode(),
|
|
110
|
-
launchIntent,
|
|
111
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
112
|
-
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
113
|
-
} else {
|
|
114
|
-
PendingIntent.FLAG_UPDATE_CURRENT
|
|
115
|
-
},
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
val builder =
|
|
119
|
-
NotificationCompat
|
|
120
|
-
.Builder(context, channelId)
|
|
121
|
-
.setSmallIcon(iconResId)
|
|
122
|
-
.setContentTitle("$appName • Missed $callType call")
|
|
123
|
-
.setContentText("You missed a call from $name")
|
|
124
|
-
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
125
|
-
.setAutoCancel(true)
|
|
126
|
-
.setCategory(NotificationCompat.CATEGORY_MISSED_CALL)
|
|
127
|
-
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
128
|
-
.setContentIntent(pendingIntent)
|
|
129
|
-
|
|
130
|
-
notificationManager.notify(uuid.hashCode(), builder.build())
|
|
131
|
-
}
|
|
132
|
-
|
|
133
76
|
private fun isAppInForeground(context: Context): Boolean {
|
|
134
77
|
val activityManager =
|
|
135
78
|
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
|
@@ -14,7 +14,9 @@ import androidx.core.app.Person
|
|
|
14
14
|
import androidx.core.content.ContextCompat
|
|
15
15
|
|
|
16
16
|
object NativeCallManager {
|
|
17
|
-
const val channelId = "
|
|
17
|
+
const val channelId = "CALL_CHANNEL_URGENT_V2"
|
|
18
|
+
private const val MISSED_CHANNEL_ID = "missed_calls"
|
|
19
|
+
|
|
18
20
|
private var currentCallData: Map<String, String>? = null
|
|
19
21
|
|
|
20
22
|
@JvmStatic internal var pendingCallNotification: Notification? = null
|
|
@@ -23,6 +25,37 @@ object NativeCallManager {
|
|
|
23
25
|
|
|
24
26
|
fun getCurrentCallData(): Map<String, String>? = currentCallData
|
|
25
27
|
|
|
28
|
+
// --- REUSABLE HELPERS ---
|
|
29
|
+
|
|
30
|
+
private fun getPendingIntentFlags(): Int =
|
|
31
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
32
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
33
|
+
} else {
|
|
34
|
+
PendingIntent.FLAG_UPDATE_CURRENT
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private fun getResourceColor(context: Context): Int {
|
|
38
|
+
val colorId = context.resources.getIdentifier("notification_icon_color", "color", context.packageName)
|
|
39
|
+
return if (colorId != 0) ContextCompat.getColor(context, colorId) else Color.parseColor("#ffffff")
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private fun createCallIntent(
|
|
43
|
+
context: Context,
|
|
44
|
+
targetClass: Class<*>,
|
|
45
|
+
actionName: String?,
|
|
46
|
+
uuid: String,
|
|
47
|
+
data: Map<String, String>,
|
|
48
|
+
): Intent =
|
|
49
|
+
Intent(context, targetClass).apply {
|
|
50
|
+
action = actionName
|
|
51
|
+
putExtra("EXTRA_CALL_UUID", uuid)
|
|
52
|
+
data.forEach { (k, v) -> putExtra(k, v) }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private fun getNotificationManager(context: Context) = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
56
|
+
|
|
57
|
+
// --- MAIN LOGIC ---
|
|
58
|
+
|
|
26
59
|
fun handleIncomingPush(
|
|
27
60
|
context: Context,
|
|
28
61
|
data: Map<String, String>,
|
|
@@ -32,45 +65,33 @@ object NativeCallManager {
|
|
|
32
65
|
val uuid = data["callUuid"] ?: return@post
|
|
33
66
|
val name = data["name"] ?: "Someone"
|
|
34
67
|
val callType = data["callType"] ?: "audio"
|
|
35
|
-
val isVideo = callType.equals("video", ignoreCase = true)
|
|
36
68
|
val notificationId = uuid.hashCode()
|
|
69
|
+
val flags = getPendingIntentFlags()
|
|
37
70
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
val pendingFlags =
|
|
41
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
42
|
-
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
43
|
-
} else {
|
|
44
|
-
PendingIntent.FLAG_UPDATE_CURRENT
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Intents
|
|
71
|
+
// 1. Setup Intents using helper
|
|
48
72
|
val overlayIntent =
|
|
49
|
-
|
|
50
|
-
putExtra("EXTRA_CALL_UUID", uuid)
|
|
51
|
-
data.forEach { (k, v) -> putExtra(k, v) }
|
|
73
|
+
createCallIntent(context, NotificationOverlayActivity::class.java, null, uuid, data).apply {
|
|
52
74
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_USER_ACTION)
|
|
53
75
|
}
|
|
54
|
-
val
|
|
55
|
-
|
|
56
|
-
val
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
val fullScreenPI = PendingIntent.getActivity(context, notificationId, overlayIntent, flags)
|
|
77
|
+
|
|
78
|
+
val answerPI =
|
|
79
|
+
PendingIntent.getBroadcast(
|
|
80
|
+
context,
|
|
81
|
+
notificationId + 1,
|
|
82
|
+
createCallIntent(context, CallActionReceiver::class.java, "ACTION_ANSWER", uuid, data),
|
|
83
|
+
flags,
|
|
84
|
+
)
|
|
63
85
|
|
|
64
|
-
val
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
86
|
+
val rejectPI =
|
|
87
|
+
PendingIntent.getBroadcast(
|
|
88
|
+
context,
|
|
89
|
+
notificationId + 2,
|
|
90
|
+
createCallIntent(context, CallActionReceiver::class.java, "ACTION_REJECT", uuid, data),
|
|
91
|
+
flags,
|
|
92
|
+
)
|
|
71
93
|
|
|
72
|
-
// Channel
|
|
73
|
-
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
94
|
+
// 2. Setup Urgent Channel
|
|
74
95
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
75
96
|
val channel =
|
|
76
97
|
NotificationChannel(channelId, "Incoming Calls", NotificationManager.IMPORTANCE_HIGH).apply {
|
|
@@ -78,7 +99,7 @@ object NativeCallManager {
|
|
|
78
99
|
enableVibration(true)
|
|
79
100
|
setBypassDnd(true)
|
|
80
101
|
setSound(
|
|
81
|
-
|
|
102
|
+
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE),
|
|
82
103
|
AudioAttributes
|
|
83
104
|
.Builder()
|
|
84
105
|
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
|
|
@@ -86,31 +107,14 @@ object NativeCallManager {
|
|
|
86
107
|
.build(),
|
|
87
108
|
)
|
|
88
109
|
}
|
|
89
|
-
|
|
110
|
+
getNotificationManager(context).createNotificationChannel(channel)
|
|
90
111
|
}
|
|
91
112
|
|
|
113
|
+
// 3. Resources & Style
|
|
92
114
|
val iconId =
|
|
93
115
|
context.resources
|
|
94
116
|
.getIdentifier("notification_icon", "drawable", context.packageName)
|
|
95
|
-
.let {
|
|
96
|
-
if (id != 0) {
|
|
97
|
-
id // Found the one you saw in the folder!
|
|
98
|
-
} else {
|
|
99
|
-
// Fallback chain if notification_icon is missing
|
|
100
|
-
val shellId = context.resources.getIdentifier("shell_notification_icon", "drawable", context.packageName)
|
|
101
|
-
if (shellId != 0) shellId else context.applicationInfo.icon
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
val colorId = context.resources.getIdentifier("notification_icon_color", "color", context.packageName)
|
|
106
|
-
|
|
107
|
-
val iconColor =
|
|
108
|
-
if (colorId != 0) {
|
|
109
|
-
ContextCompat.getColor(context, colorId)
|
|
110
|
-
} else {
|
|
111
|
-
// Fallback to a default blue or grey if they didn't provide a color
|
|
112
|
-
Color.parseColor("#ffffff")
|
|
113
|
-
}
|
|
117
|
+
.let { if (it != 0) it else context.applicationInfo.icon }
|
|
114
118
|
|
|
115
119
|
val caller =
|
|
116
120
|
Person
|
|
@@ -118,62 +122,42 @@ object NativeCallManager {
|
|
|
118
122
|
.setName(name)
|
|
119
123
|
.setImportant(true)
|
|
120
124
|
.build()
|
|
125
|
+
val incomingCallStyle = NotificationCompat.CallStyle.forIncomingCall(caller, rejectPI, answerPI)
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
NotificationCompat.CallStyle.forIncomingCall(
|
|
124
|
-
caller,
|
|
125
|
-
rejectPendingIntent,
|
|
126
|
-
answerPendingIntent,
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
if (isVideo) {
|
|
127
|
+
if (callType.equals("video", ignoreCase = true)) {
|
|
130
128
|
try {
|
|
131
|
-
|
|
129
|
+
incomingCallStyle.setIsVideo(true)
|
|
132
130
|
} catch (e: Exception) {
|
|
133
|
-
//
|
|
131
|
+
// No-op
|
|
134
132
|
}
|
|
135
133
|
}
|
|
136
|
-
|
|
137
|
-
val
|
|
134
|
+
// 4. Build Notification
|
|
135
|
+
val notification =
|
|
138
136
|
NotificationCompat
|
|
139
137
|
.Builder(context, channelId)
|
|
140
138
|
.setSmallIcon(iconId)
|
|
141
|
-
// 1. FOR ANDROID 8/9: They prioritize ContentTitle over the Style's internal logic.
|
|
142
|
-
// We include the name here so it's impossible to miss.
|
|
143
139
|
.setContentTitle("Incoming $callType Call from $name")
|
|
144
|
-
// 2. FOR ALL VERSIONS: This helps fill the "Status" line below the name.
|
|
145
140
|
.setContentText("Incoming $callType Call")
|
|
146
|
-
// 3. FOR ANDROID 12+: This places the text in the header next to the App Name.
|
|
147
141
|
.setSubText("Incoming $callType Call")
|
|
148
|
-
.setColor(
|
|
142
|
+
.setColor(getResourceColor(context))
|
|
149
143
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
150
144
|
.setCategory(NotificationCompat.CATEGORY_CALL)
|
|
151
145
|
.setOngoing(true)
|
|
152
|
-
.setFullScreenIntent(
|
|
153
|
-
.setStyle(
|
|
146
|
+
.setFullScreenIntent(fullScreenPI, true)
|
|
147
|
+
.setStyle(incomingCallStyle)
|
|
154
148
|
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
|
149
|
+
.build()
|
|
155
150
|
|
|
156
|
-
val notification = builder.build()
|
|
157
151
|
pendingCallNotification = notification
|
|
158
152
|
pendingNotificationId = notificationId
|
|
159
153
|
|
|
160
|
-
//
|
|
161
|
-
|
|
162
|
-
ContextCompat.startForegroundService(context,
|
|
163
|
-
|
|
164
|
-
// 2. Stop the SILENT Wake service (which no longer needs DATA_SYNC)
|
|
154
|
+
// 5. Execution
|
|
155
|
+
getNotificationManager(context).notify(notificationId, notification)
|
|
156
|
+
ContextCompat.startForegroundService(context, Intent(context, CallUiForegroundService::class.java))
|
|
165
157
|
CallForegroundService.stop(context)
|
|
166
158
|
}
|
|
167
159
|
}
|
|
168
160
|
|
|
169
|
-
fun refreshNotificationOnly(
|
|
170
|
-
context: Context,
|
|
171
|
-
uuid: String,
|
|
172
|
-
) {
|
|
173
|
-
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
174
|
-
manager.cancel(uuid.hashCode())
|
|
175
|
-
}
|
|
176
|
-
|
|
177
161
|
fun showMissedCallNotification(
|
|
178
162
|
context: Context,
|
|
179
163
|
data: Map<String, String>,
|
|
@@ -181,57 +165,46 @@ object NativeCallManager {
|
|
|
181
165
|
val uuid = data["callUuid"] ?: return
|
|
182
166
|
val name = data["name"] ?: "Unknown"
|
|
183
167
|
val callType = data["callType"] ?: "video"
|
|
184
|
-
val channelId = "missed_calls"
|
|
185
|
-
|
|
186
|
-
val notificationManager =
|
|
187
|
-
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
188
168
|
|
|
169
|
+
// Setup Missed Channel
|
|
189
170
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
190
|
-
val channel =
|
|
191
|
-
|
|
192
|
-
channelId,
|
|
193
|
-
"Missed Calls",
|
|
194
|
-
NotificationManager.IMPORTANCE_DEFAULT,
|
|
195
|
-
).apply { description = "Missed call notifications" }
|
|
196
|
-
notificationManager.createNotificationChannel(channel)
|
|
171
|
+
val channel = NotificationChannel(MISSED_CHANNEL_ID, "Missed Calls", NotificationManager.IMPORTANCE_DEFAULT)
|
|
172
|
+
getNotificationManager(context).createNotificationChannel(channel)
|
|
197
173
|
}
|
|
198
174
|
|
|
199
|
-
// Use your custom notification icon if available, fallback to system missed call icon
|
|
200
175
|
val iconResId =
|
|
201
176
|
context.resources
|
|
202
|
-
.getIdentifier("
|
|
203
|
-
.
|
|
204
|
-
|
|
205
|
-
val
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
context,
|
|
213
|
-
uuid.hashCode(),
|
|
214
|
-
launchIntent,
|
|
215
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
216
|
-
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
217
|
-
} else {
|
|
218
|
-
PendingIntent.FLAG_UPDATE_CURRENT
|
|
219
|
-
},
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
val builder =
|
|
177
|
+
.getIdentifier("ic_missed_call", "drawable", context.packageName)
|
|
178
|
+
.let { if (it != 0) it else android.R.drawable.sym_call_missed }
|
|
179
|
+
|
|
180
|
+
val launchIntent =
|
|
181
|
+
context.packageManager.getLaunchIntentForPackage(context.packageName)?.apply {
|
|
182
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
183
|
+
}
|
|
184
|
+
val pendingIntent = PendingIntent.getActivity(context, uuid.hashCode(), launchIntent, getPendingIntentFlags())
|
|
185
|
+
|
|
186
|
+
val notification =
|
|
223
187
|
NotificationCompat
|
|
224
|
-
.Builder(context,
|
|
188
|
+
.Builder(context, MISSED_CHANNEL_ID)
|
|
225
189
|
.setSmallIcon(iconResId)
|
|
226
|
-
.setContentTitle(
|
|
227
|
-
.setContentText("You missed a call from $name")
|
|
190
|
+
.setContentTitle(context.applicationInfo.loadLabel(context.packageManager).toString())
|
|
191
|
+
.setContentText("You missed a $callType call from $name")
|
|
228
192
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
193
|
+
.setColor(getResourceColor(context))
|
|
229
194
|
.setAutoCancel(true)
|
|
230
195
|
.setCategory(NotificationCompat.CATEGORY_MISSED_CALL)
|
|
231
196
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
232
197
|
.setContentIntent(pendingIntent)
|
|
198
|
+
.build()
|
|
233
199
|
|
|
234
|
-
|
|
200
|
+
getNotificationManager(context).notify(uuid.hashCode() + 10000, notification)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
fun refreshNotificationOnly(
|
|
204
|
+
context: Context,
|
|
205
|
+
uuid: String,
|
|
206
|
+
) {
|
|
207
|
+
getNotificationManager(context).cancel(uuid.hashCode())
|
|
235
208
|
}
|
|
236
209
|
|
|
237
210
|
fun dismissIncomingCall(
|
|
@@ -241,8 +214,7 @@ object NativeCallManager {
|
|
|
241
214
|
pendingCallNotification = null
|
|
242
215
|
pendingNotificationId = null
|
|
243
216
|
currentCallData = null
|
|
244
|
-
|
|
245
|
-
uuid?.let { manager.cancel(it.hashCode()) }
|
|
217
|
+
uuid?.let { getNotificationManager(context).cancel(it.hashCode()) }
|
|
246
218
|
context.stopService(Intent(context, CallUiForegroundService::class.java))
|
|
247
219
|
}
|
|
248
220
|
}
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
android:width="24dp"
|
|
3
|
-
android:height="24dp"
|
|
4
|
-
android:viewportWidth="24"
|
|
5
|
-
android:viewportHeight="24">
|
|
6
|
-
<path
|
|
7
|
-
android:fillColor="#FFFFFF"
|
|
8
|
-
android:pathData="M20,15.5c-1.25,0 -2.45,-0.2 -3.57,-0.57a1.02,1.02 0,0 0,-1.02 0.24l-2.2,2.2a15.05,15.05 0,0 1,-6.59 -6.59l2.2,-2.2a1.02,1.02 0,0 0,0.24 -1.02A11.36,11.36 0,0 1,8.5 4c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1c0,9.39 7.61,17 17,17c0.55,0 1,-0.45 1,-1v-3.5c0,-0.55 -0.45,-1 -1,-1z" />
|
|
9
|
-
</vector>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
android:width="24dp"
|
|
3
|
-
android:height="24dp"
|
|
4
|
-
android:viewportWidth="24"
|
|
5
|
-
android:viewportHeight="24">
|
|
6
|
-
<path
|
|
7
|
-
android:fillColor="#FFFFFF"
|
|
8
|
-
android:pathData="M12,9c-1.6,0 -3.15,0.25 -4.6,0.72v3.1c0,0.39 -0.23,0.74 -0.56,0.9 -0.98,0.49 -1.65,1.45 -1.65,2.58c0,1.65 1.34,3 3,3h2v-3H8.1c0.01,-0.99 0.87,-1.8 1.85,-1.8c0.51,0 1,-0.21 1.35,-0.56l1.8,-1.8C13.04,9.3 12.55,9 12,9z" />
|
|
9
|
-
</vector>
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<androidx.constraintlayout.widget.ConstraintLayout
|
|
3
|
-
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
4
|
-
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
5
|
-
xmlns:tools="http://schemas.android.com/tools"
|
|
6
|
-
android:layout_width="match_parent"
|
|
7
|
-
android:layout_height="match_parent"
|
|
8
|
-
android:background="#212121">
|
|
9
|
-
|
|
10
|
-
<!-- Profile Section -->
|
|
11
|
-
<ImageView
|
|
12
|
-
android:id="@+id/profileImage"
|
|
13
|
-
android:layout_width="200dp"
|
|
14
|
-
android:layout_height="200dp"
|
|
15
|
-
android:scaleType="centerCrop"
|
|
16
|
-
android:background="@drawable/circle_background"
|
|
17
|
-
app:layout_constraintTop_toTopOf="parent"
|
|
18
|
-
app:layout_constraintStart_toStartOf="parent"
|
|
19
|
-
app:layout_constraintEnd_toEndOf="parent"
|
|
20
|
-
app:layout_constraintBottom_toTopOf="@id/usernameText"
|
|
21
|
-
app:layout_constraintVertical_chainStyle="packed"
|
|
22
|
-
app:layout_constraintVertical_bias="0.35"
|
|
23
|
-
tools:src="@drawable/ic_profile_placeholder" />
|
|
24
|
-
|
|
25
|
-
<!-- Optional: Blur effect for discreet mode (apply programmatically) -->
|
|
26
|
-
<!-- You can use RenderScript or BlurView library for real blur -->
|
|
27
|
-
|
|
28
|
-
<TextView
|
|
29
|
-
android:id="@+id/usernameText"
|
|
30
|
-
android:layout_width="wrap_content"
|
|
31
|
-
android:layout_height="wrap_content"
|
|
32
|
-
android:text="John Doe"
|
|
33
|
-
android:textColor="#FFFFFF"
|
|
34
|
-
android:textSize="32sp"
|
|
35
|
-
android:fontFamily="sans-serif-medium"
|
|
36
|
-
android:layout_marginTop="20dp"
|
|
37
|
-
app:layout_constraintTop_toBottomOf="@id/profileImage"
|
|
38
|
-
app:layout_constraintStart_toStartOf="parent"
|
|
39
|
-
app:layout_constraintEnd_toEndOf="parent"
|
|
40
|
-
tools:text="John Doe" />
|
|
41
|
-
|
|
42
|
-
<TextView
|
|
43
|
-
android:id="@+id/callStatusText"
|
|
44
|
-
android:layout_width="wrap_content"
|
|
45
|
-
android:layout_height="wrap_content"
|
|
46
|
-
android:text="Incoming Video Call..."
|
|
47
|
-
android:textColor="#FFFFFF"
|
|
48
|
-
android:textSize="18sp"
|
|
49
|
-
android:alpha="0.8"
|
|
50
|
-
android:layout_marginTop="10dp"
|
|
51
|
-
app:layout_constraintTop_toBottomOf="@id/usernameText"
|
|
52
|
-
app:layout_constraintStart_toStartOf="parent"
|
|
53
|
-
app:layout_constraintEnd_toEndOf="parent" />
|
|
54
|
-
|
|
55
|
-
<!-- Action Buttons Container -->
|
|
56
|
-
<LinearLayout
|
|
57
|
-
android:id="@+id/buttonContainer"
|
|
58
|
-
android:layout_width="match_parent"
|
|
59
|
-
android:layout_height="wrap_content"
|
|
60
|
-
android:orientation="horizontal"
|
|
61
|
-
android:gravity="center"
|
|
62
|
-
android:paddingBottom="100dp"
|
|
63
|
-
app:layout_constraintBottom_toBottomOf="parent"
|
|
64
|
-
app:layout_constraintStart_toStartOf="parent"
|
|
65
|
-
app:layout_constraintEnd_toEndOf="parent">
|
|
66
|
-
|
|
67
|
-
<!-- Decline Button -->
|
|
68
|
-
<LinearLayout
|
|
69
|
-
android:layout_width="wrap_content"
|
|
70
|
-
android:layout_height="wrap_content"
|
|
71
|
-
android:orientation="vertical"
|
|
72
|
-
android:gravity="center"
|
|
73
|
-
android:layout_marginEnd="60dp">
|
|
74
|
-
|
|
75
|
-
<androidx.cardview.widget.CardView
|
|
76
|
-
android:layout_width="70dp"
|
|
77
|
-
android:layout_height="70dp"
|
|
78
|
-
app:cardCornerRadius="35dp"
|
|
79
|
-
app:cardElevation="8dp"
|
|
80
|
-
app:cardBackgroundColor="#FF3B30">
|
|
81
|
-
|
|
82
|
-
<ImageView
|
|
83
|
-
android:layout_width="match_parent"
|
|
84
|
-
android:layout_height="match_parent"
|
|
85
|
-
android:src="@drawable/ic_call_end_white"
|
|
86
|
-
android:padding="18dp"
|
|
87
|
-
android:tint="#FFFFFF" />
|
|
88
|
-
|
|
89
|
-
</androidx.cardview.widget.CardView>
|
|
90
|
-
|
|
91
|
-
<TextView
|
|
92
|
-
android:layout_width="wrap_content"
|
|
93
|
-
android:layout_height="wrap_content"
|
|
94
|
-
android:text="Decline"
|
|
95
|
-
android:textColor="#FFFFFF"
|
|
96
|
-
android:textSize="16sp"
|
|
97
|
-
android:fontFamily="sans-serif-medium"
|
|
98
|
-
android:layout_marginTop="10dp" />
|
|
99
|
-
|
|
100
|
-
</LinearLayout>
|
|
101
|
-
|
|
102
|
-
<!-- Accept Button -->
|
|
103
|
-
<LinearLayout
|
|
104
|
-
android:layout_width="wrap_content"
|
|
105
|
-
android:layout_height="wrap_content"
|
|
106
|
-
android:orientation="vertical"
|
|
107
|
-
android:gravity="center"
|
|
108
|
-
android:layout_marginStart="60dp">
|
|
109
|
-
|
|
110
|
-
<androidx.cardview.widget.CardView
|
|
111
|
-
android:layout_width="70dp"
|
|
112
|
-
android:layout_height="70dp"
|
|
113
|
-
app:cardCornerRadius="35dp"
|
|
114
|
-
app:cardElevation="8dp"
|
|
115
|
-
app:cardBackgroundColor="#4CD964">
|
|
116
|
-
|
|
117
|
-
<ImageView
|
|
118
|
-
android:layout_width="match_parent"
|
|
119
|
-
android:layout_height="match_parent"
|
|
120
|
-
android:src="@drawable/ic_call_answer_white"
|
|
121
|
-
android:padding="18dp"
|
|
122
|
-
android:tint="#FFFFFF" />
|
|
123
|
-
|
|
124
|
-
</androidx.cardview.widget.CardView>
|
|
125
|
-
|
|
126
|
-
<TextView
|
|
127
|
-
android:layout_width="wrap_content"
|
|
128
|
-
android:layout_height="wrap_content"
|
|
129
|
-
android:text="Accept"
|
|
130
|
-
android:textColor="#FFFFFF"
|
|
131
|
-
android:textSize="16sp"
|
|
132
|
-
android:fontFamily="sans-serif-medium"
|
|
133
|
-
android:layout_marginTop="10dp" />
|
|
134
|
-
|
|
135
|
-
</LinearLayout>
|
|
136
|
-
|
|
137
|
-
</LinearLayout>
|
|
138
|
-
|
|
139
|
-
</androidx.constraintlayout.widget.ConstraintLayout>
|