@@ -45,6 +45,7 @@ import coil.request.ImageRequest
4545import com.bluelinelabs.logansquare.LoganSquare
4646import com.nextcloud.talk.BuildConfig
4747import com.nextcloud.talk.R
48+ import com.nextcloud.talk.activities.CallActivity
4849import com.nextcloud.talk.activities.MainActivity
4950import com.nextcloud.talk.api.NcApi
5051import com.nextcloud.talk.application.NextcloudTalkApplication
@@ -61,6 +62,7 @@ import com.nextcloud.talk.models.json.participants.Participant
6162import com.nextcloud.talk.models.json.participants.ParticipantsOverall
6263import com.nextcloud.talk.models.json.push.DecryptedPushMessage
6364import com.nextcloud.talk.models.json.push.NotificationUser
65+ import com.nextcloud.talk.receivers.CallNotificationActionReceiver
6466import com.nextcloud.talk.receivers.DirectReplyReceiver
6567import com.nextcloud.talk.receivers.DismissRecordingAvailableReceiver
6668import com.nextcloud.talk.receivers.MarkAsReadReceiver
@@ -95,7 +97,6 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_THREAD_ID
9597import com.nextcloud.talk.utils.preferences.AppPreferences
9698import io.reactivex.Observable
9799import io.reactivex.Observer
98- import io.reactivex.android.schedulers.AndroidSchedulers
99100import io.reactivex.disposables.Disposable
100101import io.reactivex.schedulers.Schedulers
101102import okhttp3.JavaNetCookieJar
@@ -268,11 +269,66 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
268269 }
269270 )
270271
272+ val pendingIntentFlags = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
273+ PendingIntent .FLAG_IMMUTABLE or PendingIntent .FLAG_UPDATE_CURRENT
274+ } else {
275+ PendingIntent .FLAG_UPDATE_CURRENT
276+ }
277+
278+ val answerVoiceBundle = Bundle (bundle).apply { putBoolean(BundleKeys .KEY_CALL_VOICE_ONLY , true ) }
279+ val answerVoicePendingIntent = PendingIntent .getActivity(
280+ applicationContext,
281+ requestCode + ANSWER_VOICE_REQUEST_OFFSET ,
282+ Intent (applicationContext, CallActivity ::class .java).apply {
283+ putExtras(answerVoiceBundle)
284+ addFlags(Intent .FLAG_ACTIVITY_NEW_TASK )
285+ },
286+ pendingIntentFlags
287+ )
288+
289+ val answerVideoBundle = Bundle (bundle).apply { putBoolean(BundleKeys .KEY_CALL_VOICE_ONLY , false ) }
290+ val answerVideoPendingIntent = PendingIntent .getActivity(
291+ applicationContext,
292+ requestCode + ANSWER_VIDEO_REQUEST_OFFSET ,
293+ Intent (applicationContext, CallActivity ::class .java).apply {
294+ putExtras(answerVideoBundle)
295+ addFlags(Intent .FLAG_ACTIVITY_NEW_TASK )
296+ },
297+ pendingIntentFlags
298+ )
299+
300+ val declinePendingIntent = PendingIntent .getBroadcast(
301+ applicationContext,
302+ requestCode + DECLINE_CALL_REQUEST_OFFSET ,
303+ Intent (applicationContext, CallNotificationActionReceiver ::class .java).apply {
304+ action = CallNotificationActionReceiver .ACTION_DECLINE_CALL
305+ putExtra(KEY_NOTIFICATION_TIMESTAMP , pushMessage.timestamp.toInt())
306+ },
307+ pendingIntentFlags
308+ )
309+
271310 val soundUri = getCallRingtoneUri(applicationContext, appPreferences)
272311 val notificationChannelId = NotificationUtils .NotificationChannels .NOTIFICATION_CHANNEL_CALLS_V4 .name
273312 val uri = signatureVerification.user!! .baseUrl!! .toUri()
274313 val baseUrl = uri.host
275314
315+ val callerPersonBuilder = Person .Builder ()
316+ .setName(conversation.displayName)
317+ .setImportant(true )
318+ if (conversation.type == ConversationEnums .ConversationType .ROOM_TYPE_ONE_TO_ONE_CALL ) {
319+ val avatarUrl = ApiUtils .getUrlForAvatar(
320+ signatureVerification.user!! .baseUrl!! ,
321+ conversation.name,
322+ false ,
323+ darkMode = DisplayUtils .isDarkModeOn(applicationContext)
324+ )
325+ loadAvatarSync(avatarUrl, applicationContext)?.let { callerPersonBuilder.setIcon(it) }
326+ }
327+ val callerPerson = callerPersonBuilder.build()
328+
329+ val isVideoCall = (conversation.callFlag and Participant .InCallFlags .WITH_VIDEO ) > 0
330+ val primaryAnswerIntent = if (isVideoCall) answerVideoPendingIntent else answerVoicePendingIntent
331+
276332 val notification =
277333 NotificationCompat .Builder (applicationContext, notificationChannelId)
278334 .setPriority(NotificationCompat .PRIORITY_HIGH )
@@ -289,6 +345,11 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
289345 .setContentIntent(fullScreenPendingIntent)
290346 .setFullScreenIntent(fullScreenPendingIntent, true )
291347 .setSound(soundUri)
348+ .setStyle(
349+ NotificationCompat .CallStyle
350+ .forIncomingCall(callerPerson, declinePendingIntent, primaryAnswerIntent)
351+ .setIsVideo(isVideoCall)
352+ )
292353 .build()
293354 notification.flags = notification.flags or Notification .FLAG_INSISTENT
294355
@@ -299,7 +360,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
299360
300361 chatNetworkDataSource?.getRoom(userBeingCalled, roomToken = pushMessage.id!! )
301362 ?.subscribeOn(Schedulers .io())
302- ?.observeOn(AndroidSchedulers .mainThread ())
363+ ?.observeOn(Schedulers .io ())
303364 ?.subscribe(object : Observer <ConversationModel > {
304365 override fun onSubscribe (d : Disposable ) {
305366 // unused atm
@@ -1107,5 +1168,8 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
11071168 private const val TIMER_COUNT = 12
11081169 private const val TIMER_DELAY : Long = 5
11091170 private const val LINEBREAK : String = " \n "
1171+ private const val ANSWER_VOICE_REQUEST_OFFSET = 1
1172+ private const val ANSWER_VIDEO_REQUEST_OFFSET = 2
1173+ private const val DECLINE_CALL_REQUEST_OFFSET = 3
11101174 }
11111175}
0 commit comments