@qusaieilouti99/call-manager 0.1.94 → 0.1.96
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 +560 -167
- package/package.json +1 -1
- package/android/src/main/res/drawable/action_button_secondary.xml +0 -12
- package/android/src/main/res/drawable/answer_button.xml +0 -15
- package/android/src/main/res/drawable/answer_button_shadow.xml +0 -10
- package/android/src/main/res/drawable/avatar_bg.xml +0 -8
- package/android/src/main/res/drawable/avatar_glow.xml +0 -10
- package/android/src/main/res/drawable/call_background.xml +0 -24
- package/android/src/main/res/drawable/decline_button.xml +0 -15
- package/android/src/main/res/drawable/decline_button_shadow.xml +0 -10
- package/android/src/main/res/drawable/overlay_gradient.xml +0 -8
- package/android/src/main/res/layout/activity_call.xml +0 -166
|
@@ -1,181 +1,574 @@
|
|
|
1
|
-
//
|
|
1
|
+
// CallActivity.kt
|
|
2
2
|
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
3
3
|
|
|
4
|
+
import android.animation.ObjectAnimator
|
|
5
|
+
import android.animation.ValueAnimator
|
|
4
6
|
import android.app.Activity
|
|
5
7
|
import android.app.KeyguardManager
|
|
6
8
|
import android.content.Context
|
|
9
|
+
import android.graphics.*
|
|
10
|
+
import android.graphics.drawable.GradientDrawable
|
|
7
11
|
import android.os.Build
|
|
8
12
|
import android.os.Bundle
|
|
9
13
|
import android.os.Handler
|
|
10
14
|
import android.os.Looper
|
|
11
15
|
import android.util.Log
|
|
16
|
+
import android.util.TypedValue
|
|
17
|
+
import android.view.View
|
|
18
|
+
import android.view.ViewGroup
|
|
12
19
|
import android.view.WindowManager
|
|
13
|
-
import android.
|
|
14
|
-
import android.widget
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* so it always auto‐finishes when the engine ends the call.
|
|
19
|
-
* **SAMSUNG FIX**: Enhanced lock screen bypass for Samsung devices
|
|
20
|
-
*/
|
|
20
|
+
import android.view.animation.LinearInterpolator
|
|
21
|
+
import android.widget.*
|
|
22
|
+
import androidx.core.content.ContextCompat
|
|
23
|
+
import androidx.core.view.ViewCompat
|
|
24
|
+
|
|
21
25
|
class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
27
|
+
private enum class FinishReason {
|
|
28
|
+
ANSWER, DECLINE, TIMEOUT, MANUAL_DISMISS, EXTERNAL_END
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private var finishReason: FinishReason? = null
|
|
32
|
+
private var callId: String = ""
|
|
33
|
+
private var callType: String = "Audio"
|
|
34
|
+
|
|
35
|
+
// UI Components
|
|
36
|
+
private lateinit var rootContainer: FrameLayout
|
|
37
|
+
private lateinit var callerNameText: TextView
|
|
38
|
+
private lateinit var profileImage: ImageView
|
|
39
|
+
private lateinit var answerButton: FrameLayout
|
|
40
|
+
private lateinit var declineButton: FrameLayout
|
|
41
|
+
|
|
42
|
+
// Animation
|
|
43
|
+
private var pulseAnimator: ValueAnimator? = null
|
|
44
|
+
|
|
45
|
+
private val timeoutHandler = Handler(Looper.getMainLooper())
|
|
46
|
+
private val timeoutRunnable = Runnable {
|
|
47
|
+
Log.d(TAG, "CallActivity timeout triggered for callId: $callId")
|
|
48
|
+
finishReason = FinishReason.TIMEOUT
|
|
49
|
+
CallEngine.stopRingtone()
|
|
50
|
+
CallEngine.cancelIncomingCallUI()
|
|
51
|
+
CallEngine.endCall(callId)
|
|
52
|
+
finishCallActivity()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
56
|
+
super.onCreate(savedInstanceState)
|
|
57
|
+
Log.d(TAG, "CallActivity onCreate")
|
|
58
|
+
|
|
59
|
+
// Enhanced lock screen bypass
|
|
60
|
+
val isSamsungLockScreenBypass = intent.getBooleanExtra("SAMSUNG_LOCK_SCREEN_BYPASS", false)
|
|
61
|
+
setupLockScreenBypass(isSamsungLockScreenBypass)
|
|
62
|
+
|
|
63
|
+
// Create UI programmatically
|
|
64
|
+
createProfessionalUI()
|
|
65
|
+
|
|
66
|
+
// Read incoming call params
|
|
67
|
+
callId = intent.getStringExtra("callId") ?: ""
|
|
68
|
+
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
69
|
+
Log.d(TAG, "CallActivity received callId: $callId, callType: $callType")
|
|
70
|
+
|
|
71
|
+
// Register for call-end callbacks
|
|
72
|
+
CallEngine.registerCallEndListener(this)
|
|
73
|
+
|
|
74
|
+
// Bind data
|
|
75
|
+
val callerName = intent.getStringExtra("callerName") ?: "Unknown"
|
|
76
|
+
val callerAvatar = intent.getStringExtra("callerAvatar")
|
|
77
|
+
updateCallerInfo(callerName, callerAvatar)
|
|
78
|
+
|
|
79
|
+
// Setup button listeners
|
|
80
|
+
setupButtonListeners()
|
|
81
|
+
|
|
82
|
+
// Start animations
|
|
83
|
+
startPulseAnimation()
|
|
84
|
+
|
|
85
|
+
// Start auto-timeout
|
|
86
|
+
timeoutHandler.postDelayed(timeoutRunnable, 60_000)
|
|
87
|
+
Log.d(TAG, "CallActivity setup complete")
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private fun createProfessionalUI() {
|
|
91
|
+
// Root container with gradient background
|
|
92
|
+
rootContainer = FrameLayout(this).apply {
|
|
93
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
94
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
95
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
96
|
+
)
|
|
97
|
+
background = createGradientBackground()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Main content container
|
|
101
|
+
val contentContainer = LinearLayout(this).apply {
|
|
102
|
+
layoutParams = FrameLayout.LayoutParams(
|
|
103
|
+
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
104
|
+
FrameLayout.LayoutParams.MATCH_PARENT
|
|
105
|
+
).apply {
|
|
106
|
+
setPadding(dp(32), dp(80), dp(32), dp(48))
|
|
107
|
+
}
|
|
108
|
+
orientation = LinearLayout.VERTICAL
|
|
109
|
+
gravity = android.view.Gravity.CENTER_HORIZONTAL
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Add components to content container
|
|
113
|
+
contentContainer.addView(createCallTypeIndicator())
|
|
114
|
+
contentContainer.addView(createSpacerView(40))
|
|
115
|
+
contentContainer.addView(createProfileSection())
|
|
116
|
+
contentContainer.addView(createSpacerView(32))
|
|
117
|
+
contentContainer.addView(createCallerInfoSection())
|
|
118
|
+
contentContainer.addView(createFlexibleSpacerView())
|
|
119
|
+
contentContainer.addView(createQuickActionsSection())
|
|
120
|
+
contentContainer.addView(createSpacerView(32))
|
|
121
|
+
contentContainer.addView(createCallActionsSection())
|
|
122
|
+
|
|
123
|
+
rootContainer.addView(contentContainer)
|
|
124
|
+
setContentView(rootContainer)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private fun createGradientBackground(): GradientDrawable {
|
|
128
|
+
return GradientDrawable().apply {
|
|
129
|
+
colors = intArrayOf(
|
|
130
|
+
Color.parseColor("#FF0D1B2A"),
|
|
131
|
+
Color.parseColor("#FF1B263B"),
|
|
132
|
+
Color.parseColor("#FF415A77")
|
|
133
|
+
)
|
|
134
|
+
orientation = GradientDrawable.Orientation.TL_BR
|
|
135
|
+
gradientType = GradientDrawable.LINEAR_GRADIENT
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private fun createCallTypeIndicator(): LinearLayout {
|
|
140
|
+
return LinearLayout(this).apply {
|
|
141
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
142
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
143
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
144
|
+
)
|
|
145
|
+
orientation = LinearLayout.HORIZONTAL
|
|
146
|
+
gravity = android.view.Gravity.CENTER_VERTICAL
|
|
147
|
+
|
|
148
|
+
// Call icon
|
|
149
|
+
addView(createCallIcon())
|
|
150
|
+
|
|
151
|
+
// Call type text
|
|
152
|
+
addView(TextView(this@CallActivity).apply {
|
|
153
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
154
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
155
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
156
|
+
).apply { setMargins(dp(8), 0, 0, 0) }
|
|
157
|
+
text = "Incoming call"
|
|
158
|
+
setTextColor(Color.parseColor("#80FFFFFF"))
|
|
159
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
|
160
|
+
typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private fun createCallIcon(): View {
|
|
166
|
+
return View(this).apply {
|
|
167
|
+
layoutParams = LinearLayout.LayoutParams(dp(18), dp(18))
|
|
168
|
+
background = GradientDrawable().apply {
|
|
169
|
+
shape = GradientDrawable.OVAL
|
|
170
|
+
setColor(Color.parseColor("#80FFFFFF"))
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private fun createProfileSection(): FrameLayout {
|
|
176
|
+
return FrameLayout(this).apply {
|
|
177
|
+
layoutParams = LinearLayout.LayoutParams(dp(180), dp(180))
|
|
178
|
+
|
|
179
|
+
// Outer pulse ring
|
|
180
|
+
addView(createPulseRing(180, "#30FFFFFF"))
|
|
181
|
+
|
|
182
|
+
// Middle pulse ring
|
|
183
|
+
addView(createPulseRing(160, "#40FFFFFF"))
|
|
184
|
+
|
|
185
|
+
// Profile container
|
|
186
|
+
val profileContainer = FrameLayout(this@CallActivity).apply {
|
|
187
|
+
layoutParams = FrameLayout.LayoutParams(dp(140), dp(140)).apply {
|
|
188
|
+
gravity = android.view.Gravity.CENTER
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Profile background
|
|
193
|
+
profileContainer.addView(View(this@CallActivity).apply {
|
|
194
|
+
layoutParams = FrameLayout.LayoutParams(dp(140), dp(140))
|
|
195
|
+
background = GradientDrawable().apply {
|
|
196
|
+
shape = GradientDrawable.OVAL
|
|
197
|
+
setColor(Color.WHITE)
|
|
198
|
+
setStroke(dp(3), Color.parseColor("#E0E0E0"))
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
// Profile image
|
|
203
|
+
profileImage = ImageView(this@CallActivity).apply {
|
|
204
|
+
layoutParams = FrameLayout.LayoutParams(dp(136), dp(136)).apply {
|
|
205
|
+
gravity = android.view.Gravity.CENTER
|
|
206
|
+
}
|
|
207
|
+
scaleType = ImageView.ScaleType.CENTER_CROP
|
|
208
|
+
background = GradientDrawable().apply {
|
|
209
|
+
shape = GradientDrawable.OVAL
|
|
210
|
+
setColor(Color.parseColor("#F5F5F5"))
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
profileContainer.addView(profileImage)
|
|
214
|
+
|
|
215
|
+
addView(profileContainer)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private fun createPulseRing(size: Int, color: String): View {
|
|
220
|
+
return View(this).apply {
|
|
221
|
+
layoutParams = FrameLayout.LayoutParams(dp(size), dp(size)).apply {
|
|
222
|
+
gravity = android.view.Gravity.CENTER
|
|
223
|
+
}
|
|
224
|
+
background = GradientDrawable().apply {
|
|
225
|
+
shape = GradientDrawable.OVAL
|
|
226
|
+
setStroke(dp(2), Color.parseColor(color))
|
|
227
|
+
setColor(Color.parseColor("#10FFFFFF"))
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private fun createCallerInfoSection(): LinearLayout {
|
|
233
|
+
return LinearLayout(this).apply {
|
|
234
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
235
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
236
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
237
|
+
)
|
|
238
|
+
orientation = LinearLayout.VERTICAL
|
|
239
|
+
gravity = android.view.Gravity.CENTER
|
|
240
|
+
|
|
241
|
+
// Caller name
|
|
242
|
+
callerNameText = TextView(this@CallActivity).apply {
|
|
243
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
244
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
245
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
246
|
+
).apply { setMargins(0, 0, 0, dp(4)) }
|
|
247
|
+
text = "John Doe" // Default, will be updated
|
|
248
|
+
setTextColor(Color.WHITE)
|
|
249
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 32f)
|
|
250
|
+
typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
|
|
251
|
+
gravity = android.view.Gravity.CENTER
|
|
252
|
+
}
|
|
253
|
+
addView(callerNameText)
|
|
254
|
+
|
|
255
|
+
// Caller number/label
|
|
256
|
+
addView(TextView(this@CallActivity).apply {
|
|
257
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
258
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
259
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
260
|
+
)
|
|
261
|
+
text = "Mobile"
|
|
262
|
+
setTextColor(Color.parseColor("#B3FFFFFF"))
|
|
263
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
|
264
|
+
gravity = android.view.Gravity.CENTER
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private fun createQuickActionsSection(): LinearLayout {
|
|
270
|
+
return LinearLayout(this).apply {
|
|
271
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
272
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
273
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
274
|
+
)
|
|
275
|
+
orientation = LinearLayout.HORIZONTAL
|
|
276
|
+
gravity = android.view.Gravity.CENTER
|
|
277
|
+
|
|
278
|
+
// Remind me action
|
|
279
|
+
addView(createQuickAction("⏰", "Remind me").apply {
|
|
280
|
+
layoutParams = (layoutParams as LinearLayout.LayoutParams).apply {
|
|
281
|
+
setMargins(0, 0, dp(40), 0)
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
// Message action
|
|
286
|
+
addView(createQuickAction("💬", "Message"))
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private fun createQuickAction(icon: String, label: String): LinearLayout {
|
|
291
|
+
return LinearLayout(this).apply {
|
|
292
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
293
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
294
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
295
|
+
)
|
|
296
|
+
orientation = LinearLayout.VERTICAL
|
|
297
|
+
gravity = android.view.Gravity.CENTER
|
|
298
|
+
setPadding(dp(12), dp(12), dp(12), dp(12))
|
|
299
|
+
background = createQuickActionBackground()
|
|
300
|
+
isClickable = true
|
|
301
|
+
|
|
302
|
+
// Icon
|
|
303
|
+
addView(TextView(this@CallActivity).apply {
|
|
304
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
305
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
306
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
307
|
+
).apply { setMargins(0, 0, 0, dp(4)) }
|
|
308
|
+
text = icon
|
|
309
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 24f)
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
// Label
|
|
313
|
+
addView(TextView(this@CallActivity).apply {
|
|
314
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
315
|
+
LinearLayout.LayoutParams.WRAP_CONTENT,
|
|
316
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
317
|
+
)
|
|
318
|
+
text = label
|
|
319
|
+
setTextColor(Color.WHITE)
|
|
320
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f)
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private fun createQuickActionBackground(): GradientDrawable {
|
|
326
|
+
return GradientDrawable().apply {
|
|
327
|
+
shape = GradientDrawable.RECTANGLE
|
|
328
|
+
cornerRadius = dp(16).toFloat()
|
|
329
|
+
setColor(Color.parseColor("#20FFFFFF"))
|
|
330
|
+
setStroke(dp(1), Color.parseColor("#30FFFFFF"))
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private fun createCallActionsSection(): LinearLayout {
|
|
335
|
+
return LinearLayout(this).apply {
|
|
336
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
337
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
338
|
+
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
339
|
+
)
|
|
340
|
+
orientation = LinearLayout.HORIZONTAL
|
|
341
|
+
gravity = android.view.Gravity.CENTER
|
|
342
|
+
|
|
343
|
+
// Decline button
|
|
344
|
+
declineButton = createCallActionButton("✕", "#FFF44336", "#FFD32F2F").apply {
|
|
345
|
+
layoutParams = LinearLayout.LayoutParams(dp(80), dp(80)).apply {
|
|
346
|
+
setMargins(0, 0, dp(80), 0)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
addView(declineButton)
|
|
350
|
+
|
|
351
|
+
// Answer button
|
|
352
|
+
answerButton = createCallActionButton("✓", "#FF4CAF50", "#FF388E3C").apply {
|
|
353
|
+
layoutParams = LinearLayout.LayoutParams(dp(80), dp(80))
|
|
354
|
+
}
|
|
355
|
+
addView(answerButton)
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private fun createCallActionButton(text: String, startColor: String, endColor: String): FrameLayout {
|
|
360
|
+
return FrameLayout(this).apply {
|
|
361
|
+
// Shadow
|
|
362
|
+
addView(View(this@CallActivity).apply {
|
|
363
|
+
layoutParams = FrameLayout.LayoutParams(dp(80), dp(80))
|
|
364
|
+
background = GradientDrawable().apply {
|
|
365
|
+
shape = GradientDrawable.OVAL
|
|
366
|
+
colors = intArrayOf(
|
|
367
|
+
Color.parseColor("#40000000"),
|
|
368
|
+
Color.parseColor("#20000000"),
|
|
369
|
+
Color.parseColor("#00000000")
|
|
370
|
+
)
|
|
371
|
+
gradientType = GradientDrawable.RADIAL_GRADIENT
|
|
372
|
+
gradientRadius = dp(40).toFloat()
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
// Button
|
|
377
|
+
addView(TextView(this@CallActivity).apply {
|
|
378
|
+
layoutParams = FrameLayout.LayoutParams(dp(72), dp(72)).apply {
|
|
379
|
+
gravity = android.view.Gravity.CENTER
|
|
380
|
+
}
|
|
381
|
+
this.text = text
|
|
382
|
+
setTextColor(Color.WHITE)
|
|
383
|
+
setTextSize(TypedValue.COMPLEX_UNIT_SP, 28f)
|
|
384
|
+
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
|
|
385
|
+
gravity = android.view.Gravity.CENTER
|
|
386
|
+
background = GradientDrawable().apply {
|
|
387
|
+
shape = GradientDrawable.OVAL
|
|
388
|
+
colors = intArrayOf(
|
|
389
|
+
Color.parseColor(startColor),
|
|
390
|
+
Color.parseColor(endColor)
|
|
391
|
+
)
|
|
392
|
+
orientation = GradientDrawable.Orientation.TL_BR
|
|
393
|
+
setStroke(dp(2), Color.parseColor("#FF66BB6A"))
|
|
394
|
+
}
|
|
395
|
+
isClickable = true
|
|
396
|
+
})
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private fun createSpacerView(heightDp: Int): View {
|
|
401
|
+
return View(this).apply {
|
|
402
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
403
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
404
|
+
dp(heightDp)
|
|
405
|
+
)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
private fun createFlexibleSpacerView(): View {
|
|
410
|
+
return View(this).apply {
|
|
411
|
+
layoutParams = LinearLayout.LayoutParams(
|
|
412
|
+
LinearLayout.LayoutParams.MATCH_PARENT,
|
|
413
|
+
0,
|
|
414
|
+
1f
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
private fun updateCallerInfo(callerName: String, callerAvatar: String?) {
|
|
420
|
+
callerNameText.text = callerName
|
|
421
|
+
|
|
422
|
+
if (callerAvatar != null && callerAvatar.isNotEmpty()) {
|
|
423
|
+
// Load profile picture (you can use Glide, Picasso, or similar)
|
|
424
|
+
// For now, just show default
|
|
425
|
+
profileImage.setImageResource(android.R.drawable.sym_def_app_icon)
|
|
426
|
+
} else {
|
|
427
|
+
// Create default avatar with initials
|
|
428
|
+
profileImage.setImageDrawable(createDefaultAvatar(callerName))
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private fun createDefaultAvatar(name: String): GradientDrawable {
|
|
433
|
+
return GradientDrawable().apply {
|
|
434
|
+
shape = GradientDrawable.OVAL
|
|
435
|
+
setColor(Color.parseColor("#FF4CAF50"))
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
private fun setupButtonListeners() {
|
|
440
|
+
answerButton.setOnClickListener {
|
|
441
|
+
Log.d(TAG, "Answer clicked for callId: $callId")
|
|
442
|
+
finishReason = FinishReason.ANSWER
|
|
443
|
+
CallEngine.stopRingtone()
|
|
444
|
+
CallEngine.cancelIncomingCallUI()
|
|
445
|
+
CallEngine.answerCall(callId)
|
|
446
|
+
finishCallActivity()
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
declineButton.setOnClickListener {
|
|
450
|
+
Log.d(TAG, "Decline clicked for callId: $callId")
|
|
451
|
+
finishReason = FinishReason.DECLINE
|
|
452
|
+
CallEngine.stopRingtone()
|
|
453
|
+
CallEngine.cancelIncomingCallUI()
|
|
454
|
+
CallEngine.endCall(callId)
|
|
455
|
+
finishCallActivity()
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
private fun startPulseAnimation() {
|
|
460
|
+
pulseAnimator = ValueAnimator.ofFloat(1f, 1.2f).apply {
|
|
461
|
+
duration = 1500
|
|
462
|
+
repeatCount = ValueAnimator.INFINITE
|
|
463
|
+
repeatMode = ValueAnimator.REVERSE
|
|
464
|
+
interpolator = LinearInterpolator()
|
|
465
|
+
|
|
466
|
+
addUpdateListener { animation ->
|
|
467
|
+
val scale = animation.animatedValue as Float
|
|
468
|
+
// Apply to pulse rings (you can get references to them if needed)
|
|
469
|
+
// For now, this is a placeholder for the animation logic
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
pulseAnimator?.start()
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
private fun setupLockScreenBypass(isSamsungSpecific: Boolean) {
|
|
476
|
+
// Standard lock screen bypass
|
|
477
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
478
|
+
setShowWhenLocked(true)
|
|
479
|
+
setTurnScreenOn(true)
|
|
480
|
+
} else {
|
|
481
|
+
window.addFlags(
|
|
482
|
+
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
483
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
484
|
+
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
|
485
|
+
)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Samsung specific fixes
|
|
489
|
+
if (isSamsungSpecific) {
|
|
490
|
+
Log.d(TAG, "Applying Samsung-specific lock screen bypass")
|
|
491
|
+
window.addFlags(
|
|
492
|
+
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
493
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
494
|
+
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
|
|
495
|
+
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
|
499
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
500
|
+
keyguardManager.requestDismissKeyguard(this, object : KeyguardManager.KeyguardDismissCallback() {
|
|
501
|
+
override fun onDismissSucceeded() {
|
|
502
|
+
Log.d(TAG, "Samsung keyguard dismissed successfully")
|
|
503
|
+
}
|
|
504
|
+
override fun onDismissError() {
|
|
505
|
+
Log.w(TAG, "Samsung keyguard dismissal failed")
|
|
506
|
+
}
|
|
507
|
+
})
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Helper function to convert dp to pixels
|
|
513
|
+
private fun dp(value: Int): Int {
|
|
514
|
+
return TypedValue.applyDimension(
|
|
515
|
+
TypedValue.COMPLEX_UNIT_DIP,
|
|
516
|
+
value.toFloat(),
|
|
517
|
+
resources.displayMetrics
|
|
518
|
+
).toInt()
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
override fun onDestroy() {
|
|
522
|
+
super.onDestroy()
|
|
523
|
+
Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
|
|
524
|
+
|
|
525
|
+
// Stop animations
|
|
526
|
+
pulseAnimator?.cancel()
|
|
527
|
+
|
|
528
|
+
// Unregister listener
|
|
529
|
+
CallEngine.unregisterCallEndListener(this)
|
|
530
|
+
|
|
531
|
+
// Cancel timeout
|
|
532
|
+
timeoutHandler.removeCallbacks(timeoutRunnable)
|
|
533
|
+
|
|
534
|
+
// If user never answered, clean up ringtone/UI
|
|
535
|
+
if (finishReason != FinishReason.ANSWER) {
|
|
536
|
+
CallEngine.stopRingtone()
|
|
537
|
+
CallEngine.cancelIncomingCallUI()
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
override fun onBackPressed() {
|
|
542
|
+
Log.d(TAG, "onBackPressed for callId: $callId → treat as decline")
|
|
543
|
+
finishReason = FinishReason.MANUAL_DISMISS
|
|
544
|
+
CallEngine.stopRingtone()
|
|
545
|
+
CallEngine.cancelIncomingCallUI()
|
|
546
|
+
CallEngine.endCall(callId)
|
|
547
|
+
finishCallActivity()
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
override fun onCallEnded(endedCallId: String) {
|
|
551
|
+
if (endedCallId == callId && !isFinishing) {
|
|
552
|
+
Log.d(TAG, "CallActivity onCallEnded callback for callId: $callId")
|
|
553
|
+
finishReason = FinishReason.EXTERNAL_END
|
|
554
|
+
runOnUiThread { finishCallActivity() }
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private fun finishCallActivity() {
|
|
559
|
+
if (isFinishing) {
|
|
560
|
+
Log.d(TAG, "Already finishing, skip.")
|
|
561
|
+
return
|
|
562
|
+
}
|
|
563
|
+
Log.d(TAG, "Finishing CallActivity for callId: $callId")
|
|
564
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
565
|
+
finishAndRemoveTask()
|
|
566
|
+
} else {
|
|
567
|
+
finish()
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
companion object {
|
|
572
|
+
private const val TAG = "CallActivity"
|
|
573
|
+
}
|
|
181
574
|
}
|
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"
|
|
3
|
-
android:color="#30FFFFFF">
|
|
4
|
-
<item>
|
|
5
|
-
<shape android:shape="oval">
|
|
6
|
-
<solid android:color="#40FFFFFF" />
|
|
7
|
-
<stroke
|
|
8
|
-
android:width="2dp"
|
|
9
|
-
android:color="#60FFFFFF" />
|
|
10
|
-
</shape>
|
|
11
|
-
</item>
|
|
12
|
-
</ripple>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:color="#40FFFFFF">
|
|
4
|
-
<item>
|
|
5
|
-
<shape android:shape="oval">
|
|
6
|
-
<gradient
|
|
7
|
-
android:startColor="#4CAF50"
|
|
8
|
-
android:endColor="#388E3C"
|
|
9
|
-
android:angle="135" />
|
|
10
|
-
<stroke
|
|
11
|
-
android:width="3dp"
|
|
12
|
-
android:color="#66BB6A" />
|
|
13
|
-
</shape>
|
|
14
|
-
</item>
|
|
15
|
-
</ripple>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:shape="oval">
|
|
4
|
-
<gradient
|
|
5
|
-
android:startColor="#40000000"
|
|
6
|
-
android:centerColor="#20000000"
|
|
7
|
-
android:endColor="#00000000"
|
|
8
|
-
android:type="radial"
|
|
9
|
-
android:gradientRadius="40dp" />
|
|
10
|
-
</shape>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:shape="oval">
|
|
4
|
-
<gradient
|
|
5
|
-
android:startColor="#40FFFFFF"
|
|
6
|
-
android:centerColor="#20FFFFFF"
|
|
7
|
-
android:endColor="#00FFFFFF"
|
|
8
|
-
android:type="radial"
|
|
9
|
-
android:gradientRadius="70dp" />
|
|
10
|
-
</shape>
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
-
<!-- Base gradient -->
|
|
4
|
-
<item>
|
|
5
|
-
<shape>
|
|
6
|
-
<gradient
|
|
7
|
-
android:startColor="#1a237e"
|
|
8
|
-
android:centerColor="#283593"
|
|
9
|
-
android:endColor="#3949ab"
|
|
10
|
-
android:angle="135" />
|
|
11
|
-
</shape>
|
|
12
|
-
</item>
|
|
13
|
-
|
|
14
|
-
<!-- Abstract pattern overlay -->
|
|
15
|
-
<item>
|
|
16
|
-
<shape>
|
|
17
|
-
<gradient
|
|
18
|
-
android:startColor="#20FFFFFF"
|
|
19
|
-
android:centerColor="#10FFFFFF"
|
|
20
|
-
android:endColor="#05FFFFFF"
|
|
21
|
-
android:angle="45" />
|
|
22
|
-
</shape>
|
|
23
|
-
</item>
|
|
24
|
-
</layer-list>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:color="#40FFFFFF">
|
|
4
|
-
<item>
|
|
5
|
-
<shape android:shape="oval">
|
|
6
|
-
<gradient
|
|
7
|
-
android:startColor="#F44336"
|
|
8
|
-
android:endColor="#D32F2F"
|
|
9
|
-
android:angle="135" />
|
|
10
|
-
<stroke
|
|
11
|
-
android:width="3dp"
|
|
12
|
-
android:color="#EF5350" />
|
|
13
|
-
</shape>
|
|
14
|
-
</item>
|
|
15
|
-
</ripple>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:shape="oval">
|
|
4
|
-
<gradient
|
|
5
|
-
android:startColor="#40000000"
|
|
6
|
-
android:centerColor="#20000000"
|
|
7
|
-
android:endColor="#00000000"
|
|
8
|
-
android:type="radial"
|
|
9
|
-
android:gradientRadius="40dp" />
|
|
10
|
-
</shape>
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
android:id="@+id/call_root"
|
|
4
|
-
android:layout_width="match_parent"
|
|
5
|
-
android:layout_height="match_parent"
|
|
6
|
-
android:background="@drawable/call_background">
|
|
7
|
-
|
|
8
|
-
<!-- Overlay for better text readability -->
|
|
9
|
-
<View
|
|
10
|
-
android:layout_width="match_parent"
|
|
11
|
-
android:layout_height="match_parent"
|
|
12
|
-
android:background="@drawable/overlay_gradient" />
|
|
13
|
-
|
|
14
|
-
<!-- Top section with incoming call info -->
|
|
15
|
-
<LinearLayout
|
|
16
|
-
android:id="@+id/top_section"
|
|
17
|
-
android:layout_width="match_parent"
|
|
18
|
-
android:layout_height="wrap_content"
|
|
19
|
-
android:layout_centerInParent="true"
|
|
20
|
-
android:layout_marginTop="80dp"
|
|
21
|
-
android:gravity="center"
|
|
22
|
-
android:orientation="vertical"
|
|
23
|
-
android:padding="32dp">
|
|
24
|
-
|
|
25
|
-
<TextView
|
|
26
|
-
android:layout_width="wrap_content"
|
|
27
|
-
android:layout_height="wrap_content"
|
|
28
|
-
android:text="Incoming call"
|
|
29
|
-
android:textColor="#B3FFFFFF"
|
|
30
|
-
android:textSize="16sp"
|
|
31
|
-
android:layout_marginBottom="24dp"
|
|
32
|
-
android:letterSpacing="0.1" />
|
|
33
|
-
|
|
34
|
-
<!-- Avatar with glow effect -->
|
|
35
|
-
<FrameLayout
|
|
36
|
-
android:layout_width="140dp"
|
|
37
|
-
android:layout_height="140dp"
|
|
38
|
-
android:layout_marginBottom="24dp">
|
|
39
|
-
|
|
40
|
-
<View
|
|
41
|
-
android:layout_width="140dp"
|
|
42
|
-
android:layout_height="140dp"
|
|
43
|
-
android:background="@drawable/avatar_glow" />
|
|
44
|
-
|
|
45
|
-
<ImageView
|
|
46
|
-
android:id="@+id/avatar"
|
|
47
|
-
android:layout_width="120dp"
|
|
48
|
-
android:layout_height="120dp"
|
|
49
|
-
android:layout_gravity="center"
|
|
50
|
-
android:background="@drawable/avatar_bg"
|
|
51
|
-
android:scaleType="centerCrop"
|
|
52
|
-
android:src="@android:drawable/sym_def_app_icon" />
|
|
53
|
-
</FrameLayout>
|
|
54
|
-
|
|
55
|
-
<TextView
|
|
56
|
-
android:id="@+id/caller_name"
|
|
57
|
-
android:layout_width="wrap_content"
|
|
58
|
-
android:layout_height="wrap_content"
|
|
59
|
-
android:text="Caller Name"
|
|
60
|
-
android:textColor="#FFFFFF"
|
|
61
|
-
android:textSize="28sp"
|
|
62
|
-
android:textStyle="bold"
|
|
63
|
-
android:layout_marginBottom="8dp"
|
|
64
|
-
android:shadowColor="#33000000"
|
|
65
|
-
android:shadowDx="0"
|
|
66
|
-
android:shadowDy="2"
|
|
67
|
-
android:shadowRadius="4" />
|
|
68
|
-
|
|
69
|
-
<TextView
|
|
70
|
-
android:layout_width="wrap_content"
|
|
71
|
-
android:layout_height="wrap_content"
|
|
72
|
-
android:text="Mobile"
|
|
73
|
-
android:textColor="#B3FFFFFF"
|
|
74
|
-
android:textSize="16sp"
|
|
75
|
-
android:layout_marginBottom="48dp" />
|
|
76
|
-
|
|
77
|
-
</LinearLayout>
|
|
78
|
-
|
|
79
|
-
<!-- Bottom section with action buttons -->
|
|
80
|
-
<LinearLayout
|
|
81
|
-
android:layout_width="match_parent"
|
|
82
|
-
android:layout_height="wrap_content"
|
|
83
|
-
android:layout_alignParentBottom="true"
|
|
84
|
-
android:layout_marginBottom="80dp"
|
|
85
|
-
android:gravity="center"
|
|
86
|
-
android:orientation="horizontal"
|
|
87
|
-
android:padding="32dp">
|
|
88
|
-
|
|
89
|
-
<!-- Additional quick actions -->
|
|
90
|
-
<FrameLayout
|
|
91
|
-
android:layout_width="56dp"
|
|
92
|
-
android:layout_height="56dp"
|
|
93
|
-
android:layout_marginEnd="32dp">
|
|
94
|
-
|
|
95
|
-
<ImageView
|
|
96
|
-
android:layout_width="56dp"
|
|
97
|
-
android:layout_height="56dp"
|
|
98
|
-
android:background="@drawable/action_button_secondary"
|
|
99
|
-
android:src="@android:drawable/ic_menu_call"
|
|
100
|
-
android:padding="16dp"
|
|
101
|
-
android:tint="#FFFFFF" />
|
|
102
|
-
</FrameLayout>
|
|
103
|
-
|
|
104
|
-
<!-- Decline Button -->
|
|
105
|
-
<FrameLayout
|
|
106
|
-
android:layout_width="80dp"
|
|
107
|
-
android:layout_height="80dp"
|
|
108
|
-
android:layout_marginEnd="48dp">
|
|
109
|
-
|
|
110
|
-
<View
|
|
111
|
-
android:layout_width="80dp"
|
|
112
|
-
android:layout_height="80dp"
|
|
113
|
-
android:background="@drawable/decline_button_shadow" />
|
|
114
|
-
|
|
115
|
-
<Button
|
|
116
|
-
android:id="@+id/decline_btn"
|
|
117
|
-
android:layout_width="72dp"
|
|
118
|
-
android:layout_height="72dp"
|
|
119
|
-
android:layout_gravity="center"
|
|
120
|
-
android:background="@drawable/decline_button"
|
|
121
|
-
android:text="✕"
|
|
122
|
-
android:textColor="#FFFFFF"
|
|
123
|
-
android:textSize="24sp"
|
|
124
|
-
android:textStyle="bold" />
|
|
125
|
-
</FrameLayout>
|
|
126
|
-
|
|
127
|
-
<!-- Answer Button -->
|
|
128
|
-
<FrameLayout
|
|
129
|
-
android:layout_width="80dp"
|
|
130
|
-
android:layout_height="80dp">
|
|
131
|
-
|
|
132
|
-
<View
|
|
133
|
-
android:layout_width="80dp"
|
|
134
|
-
android:layout_height="80dp"
|
|
135
|
-
android:background="@drawable/answer_button_shadow" />
|
|
136
|
-
|
|
137
|
-
<Button
|
|
138
|
-
android:id="@+id/answer_btn"
|
|
139
|
-
android:layout_width="72dp"
|
|
140
|
-
android:layout_height="72dp"
|
|
141
|
-
android:layout_gravity="center"
|
|
142
|
-
android:background="@drawable/answer_button"
|
|
143
|
-
android:text="✓"
|
|
144
|
-
android:textColor="#FFFFFF"
|
|
145
|
-
android:textSize="24sp"
|
|
146
|
-
android:textStyle="bold" />
|
|
147
|
-
</FrameLayout>
|
|
148
|
-
|
|
149
|
-
<!-- Message quick action -->
|
|
150
|
-
<FrameLayout
|
|
151
|
-
android:layout_width="56dp"
|
|
152
|
-
android:layout_height="56dp"
|
|
153
|
-
android:layout_marginStart="32dp">
|
|
154
|
-
|
|
155
|
-
<ImageView
|
|
156
|
-
android:layout_width="56dp"
|
|
157
|
-
android:layout_height="56dp"
|
|
158
|
-
android:background="@drawable/action_button_secondary"
|
|
159
|
-
android:src="@android:drawable/ic_menu_send"
|
|
160
|
-
android:padding="16dp"
|
|
161
|
-
android:tint="#FFFFFF" />
|
|
162
|
-
</FrameLayout>
|
|
163
|
-
|
|
164
|
-
</LinearLayout>
|
|
165
|
-
|
|
166
|
-
</RelativeLayout>
|