Browse Source

restrict deletion of "Recording available" notification

...for preparation to replace Dialog that was openend in ChatController. It will be replaced by Notification Actions.

The dialog was not opened when already being in a chat, because remapChatController only moved the currentChatController to top so to won't be initialized again. That's why the dialog didn't pop up for this case.

As a solution, the actions should be available directly inside the notification.

For this, it must be avoided that the "recording available" notification is closed whenever the chat is opened.

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Marcel Hibbe 2 years ago
parent
commit
0f3662cd82

+ 94 - 31
app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt

@@ -85,6 +85,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MESSAGE_ID
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_ID
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_RECORDING_NOTIFICATION
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_RESTRICT_DELETION
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_TIMESTAMP
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SYSTEM_NOTIFICATION_ID
@@ -413,44 +414,17 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
         } else {
             pushMessage.subject = ncNotification.subject.orEmpty()
         }
-
-        if ("recording" == ncNotification.objectType) {
-            conversationType = "recording"
-        }
     }
 
     @Suppress("MagicNumber")
     private fun showNotification(intent: Intent) {
-        val largeIcon: Bitmap
-        val priority = NotificationCompat.PRIORITY_HIGH
-        val smallIcon: Int = R.drawable.ic_logo
-
-        var category: String = ""
+        var category = ""
         when (pushMessage.type) {
             TYPE_CHAT, TYPE_ROOM, TYPE_RECORDING -> category = Notification.CATEGORY_MESSAGE
             TYPE_CALL -> category = Notification.CATEGORY_CALL
             else -> Log.e(TAG, "unknown pushMessage.type")
         }
 
-        when (conversationType) {
-            "recording" -> {
-                largeIcon = ContextCompat.getDrawable(context!!, R.drawable.ic_baseline_videocam_24)?.toBitmap()!!
-            }
-            "one2one" -> {
-                pushMessage.subject = ""
-                largeIcon = ContextCompat.getDrawable(context!!, R.drawable.ic_people_group_black_24px)?.toBitmap()!!
-            }
-            "group" ->
-                largeIcon = ContextCompat.getDrawable(context!!, R.drawable.ic_people_group_black_24px)?.toBitmap()!!
-            "public" -> largeIcon = ContextCompat.getDrawable(context!!, R.drawable.ic_link_black_24px)?.toBitmap()!!
-            else -> // assuming one2one
-                largeIcon = if (TYPE_CHAT == pushMessage.type || TYPE_ROOM == pushMessage.type) {
-                    ContextCompat.getDrawable(context!!, R.drawable.ic_comment)?.toBitmap()!!
-                } else {
-                    ContextCompat.getDrawable(context!!, R.drawable.ic_call_black_24dp)?.toBitmap()!!
-                }
-        }
-
         // Use unique request code to make sure that a new PendingIntent gets created for each notification
         // See https://github.com/nextcloud/talk-android/issues/2111
         val requestCode = System.currentTimeMillis().toInt()
@@ -474,10 +448,10 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
         }
 
         val notificationBuilder = NotificationCompat.Builder(context!!, "1")
-            .setLargeIcon(largeIcon)
-            .setSmallIcon(smallIcon)
+            .setPriority(NotificationCompat.PRIORITY_HIGH)
             .setCategory(category)
-            .setPriority(priority)
+            .setLargeIcon(getLargeIcon())
+            .setSmallIcon(R.drawable.ic_logo)
             .setContentTitle(contentTitle)
             .setContentText(contentText)
             .setSubText(baseUrl)
@@ -492,6 +466,11 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
         // could be an ID or a TOKEN
         notificationInfoBundle.putString(KEY_ROOM_TOKEN, pushMessage.id)
         notificationInfoBundle.putLong(KEY_NOTIFICATION_ID, pushMessage.notificationId!!)
+
+        if (pushMessage.type == TYPE_RECORDING) {
+            notificationInfoBundle.putBoolean(KEY_NOTIFICATION_RESTRICT_DELETION, true)
+        }
+
         notificationBuilder.setExtras(notificationInfoBundle)
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -530,6 +509,15 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
             addMarkAsReadAction(notificationBuilder, systemNotificationId)
         }
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
+            TYPE_RECORDING == pushMessage.type &&
+            pushMessage.notificationUser != null
+        ) {
+            prepareChatNotification(notificationBuilder, activeStatusBarNotification, systemNotificationId)
+            // addDiscardRecordingAvailableAction(notificationBuilder, systemNotificationId)
+            // addShareRecordingToChatAction(notificationBuilder, systemNotificationId)
+        }
+
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
             TYPE_RECORDING == pushMessage.type &&
             pushMessage.notificationUser != null // null
@@ -539,6 +527,34 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
         sendNotification(systemNotificationId, notificationBuilder.build())
     }
 
