@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.notifications.v2
33import android.app.Notification
44import android.app.PendingIntent
55import android.content.Context
6+ import android.content.Intent
67import android.graphics.Bitmap
78import android.graphics.Color
89import android.net.Uri
@@ -13,6 +14,7 @@ import androidx.annotation.DrawableRes
1314import androidx.annotation.StringRes
1415import androidx.annotation.WorkerThread
1516import androidx.core.app.NotificationCompat
17+ import androidx.core.app.NotificationManagerCompat
1618import androidx.core.app.RemoteInput
1719import androidx.core.content.LocusIdCompat
1820import androidx.core.graphics.drawable.IconCompat
@@ -82,7 +84,7 @@ sealed class NotificationBuilder(protected val context: Context) {
8284 protected abstract fun addActions (replyMethod : ReplyMethod , conversation : NotificationConversation )
8385 protected abstract fun addMarkAsReadActionActual (conversation : NotificationConversation )
8486 protected abstract fun addMarkAsReadActionActual (state : NotificationState )
85- protected abstract fun addMessagesActual (conversation : NotificationConversation , includeShortcut : Boolean )
87+ protected abstract fun addMessagesActual (conversation : NotificationConversation , includeShortcut : Boolean , includeMediaContent : Boolean )
8688 protected abstract fun addMessagesActual (state : NotificationState )
8789
8890 @WorkerThread
@@ -145,8 +147,8 @@ sealed class NotificationBuilder(protected val context: Context) {
145147 }
146148 }
147149
148- fun addMessages (conversation : NotificationConversation ) {
149- addMessagesActual(conversation, privacy.isDisplayContact)
150+ fun addMessages (conversation : NotificationConversation , includeMediaContent : Boolean = true ) {
151+ addMessagesActual(conversation, privacy.isDisplayContact, includeMediaContent )
150152 }
151153
152154 fun addMessages (state : NotificationState ) {
@@ -200,10 +202,9 @@ sealed class NotificationBuilder(protected val context: Context) {
200202 */
201203 private class NotificationBuilderCompat (context : Context ) : NotificationBuilder(context) {
202204 val builder: NotificationCompat .Builder = NotificationCompat .Builder (context, NotificationChannels .getInstance().messagesChannel)
205+ private val wearableExtender: NotificationCompat .WearableExtender = NotificationCompat .WearableExtender ()
203206
204207 override fun addActions (replyMethod : ReplyMethod , conversation : NotificationConversation ) {
205- val extender: NotificationCompat .WearableExtender = NotificationCompat .WearableExtender ()
206-
207208 addMarkAsReadActionActual(conversation)
208209
209210 if (conversation.mostRecentNotification.canReply(context)) {
@@ -231,11 +232,9 @@ sealed class NotificationBuilder(protected val context: Context) {
231232 .addRemoteInput(RemoteInput .Builder (DefaultMessageNotifier .EXTRA_REMOTE_REPLY ).setLabel(label).build())
232233 .build()
233234
234- extender .addAction(wearableReplyAction)
235+ wearableExtender .addAction(wearableReplyAction)
235236 }
236237 }
237-
238- builder.extend(extender)
239238 }
240239
241240 override fun addMarkAsReadActionActual (conversation : NotificationConversation ) {
@@ -248,7 +247,7 @@ sealed class NotificationBuilder(protected val context: Context) {
248247 .build()
249248
250249 builder.addAction(markAsReadAction)
251- builder.extend( NotificationCompat . WearableExtender (). addAction(markAsReadAction) )
250+ wearableExtender. addAction(markAsReadAction)
252251 }
253252 }
254253
@@ -258,7 +257,7 @@ sealed class NotificationBuilder(protected val context: Context) {
258257 if (markAsRead != null ) {
259258 val markAllAsReadAction = NotificationCompat .Action (CoreUiR .drawable.symbol_check_24, context.getString(R .string.MessageNotifier_mark_all_as_read ), markAsRead)
260259 builder.addAction(markAllAsReadAction)
261- builder.extend( NotificationCompat . WearableExtender (). addAction(markAllAsReadAction) )
260+ wearableExtender. addAction(markAllAsReadAction)
262261 }
263262 }
264263
@@ -274,8 +273,8 @@ sealed class NotificationBuilder(protected val context: Context) {
274273 }
275274 }
276275
277- override fun addMessagesActual (conversation : NotificationConversation , includeShortcut : Boolean ) {
278- if (Build .VERSION .SDK_INT < 24 ) {
276+ override fun addMessagesActual (conversation : NotificationConversation , includeShortcut : Boolean , includeMediaContent : Boolean ) {
277+ if (Build .VERSION .SDK_INT < 24 && includeMediaContent ) {
279278 val bigPictureUri: Uri ? = conversation.getSlideBigPictureUri(context)
280279 if (bigPictureUri != null ) {
281280 builder.setStyle(
@@ -317,14 +316,41 @@ sealed class NotificationBuilder(protected val context: Context) {
317316 person = personBuilder.build()
318317 }
319318
320- val (dataUri: Uri ? , mimeType: String? ) = notificationItem.getThumbnailInfo(context)
319+ val thumbnailInfos: List <NotificationItem .ThumbnailInfo > = if (includeMediaContent) {
320+ notificationItem.getThumbnailInfos(context)
321+ } else {
322+ emptyList()
323+ }
324+ val mediaContents: List <MessageMediaContent > = thumbnailInfos.toMessageMediaContent()
321325
322- messagingStyle.addMessage(NotificationCompat .MessagingStyle .Message (notificationItem.getPrimaryText(context), notificationItem.timestamp, person).setData(mimeType, dataUri))
326+ if (! includeMediaContent || thumbnailInfos.isEmpty()) {
327+ messagingStyle.addMessage(NotificationCompat .MessagingStyle .Message (notificationItem.getPrimaryText(context), notificationItem.timestamp, person))
328+ } else {
329+ mediaContents.forEach { mediaContent ->
330+ val message = NotificationCompat .MessagingStyle .Message (" " , notificationItem.timestamp, person)
331+
332+ grantNotificationListenerReadAccess(mediaContent.uri)
333+ message.setData(mediaContent.contentType, mediaContent.uri)
334+ messagingStyle.addMessage(message)
335+ }
336+ }
323337 }
324338
325339 builder.setStyle(messagingStyle)
326340 }
327341
342+ private fun grantNotificationListenerReadAccess (uri : Uri ? ) {
343+ if (uri == null ) {
344+ return
345+ }
346+
347+ NotificationManagerCompat .getEnabledListenerPackages(context).forEach { packageName ->
348+ runCatching {
349+ context.grantUriPermission(packageName, uri, Intent .FLAG_GRANT_READ_URI_PERMISSION )
350+ }
351+ }
352+ }
353+
328354 override fun addMessagesActual (state : NotificationState ) {
329355 if (Build .VERSION .SDK_INT >= 24 ) {
330356 return
@@ -486,6 +512,7 @@ sealed class NotificationBuilder(protected val context: Context) {
486512 }
487513
488514 override fun build (): Notification {
515+ builder.extend(wearableExtender)
489516 return builder.build()
490517 }
491518
@@ -517,6 +544,17 @@ sealed class NotificationBuilder(protected val context: Context) {
517544 }
518545}
519546
547+ private fun List<NotificationItem.ThumbnailInfo>.toMessageMediaContent (): List <MessageMediaContent > {
548+ return mapNotNull { thumbnailInfo ->
549+ val uri: Uri = thumbnailInfo.uri ? : return @mapNotNull null
550+ val contentType: String = thumbnailInfo.contentType ? : return @mapNotNull null
551+
552+ MessageMediaContent (uri, contentType)
553+ }
554+ }
555+
556+ private data class MessageMediaContent (val uri : Uri , val contentType : String )
557+
520558private fun Bitmap?.toIconCompat (): IconCompat ? {
521559 return if (this != null ) {
522560 IconCompat .createWithBitmap(this )
0 commit comments