@qusaieilouti99/call-manager 0.1.95 → 0.1.97
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/margelo/nitro/qusaieilouti99/callmanager/CallActivity.kt +235 -94
- package/package.json +1 -1
- package/android/src/main/res/drawable/answer_btn_bg.xml +0 -12
- package/android/src/main/res/drawable/button_shadow.xml +0 -9
- package/android/src/main/res/drawable/decline_btn_bg.xml +0 -12
- package/android/src/main/res/drawable/default_avatar.xml +0 -10
- package/android/src/main/res/drawable/professional_bg.xml +0 -21
- package/android/src/main/res/drawable/profile_bg.xml +0 -5
- package/android/src/main/res/drawable/profile_image_bg.xml +0 -4
- package/android/src/main/res/drawable/pulse_ring_middle.xml +0 -5
- package/android/src/main/res/drawable/pulse_ring_outer.xml +0 -5
- package/android/src/main/res/drawable/quick_action_bg.xml +0 -10
- package/android/src/main/res/layout/activity_call.xml +0 -244
|
@@ -4,33 +4,37 @@ package com.margelo.nitro.qusaieilouti99.callmanager
|
|
|
4
4
|
import android.app.Activity
|
|
5
5
|
import android.app.KeyguardManager
|
|
6
6
|
import android.content.Context
|
|
7
|
+
import android.graphics.Color
|
|
8
|
+
import android.graphics.RenderEffect
|
|
9
|
+
import android.graphics.Shader
|
|
10
|
+
import android.graphics.drawable.Drawable
|
|
11
|
+
import android.graphics.drawable.GradientDrawable
|
|
7
12
|
import android.os.Build
|
|
8
13
|
import android.os.Bundle
|
|
9
14
|
import android.os.Handler
|
|
10
15
|
import android.os.Looper
|
|
11
16
|
import android.util.Log
|
|
17
|
+
import android.util.TypedValue
|
|
18
|
+
import android.view.Gravity
|
|
19
|
+
import android.view.View
|
|
20
|
+
import android.view.ViewGroup
|
|
12
21
|
import android.view.WindowManager
|
|
13
|
-
import android.widget.
|
|
22
|
+
import android.widget.FrameLayout
|
|
23
|
+
import android.widget.ImageView
|
|
24
|
+
import android.widget.LinearLayout
|
|
14
25
|
import android.widget.TextView
|
|
26
|
+
import androidx.core.content.ContextCompat
|
|
27
|
+
import com.bumptech.glide.Glide
|
|
15
28
|
|
|
16
|
-
/**
|
|
17
|
-
* Full‐screen incoming‐call UI. Implements CallEndListener
|
|
18
|
-
* so it always auto‐finishes when the engine ends the call.
|
|
19
|
-
* **SAMSUNG FIX**: Enhanced lock screen bypass for Samsung devices
|
|
20
|
-
*/
|
|
21
29
|
class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ANSWER, DECLINE, TIMEOUT, MANUAL_DISMISS, EXTERNAL_END
|
|
25
|
-
}
|
|
26
|
-
|
|
30
|
+
private enum class FinishReason { ANSWER, DECLINE, TIMEOUT,
|
|
31
|
+
MANUAL_DISMISS, EXTERNAL_END }
|
|
27
32
|
private var finishReason: FinishReason? = null
|
|
28
33
|
private var callId: String = ""
|
|
29
34
|
private var callType: String = "Audio"
|
|
30
|
-
|
|
31
|
-
private val
|
|
35
|
+
private val timeoutMs = 60_000L
|
|
36
|
+
private val handler = Handler(Looper.getMainLooper())
|
|
32
37
|
private val timeoutRunnable = Runnable {
|
|
33
|
-
Log.d(TAG, "CallActivity timeout triggered for callId: $callId")
|
|
34
38
|
finishReason = FinishReason.TIMEOUT
|
|
35
39
|
CallEngine.stopRingtone()
|
|
36
40
|
CallEngine.cancelIncomingCallUI()
|
|
@@ -40,55 +44,214 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
40
44
|
|
|
41
45
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
42
46
|
super.onCreate(savedInstanceState)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
setupLockScreenBypass(isSamsungLockScreenBypass)
|
|
47
|
+
val isSamsungBypass = intent.getBooleanExtra(
|
|
48
|
+
"SAMSUNG_LOCK_SCREEN_BYPASS", false
|
|
49
|
+
)
|
|
50
|
+
setupLockScreenBypass(isSamsungBypass)
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// Read incoming‐call params
|
|
52
|
+
// Read params
|
|
52
53
|
callId = intent.getStringExtra("callId") ?: ""
|
|
53
54
|
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
54
|
-
|
|
55
|
+
val callerName = intent.getStringExtra("callerName") ?: "Unknown"
|
|
56
|
+
val avatarUrl = intent.getStringExtra("callerAvatar")
|
|
55
57
|
|
|
56
|
-
// Register for call‐end callbacks BEFORE timeout or user can dismiss
|
|
57
58
|
CallEngine.registerCallEndListener(this)
|
|
59
|
+
buildUi(callerName, avatarUrl)
|
|
60
|
+
handler.postDelayed(timeoutRunnable, timeoutMs)
|
|
61
|
+
Log.d(TAG, "CallActivity setup complete for $callId")
|
|
62
|
+
}
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
val
|
|
61
|
-
|
|
64
|
+
private fun buildUi(name: String, avatarUrl: String?) {
|
|
65
|
+
val root = FrameLayout(this).apply {
|
|
66
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
67
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
68
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
69
|
+
)
|
|
70
|
+
}
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
// 1) Background image + blur
|
|
73
|
+
val bg = ImageView(this).apply {
|
|
74
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
75
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
76
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
77
|
+
)
|
|
78
|
+
scaleType = ImageView.ScaleType.CENTER_CROP
|
|
79
|
+
}
|
|
80
|
+
if (!avatarUrl.isNullOrEmpty()) {
|
|
81
|
+
Glide.with(this).load(avatarUrl).into(bg)
|
|
82
|
+
} else {
|
|
83
|
+
bg.setImageResource(android.R.drawable.sym_def_app_icon)
|
|
84
|
+
}
|
|
85
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
86
|
+
bg.setRenderEffect(
|
|
87
|
+
RenderEffect.createBlurEffect(25f, 25f, Shader.TileMode.CLAMP)
|
|
88
|
+
)
|
|
70
89
|
}
|
|
90
|
+
root.addView(bg)
|
|
71
91
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
92
|
+
// 2) Dark scrim
|
|
93
|
+
root.addView(View(this).apply {
|
|
94
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
95
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
96
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
97
|
+
)
|
|
98
|
+
setBackgroundColor(Color.parseColor("#80000000"))
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// 3) Top call-type label
|
|
102
|
+
val callTypeLabel = TextView(this).apply {
|
|
103
|
+
text = when (callType.lowercase()) {
|
|
104
|
+
"video" -> "Incoming video call"
|
|
105
|
+
else -> "Incoming audio call"
|
|
106
|
+
}
|
|
107
|
+
setTextColor(Color.WHITE)
|
|
108
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
|
|
109
|
+
gravity = Gravity.CENTER
|
|
110
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
111
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
112
|
+
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
113
|
+
).apply {
|
|
114
|
+
gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
|
115
|
+
topMargin = dp(40)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
root.addView(callTypeLabel)
|
|
119
|
+
|
|
120
|
+
// 4) Center content: profile + name
|
|
121
|
+
val centerCol = LinearLayout(this).apply {
|
|
122
|
+
orientation = LinearLayout.VERTICAL
|
|
123
|
+
gravity = Gravity.CENTER_HORIZONTAL
|
|
124
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
125
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
126
|
+
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
127
|
+
).apply {
|
|
128
|
+
gravity = Gravity.CENTER
|
|
129
|
+
topMargin = dp(20)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Profile circle
|
|
133
|
+
val profile = ImageView(this).apply {
|
|
134
|
+
val sz = dp(140)
|
|
135
|
+
layoutParams = LinearLayout.LayoutParams(sz, sz)
|
|
136
|
+
scaleType = ImageView.ScaleType.CENTER_CROP
|
|
137
|
+
background = GradientDrawable().apply {
|
|
138
|
+
shape = GradientDrawable.OVAL
|
|
139
|
+
setColor(Color.LTGRAY)
|
|
140
|
+
}
|
|
141
|
+
clipToOutline = true
|
|
142
|
+
}
|
|
143
|
+
if (!avatarUrl.isNullOrEmpty()) {
|
|
144
|
+
Glide.with(this).load(avatarUrl).circleCrop().into(profile)
|
|
145
|
+
}
|
|
146
|
+
centerCol.addView(profile)
|
|
147
|
+
|
|
148
|
+
// Caller name
|
|
149
|
+
centerCol.addView(TextView(this).apply {
|
|
150
|
+
text = name
|
|
151
|
+
setTextColor(Color.WHITE)
|
|
152
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 28f)
|
|
153
|
+
typeface = android.graphics.Typeface.DEFAULT_BOLD
|
|
154
|
+
gravity = Gravity.CENTER
|
|
155
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
156
|
+
ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
157
|
+
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
158
|
+
).apply { topMargin = dp(24) }
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
root.addView(centerCol)
|
|
162
|
+
|
|
163
|
+
// 5) Bottom actions
|
|
164
|
+
val actions = LinearLayout(this).apply {
|
|
165
|
+
orientation = LinearLayout.HORIZONTAL
|
|
166
|
+
gravity = Gravity.CENTER
|
|
167
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
168
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
169
|
+
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
170
|
+
).apply {
|
|
171
|
+
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
|
|
172
|
+
bottomMargin = dp(48)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
val declineBtn = createCircleButton(
|
|
177
|
+
android.R.drawable.ic_menu_close_clear_cancel,
|
|
178
|
+
Color.parseColor("#F44336")
|
|
179
|
+
).apply { setOnClickListener { onDecline() } }
|
|
180
|
+
|
|
181
|
+
val answerBtn = createCircleButton(
|
|
182
|
+
android.R.drawable.ic_menu_call,
|
|
183
|
+
Color.parseColor("#4CAF50")
|
|
184
|
+
).apply { setOnClickListener { onAnswer() } }
|
|
185
|
+
|
|
186
|
+
actions.addView(declineBtn)
|
|
187
|
+
actions.addView(View(this).apply {
|
|
188
|
+
layoutParams = LinearLayout.LayoutParams(dp(60), 0)
|
|
189
|
+
})
|
|
190
|
+
actions.addView(answerBtn)
|
|
191
|
+
root.addView(actions)
|
|
192
|
+
|
|
193
|
+
setContentView(root)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private fun createCircleButton(iconRes: Int, bgColor: Int): FrameLayout {
|
|
197
|
+
val size = dp(70)
|
|
198
|
+
return FrameLayout(this).apply {
|
|
199
|
+
layoutParams = LinearLayout.LayoutParams(size, size)
|
|
200
|
+
isClickable = true; isFocusable = true
|
|
201
|
+
foreground = getRipple()
|
|
202
|
+
// circle bg
|
|
203
|
+
addView(View(context).apply {
|
|
204
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
205
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
206
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
207
|
+
)
|
|
208
|
+
background = GradientDrawable().apply {
|
|
209
|
+
shape = GradientDrawable.OVAL
|
|
210
|
+
setColor(bgColor)
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
// icon
|
|
214
|
+
addView(ImageView(context).apply {
|
|
215
|
+
layoutParams = FrameLayout.LayoutParams(dp(36), dp(36))
|
|
216
|
+
.apply { gravity = Gravity.CENTER }
|
|
217
|
+
setImageResource(iconRes)
|
|
218
|
+
setColorFilter(Color.WHITE)
|
|
219
|
+
})
|
|
79
220
|
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private fun getRipple(): Drawable? {
|
|
224
|
+
val tv = TypedValue()
|
|
225
|
+
theme.resolveAttribute(
|
|
226
|
+
android.R.attr.selectableItemBackgroundBorderless, tv, true
|
|
227
|
+
)
|
|
228
|
+
return ContextCompat.getDrawable(this, tv.resourceId)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private fun onAnswer() {
|
|
232
|
+
finishReason = FinishReason.ANSWER
|
|
233
|
+
CallEngine.stopRingtone()
|
|
234
|
+
CallEngine.cancelIncomingCallUI()
|
|
235
|
+
CallEngine.answerCall(callId)
|
|
236
|
+
finishCallActivity()
|
|
237
|
+
}
|
|
80
238
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
239
|
+
private fun onDecline() {
|
|
240
|
+
finishReason = FinishReason.DECLINE
|
|
241
|
+
CallEngine.stopRingtone()
|
|
242
|
+
CallEngine.cancelIncomingCallUI()
|
|
243
|
+
CallEngine.endCall(callId)
|
|
244
|
+
finishCallActivity()
|
|
84
245
|
}
|
|
85
246
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
247
|
+
private fun dp(v: Int): Int = TypedValue.applyDimension(
|
|
248
|
+
TypedValue.COMPLEX_UNIT_DIP, v.toFloat(),
|
|
249
|
+
resources.displayMetrics
|
|
250
|
+
).toInt()
|
|
251
|
+
|
|
252
|
+
private fun setupLockScreenBypass(isSamsung: Boolean) {
|
|
89
253
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
90
|
-
setShowWhenLocked(true)
|
|
91
|
-
setTurnScreenOn(true)
|
|
254
|
+
setShowWhenLocked(true); setTurnScreenOn(true)
|
|
92
255
|
} else {
|
|
93
256
|
window.addFlags(
|
|
94
257
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
@@ -96,53 +259,30 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
96
259
|
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
|
97
260
|
)
|
|
98
261
|
}
|
|
99
|
-
|
|
100
|
-
// **SAMSUNG SPECIFIC**: Additional fixes for Samsung One UI 7
|
|
101
|
-
if (isSamsungSpecific) {
|
|
102
|
-
Log.d(TAG, "Applying Samsung-specific lock screen bypass")
|
|
103
|
-
|
|
104
|
-
// **CRITICAL**: Samsung requires BOTH new and old methods
|
|
262
|
+
if (isSamsung) {
|
|
105
263
|
window.addFlags(
|
|
106
264
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
107
265
|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
108
266
|
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
|
|
109
267
|
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
110
268
|
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
|
269
|
+
val km = getSystemService(Context.KEYGUARD_SERVICE)
|
|
270
|
+
as KeyguardManager
|
|
114
271
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
272
|
+
km.requestDismissKeyguard(this,
|
|
273
|
+
object : KeyguardManager.KeyguardDismissCallback() {
|
|
274
|
+
override fun onDismissSucceeded() {
|
|
275
|
+
Log.d(TAG, "Samsung keyguard dismissed")
|
|
276
|
+
}
|
|
277
|
+
override fun onDismissError() {
|
|
278
|
+
Log.w(TAG, "Samsung keyguard dismiss error")
|
|
279
|
+
}
|
|
280
|
+
})
|
|
123
281
|
}
|
|
124
282
|
}
|
|
125
283
|
}
|
|
126
284
|
|
|
127
|
-
override fun onDestroy() {
|
|
128
|
-
super.onDestroy()
|
|
129
|
-
Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
|
|
130
|
-
|
|
131
|
-
// Unregister listener
|
|
132
|
-
CallEngine.unregisterCallEndListener(this)
|
|
133
|
-
|
|
134
|
-
// Cancel timeout
|
|
135
|
-
timeoutHandler.removeCallbacks(timeoutRunnable)
|
|
136
|
-
|
|
137
|
-
// If user never answered, clean up ringtone/UI
|
|
138
|
-
if (finishReason != FinishReason.ANSWER) {
|
|
139
|
-
CallEngine.stopRingtone()
|
|
140
|
-
CallEngine.cancelIncomingCallUI()
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
285
|
override fun onBackPressed() {
|
|
145
|
-
Log.d(TAG, "onBackPressed for callId: $callId → treat as decline")
|
|
146
286
|
finishReason = FinishReason.MANUAL_DISMISS
|
|
147
287
|
CallEngine.stopRingtone()
|
|
148
288
|
CallEngine.cancelIncomingCallUI()
|
|
@@ -150,24 +290,25 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
|
150
290
|
finishCallActivity()
|
|
151
291
|
}
|
|
152
292
|
|
|
153
|
-
/**
|
|
154
|
-
* Called by CallEngine whenever ANY call ends.
|
|
155
|
-
* We only care about our own callId.
|
|
156
|
-
*/
|
|
157
293
|
override fun onCallEnded(endedCallId: String) {
|
|
158
294
|
if (endedCallId == callId && !isFinishing) {
|
|
159
|
-
Log.d(TAG, "CallActivity onCallEnded callback for callId: $callId")
|
|
160
295
|
finishReason = FinishReason.EXTERNAL_END
|
|
161
296
|
runOnUiThread { finishCallActivity() }
|
|
162
297
|
}
|
|
163
298
|
}
|
|
164
299
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
300
|
+
override fun onDestroy() {
|
|
301
|
+
super.onDestroy()
|
|
302
|
+
CallEngine.unregisterCallEndListener(this)
|
|
303
|
+
handler.removeCallbacks(timeoutRunnable)
|
|
304
|
+
if (finishReason != FinishReason.ANSWER) {
|
|
305
|
+
CallEngine.stopRingtone()
|
|
306
|
+
CallEngine.cancelIncomingCallUI()
|
|
169
307
|
}
|
|
170
|
-
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private fun finishCallActivity() {
|
|
311
|
+
if (isFinishing) return
|
|
171
312
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
172
313
|
finishAndRemoveTask()
|
|
173
314
|
} else {
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#40FFFFFF">
|
|
3
|
-
<item>
|
|
4
|
-
<shape android:shape="oval">
|
|
5
|
-
<gradient
|
|
6
|
-
android:startColor="#FF4CAF50"
|
|
7
|
-
android:endColor="#FF388E3C"
|
|
8
|
-
android:angle="135" />
|
|
9
|
-
<stroke android:width="2dp" android:color="#FF66BB6A" />
|
|
10
|
-
</shape>
|
|
11
|
-
</item>
|
|
12
|
-
</ripple>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
|
3
|
-
<gradient
|
|
4
|
-
android:startColor="#40000000"
|
|
5
|
-
android:centerColor="#20000000"
|
|
6
|
-
android:endColor="#00000000"
|
|
7
|
-
android:type="radial"
|
|
8
|
-
android:gradientRadius="40dp" />
|
|
9
|
-
</shape>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#40FFFFFF">
|
|
3
|
-
<item>
|
|
4
|
-
<shape android:shape="oval">
|
|
5
|
-
<gradient
|
|
6
|
-
android:startColor="#FFF44336"
|
|
7
|
-
android:endColor="#FFD32F2F"
|
|
8
|
-
android:angle="135" />
|
|
9
|
-
<stroke android:width="2dp" android:color="#FFEF5350" />
|
|
10
|
-
</shape>
|
|
11
|
-
</item>
|
|
12
|
-
</ripple>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:width="136dp"
|
|
4
|
-
android:height="136dp"
|
|
5
|
-
android:viewportWidth="24"
|
|
6
|
-
android:viewportHeight="24">
|
|
7
|
-
<path
|
|
8
|
-
android:fillColor="#FF9E9E9E"
|
|
9
|
-
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
|
10
|
-
</vector>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
-
<item>
|
|
4
|
-
<shape>
|
|
5
|
-
<gradient
|
|
6
|
-
android:startColor="#FF0D1B2A"
|
|
7
|
-
android:centerColor="#FF1B263B"
|
|
8
|
-
android:endColor="#FF415A77"
|
|
9
|
-
android:angle="135" />
|
|
10
|
-
</shape>
|
|
11
|
-
</item>
|
|
12
|
-
<item>
|
|
13
|
-
<shape>
|
|
14
|
-
<gradient
|
|
15
|
-
android:startColor="#15FFFFFF"
|
|
16
|
-
android:centerColor="#08FFFFFF"
|
|
17
|
-
android:endColor="#00FFFFFF"
|
|
18
|
-
android:angle="45" />
|
|
19
|
-
</shape>
|
|
20
|
-
</item>
|
|
21
|
-
</layer-list>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#30FFFFFF">
|
|
3
|
-
<item>
|
|
4
|
-
<shape android:shape="rectangle">
|
|
5
|
-
<solid android:color="#20FFFFFF" />
|
|
6
|
-
<corners android:radius="16dp" />
|
|
7
|
-
<stroke android:width="1dp" android:color="#30FFFFFF" />
|
|
8
|
-
</shape>
|
|
9
|
-
</item>
|
|
10
|
-
</ripple>
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:layout_width="match_parent"
|
|
4
|
-
android:layout_height="match_parent"
|
|
5
|
-
android:background="#FF0D1B2A">
|
|
6
|
-
|
|
7
|
-
<!-- Professional gradient background -->
|
|
8
|
-
<View
|
|
9
|
-
android:layout_width="match_parent"
|
|
10
|
-
android:layout_height="match_parent"
|
|
11
|
-
android:background="@drawable/professional_bg" />
|
|
12
|
-
|
|
13
|
-
<!-- Main content container -->
|
|
14
|
-
<LinearLayout
|
|
15
|
-
android:layout_width="match_parent"
|
|
16
|
-
android:layout_height="match_parent"
|
|
17
|
-
android:orientation="vertical"
|
|
18
|
-
android:gravity="center_horizontal"
|
|
19
|
-
android:fitsSystemWindows="true">
|
|
20
|
-
|
|
21
|
-
<!-- Top spacing -->
|
|
22
|
-
<View
|
|
23
|
-
android:layout_width="match_parent"
|
|
24
|
-
android:layout_height="0dp"
|
|
25
|
-
android:layout_weight="1" />
|
|
26
|
-
|
|
27
|
-
<!-- Call type indicator -->
|
|
28
|
-
<LinearLayout
|
|
29
|
-
android:layout_width="wrap_content"
|
|
30
|
-
android:layout_height="wrap_content"
|
|
31
|
-
android:orientation="horizontal"
|
|
32
|
-
android:gravity="center_vertical"
|
|
33
|
-
android:layout_marginBottom="32dp">
|
|
34
|
-
|
|
35
|
-
<ImageView
|
|
36
|
-
android:layout_width="18dp"
|
|
37
|
-
android:layout_height="18dp"
|
|
38
|
-
android:src="@android:drawable/ic_menu_call"
|
|
39
|
-
android:tint="#80FFFFFF"
|
|
40
|
-
android:layout_marginEnd="8dp" />
|
|
41
|
-
|
|
42
|
-
<TextView
|
|
43
|
-
android:layout_width="wrap_content"
|
|
44
|
-
android:layout_height="wrap_content"
|
|
45
|
-
android:text="Incoming call"
|
|
46
|
-
android:textColor="#80FFFFFF"
|
|
47
|
-
android:textSize="14sp"
|
|
48
|
-
android:fontFamily="sans-serif-medium" />
|
|
49
|
-
</LinearLayout>
|
|
50
|
-
|
|
51
|
-
<!-- Profile picture with animated rings -->
|
|
52
|
-
<FrameLayout
|
|
53
|
-
android:layout_width="180dp"
|
|
54
|
-
android:layout_height="180dp"
|
|
55
|
-
android:layout_marginBottom="32dp">
|
|
56
|
-
|
|
57
|
-
<!-- Outer pulse ring -->
|
|
58
|
-
<View
|
|
59
|
-
android:layout_width="180dp"
|
|
60
|
-
android:layout_height="180dp"
|
|
61
|
-
android:background="@drawable/pulse_ring_outer" />
|
|
62
|
-
|
|
63
|
-
<!-- Middle pulse ring -->
|
|
64
|
-
<View
|
|
65
|
-
android:layout_width="160dp"
|
|
66
|
-
android:layout_height="160dp"
|
|
67
|
-
android:layout_gravity="center"
|
|
68
|
-
android:background="@drawable/pulse_ring_middle" />
|
|
69
|
-
|
|
70
|
-
<!-- Profile picture -->
|
|
71
|
-
<FrameLayout
|
|
72
|
-
android:layout_width="140dp"
|
|
73
|
-
android:layout_height="140dp"
|
|
74
|
-
android:layout_gravity="center">
|
|
75
|
-
|
|
76
|
-
<!-- Profile background -->
|
|
77
|
-
<View
|
|
78
|
-
android:layout_width="140dp"
|
|
79
|
-
android:layout_height="140dp"
|
|
80
|
-
android:background="@drawable/profile_bg" />
|
|
81
|
-
|
|
82
|
-
<!-- Actual profile image -->
|
|
83
|
-
<ImageView
|
|
84
|
-
android:id="@+id/avatar"
|
|
85
|
-
android:layout_width="136dp"
|
|
86
|
-
android:layout_height="136dp"
|
|
87
|
-
android:layout_gravity="center"
|
|
88
|
-
android:background="@drawable/profile_image_bg"
|
|
89
|
-
android:scaleType="centerCrop"
|
|
90
|
-
android:src="@drawable/default_avatar" />
|
|
91
|
-
</FrameLayout>
|
|
92
|
-
</FrameLayout>
|
|
93
|
-
|
|
94
|
-
<!-- Caller information -->
|
|
95
|
-
<LinearLayout
|
|
96
|
-
android:layout_width="wrap_content"
|
|
97
|
-
android:layout_height="wrap_content"
|
|
98
|
-
android:orientation="vertical"
|
|
99
|
-
android:gravity="center"
|
|
100
|
-
android:layout_marginBottom="24dp">
|
|
101
|
-
|
|
102
|
-
<TextView
|
|
103
|
-
android:id="@+id/caller_name"
|
|
104
|
-
android:layout_width="wrap_content"
|
|
105
|
-
android:layout_height="wrap_content"
|
|
106
|
-
android:text="John Doe"
|
|
107
|
-
android:textColor="#FFFFFF"
|
|
108
|
-
android:textSize="32sp"
|
|
109
|
-
android:fontFamily="sans-serif-light"
|
|
110
|
-
android:gravity="center"
|
|
111
|
-
android:layout_marginBottom="4dp" />
|
|
112
|
-
|
|
113
|
-
<TextView
|
|
114
|
-
android:layout_width="wrap_content"
|
|
115
|
-
android:layout_height="wrap_content"
|
|
116
|
-
android:text="Mobile • +1 (555) 123-4567"
|
|
117
|
-
android:textColor="#B3FFFFFF"
|
|
118
|
-
android:textSize="16sp"
|
|
119
|
-
android:fontFamily="sans-serif" />
|
|
120
|
-
</LinearLayout>
|
|
121
|
-
|
|
122
|
-
<!-- Middle spacing -->
|
|
123
|
-
<View
|
|
124
|
-
android:layout_width="match_parent"
|
|
125
|
-
android:layout_height="0dp"
|
|
126
|
-
android:layout_weight="2" />
|
|
127
|
-
|
|
128
|
-
<!-- Quick actions (Samsung style) -->
|
|
129
|
-
<LinearLayout
|
|
130
|
-
android:layout_width="match_parent"
|
|
131
|
-
android:layout_height="wrap_content"
|
|
132
|
-
android:orientation="horizontal"
|
|
133
|
-
android:gravity="center"
|
|
134
|
-
android:layout_marginBottom="32dp">
|
|
135
|
-
|
|
136
|
-
<!-- Remind me -->
|
|
137
|
-
<LinearLayout
|
|
138
|
-
android:layout_width="wrap_content"
|
|
139
|
-
android:layout_height="wrap_content"
|
|
140
|
-
android:orientation="vertical"
|
|
141
|
-
android:gravity="center"
|
|
142
|
-
android:padding="12dp"
|
|
143
|
-
android:layout_marginEnd="40dp"
|
|
144
|
-
android:background="@drawable/quick_action_bg"
|
|
145
|
-
android:clickable="true">
|
|
146
|
-
|
|
147
|
-
<ImageView
|
|
148
|
-
android:layout_width="24dp"
|
|
149
|
-
android:layout_height="24dp"
|
|
150
|
-
android:src="@android:drawable/ic_menu_recent_history"
|
|
151
|
-
android:tint="#FFFFFF"
|
|
152
|
-
android:layout_marginBottom="4dp" />
|
|
153
|
-
|
|
154
|
-
<TextView
|
|
155
|
-
android:layout_width="wrap_content"
|
|
156
|
-
android:layout_height="wrap_content"
|
|
157
|
-
android:text="Remind me"
|
|
158
|
-
android:textColor="#FFFFFF"
|
|
159
|
-
android:textSize="12sp" />
|
|
160
|
-
</LinearLayout>
|
|
161
|
-
|
|
162
|
-
<!-- Message -->
|
|
163
|
-
<LinearLayout
|
|
164
|
-
android:layout_width="wrap_content"
|
|
165
|
-
android:layout_height="wrap_content"
|
|
166
|
-
android:orientation="vertical"
|
|
167
|
-
android:gravity="center"
|
|
168
|
-
android:padding="12dp"
|
|
169
|
-
android:background="@drawable/quick_action_bg"
|
|
170
|
-
android:clickable="true">
|
|
171
|
-
|
|
172
|
-
<ImageView
|
|
173
|
-
android:layout_width="24dp"
|
|
174
|
-
android:layout_height="24dp"
|
|
175
|
-
android:src="@android:drawable/ic_menu_send"
|
|
176
|
-
android:tint="#FFFFFF"
|
|
177
|
-
android:layout_marginBottom="4dp" />
|
|
178
|
-
|
|
179
|
-
<TextView
|
|
180
|
-
android:layout_width="wrap_content"
|
|
181
|
-
android:layout_height="wrap_content"
|
|
182
|
-
android:text="Message"
|
|
183
|
-
android:textColor="#FFFFFF"
|
|
184
|
-
android:textSize="12sp" />
|
|
185
|
-
</LinearLayout>
|
|
186
|
-
</LinearLayout>
|
|
187
|
-
|
|
188
|
-
<!-- Main call actions -->
|
|
189
|
-
<LinearLayout
|
|
190
|
-
android:layout_width="match_parent"
|
|
191
|
-
android:layout_height="wrap_content"
|
|
192
|
-
android:orientation="horizontal"
|
|
193
|
-
android:gravity="center"
|
|
194
|
-
android:layout_marginBottom="48dp">
|
|
195
|
-
|
|
196
|
-
<!-- Decline button -->
|
|
197
|
-
<FrameLayout
|
|
198
|
-
android:layout_width="80dp"
|
|
199
|
-
android:layout_height="80dp"
|
|
200
|
-
android:layout_marginEnd="80dp">
|
|
201
|
-
|
|
202
|
-
<!-- Button shadow -->
|
|
203
|
-
<View
|
|
204
|
-
android:layout_width="80dp"
|
|
205
|
-
android:layout_height="80dp"
|
|
206
|
-
android:background="@drawable/button_shadow" />
|
|
207
|
-
|
|
208
|
-
<Button
|
|
209
|
-
android:id="@+id/decline_btn"
|
|
210
|
-
android:layout_width="72dp"
|
|
211
|
-
android:layout_height="72dp"
|
|
212
|
-
android:layout_gravity="center"
|
|
213
|
-
android:background="@drawable/decline_btn_bg"
|
|
214
|
-
android:text="✕"
|
|
215
|
-
android:textColor="#FFFFFF"
|
|
216
|
-
android:textSize="28sp"
|
|
217
|
-
android:textStyle="bold" />
|
|
218
|
-
</FrameLayout>
|
|
219
|
-
|
|
220
|
-
<!-- Answer button -->
|
|
221
|
-
<FrameLayout
|
|
222
|
-
android:layout_width="80dp"
|
|
223
|
-
android:layout_height="80dp">
|
|
224
|
-
|
|
225
|
-
<!-- Button shadow -->
|
|
226
|
-
<View
|
|
227
|
-
android:layout_width="80dp"
|
|
228
|
-
android:layout_height="80dp"
|
|
229
|
-
android:background="@drawable/button_shadow" />
|
|
230
|
-
|
|
231
|
-
<Button
|
|
232
|
-
android:id="@+id/answer_btn"
|
|
233
|
-
android:layout_width="72dp"
|
|
234
|
-
android:layout_height="72dp"
|
|
235
|
-
android:layout_gravity="center"
|
|
236
|
-
android:background="@drawable/answer_btn_bg"
|
|
237
|
-
android:text="✓"
|
|
238
|
-
android:textColor="#FFFFFF"
|
|
239
|
-
android:textSize="28sp"
|
|
240
|
-
android:textStyle="bold" />
|
|
241
|
-
</FrameLayout>
|
|
242
|
-
</LinearLayout>
|
|
243
|
-
</LinearLayout>
|
|
244
|
-
</FrameLayout>
|