+    private fun getLargeIcon(): Bitmap {
+        val largeIcon: Bitmap
+        if (pushMessage.type == "recording") {
+            largeIcon = ContextCompat.getDrawable(context!!, R.drawable.ic_baseline_videocam_24)?.toBitmap()!!
+        } else {
+            when (conversationType) {
+                "one2one" -> {
+                    pushMessage.subject = ""
+                    largeIcon =
+                        ContextCompat.getDrawable(context!!, R.drawable.ic_people_group_black_24px)?.toBitmap()!!
+                }
+                "group" ->
+                    largeIcon =
+                        ContextCompat.getDrawable(context!!, R.drawable.ic_people_group_black_24px)?.toBitmap()!!
+                "public" ->
+                    largeIcon =
+                        ContextCompat.getDrawable(context!!, R.drawable.ic_link_black_24px)?.toBitmap()!!
+                else -> // assuming one2one
+                    largeIcon = if (TYPE_CHAT == pushMessage.type || TYPE_ROOM == pushMessage.type) {
+                        ContextCompat.getDrawable(context!!, R.drawable.ic_comment)?.toBitmap()!!
+                    } else {
+                        ContextCompat.getDrawable(context!!, R.drawable.ic_call_black_24dp)?.toBitmap()!!
+                    }
+            }
+        }
+        return largeIcon
+    }
+
     private fun calculateCRC32(s: String): Long {
         val crc32 = CRC32()
         crc32.update(s.toByteArray())
@@ -646,6 +662,51 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
         notificationBuilder.addAction(replyAction)
     }
 
+    // @RequiresApi(api = Build.VERSION_CODES.N)
+    // private fun addDiscardRecordingAvailableAction(notificationBuilder: NotificationCompat.Builder,
+    //     systemNotificationId:
+    // Int) {
+    //     val replyLabel = context!!.resources.getString(R.string.nc_reply)
+    //     val remoteInput = RemoteInput.Builder(NotificationUtils.KEY_DIRECT_REPLY)
+    //         .setLabel(replyLabel)
+    //         .build()
+    //
+    //     val replyPendingIntent = buildIntentForAction(
+    //         DirectReplyReceiver::class.java,
+    //         systemNotificationId,
+    //         0
+    //     )
+    //     val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, replyLabel, replyPendingIntent)
+    //         .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
+    //         .setShowsUserInterface(false)
+    //         .setAllowGeneratedReplies(true)
+    //         .addRemoteInput(remoteInput)
+    //         .build()
+    //     notificationBuilder.addAction(replyAction)
+    // }
+    //
+    // @RequiresApi(api = Build.VERSION_CODES.N)
+    // private fun addShareRecordingToChatAction(notificationBuilder: NotificationCompat.Builder, systemNotificationId:
+    // Int) {
+    //     val replyLabel = context!!.resources.getString(R.string.nc_reply)
+    //     val remoteInput = RemoteInput.Builder(NotificationUtils.KEY_DIRECT_REPLY)
+    //         .setLabel(replyLabel)
+    //         .build()
+    //
+    //     val replyPendingIntent = buildIntentForAction(
+    //         DirectReplyReceiver::class.java,
+    //         systemNotificationId,
+    //         0
+    //     )
+    //     val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, replyLabel, replyPendingIntent)
+    //         .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
+    //         .setShowsUserInterface(false)
+    //         .setAllowGeneratedReplies(true)
+    //         .addRemoteInput(remoteInput)
+    //         .build()
+    //     notificationBuilder.addAction(replyAction)
+    // }
+
     @RequiresApi(api = Build.VERSION_CODES.N)
     private fun getStyle(person: Person, style: NotificationCompat.MessagingStyle?): NotificationCompat.MessagingStyle {
         val newStyle = NotificationCompat.MessagingStyle(person)
@@ -860,6 +921,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
                 })
         }
     }
+
     private fun createMainActivityIntent(): Intent {
         val intent = Intent(context, MainActivity::class.java)
         intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
@@ -870,6 +932,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
         intent.putExtras(bundle)
         return intent
     }
+
     private fun getIntentToOpenConversation(): PendingIntent? {
         val intent = Intent(context, MainActivity::class.java)
         intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK

+ 3 - 1
app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.kt

@@ -267,7 +267,9 @@ object NotificationUtils {
 
     fun cancelExistingNotificationsForRoom(context: Context?, conversationUser: User, roomTokenOrId: String) {
         scanNotifications(context, conversationUser) { notificationManager, statusBarNotification, notification ->
-            if (roomTokenOrId == notification.extras.getString(BundleKeys.KEY_ROOM_TOKEN)) {
+            if (roomTokenOrId == notification.extras.getString(BundleKeys.KEY_ROOM_TOKEN) &&
+                !notification.extras.getBoolean(BundleKeys.KEY_NOTIFICATION_RESTRICT_DELETION)
+            ) {
                 notificationManager.cancel(statusBarNotification.id)
             }
         }

+ 1 - 0
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt

@@ -83,4 +83,5 @@ object BundleKeys {
     const val KEY_SWITCH_TO_ROOM_AND_START_CALL = "KEY_SWITCH_TO_ROOM_AND_START_CALL"
     const val KEY_IS_BREAKOUT_ROOM = "KEY_IS_BREAKOUT_ROOM"
     const val KEY_NOTIFICATION_RECORDING_NOTIFICATION = "KEY_NOTIFICATION_RECORDING_NOTIFICATION"
+    const val KEY_NOTIFICATION_RESTRICT_DELETION = "KEY_NOTIFICATION_RESTRICT_DELETION"
 }