1515 */
1616package im.vector.app.features.notifications
1717
18+ import android.net.Uri
1819import im.vector.app.BuildConfig
1920import im.vector.app.R
21+ import im.vector.app.core.extensions.takeAs
2022import im.vector.app.core.resources.StringProvider
2123import im.vector.app.features.displayname.getBestName
2224import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter
@@ -28,12 +30,15 @@ import org.matrix.android.sdk.api.session.crypto.MXCryptoError
2830import org.matrix.android.sdk.api.session.events.model.Event
2931import org.matrix.android.sdk.api.session.events.model.EventType
3032import org.matrix.android.sdk.api.session.events.model.isEdition
33+ import org.matrix.android.sdk.api.session.events.model.isImageMessage
3134import org.matrix.android.sdk.api.session.events.model.toModel
3235import org.matrix.android.sdk.api.session.room.model.Membership
3336import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
37+ import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
3438import org.matrix.android.sdk.api.session.room.sender.SenderInfo
3539import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
3640import org.matrix.android.sdk.api.session.room.timeline.getEditedEventId
41+ import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
3742import org.matrix.android.sdk.api.util.toMatrixItem
3843import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
3944import timber.log.Timber
@@ -49,11 +54,12 @@ import javax.inject.Inject
4954class NotifiableEventResolver @Inject constructor(
5055 private val stringProvider : StringProvider ,
5156 private val noticeEventFormatter : NoticeEventFormatter ,
52- private val displayableEventFormatter : DisplayableEventFormatter ) {
57+ private val displayableEventFormatter : DisplayableEventFormatter
58+ ) {
5359
5460 // private val eventDisplay = RiotEventDisplay(context)
5561
56- fun resolveEvent (event : Event /* , roomState: RoomState?, bingRule: PushRule?*/ , session : Session , isNoisy : Boolean ): NotifiableEvent ? {
62+ suspend fun resolveEvent (event : Event /* , roomState: RoomState?, bingRule: PushRule?*/ , session : Session , isNoisy : Boolean ): NotifiableEvent ? {
5763 val roomID = event.roomId ? : return null
5864 val eventId = event.eventId ? : return null
5965 if (event.getClearType() == EventType .STATE_ROOM_MEMBER ) {
@@ -89,7 +95,7 @@ class NotifiableEventResolver @Inject constructor(
8995 }
9096 }
9197
92- fun resolveInMemoryEvent (session : Session , event : Event , canBeReplaced : Boolean ): NotifiableEvent ? {
98+ suspend fun resolveInMemoryEvent (session : Session , event : Event , canBeReplaced : Boolean ): NotifiableEvent ? {
9399 if (event.getClearType() != EventType .MESSAGE ) return null
94100
95101 // Ignore message edition
@@ -120,7 +126,7 @@ class NotifiableEventResolver @Inject constructor(
120126 }
121127 }
122128
123- private fun resolveMessageEvent (event : TimelineEvent , session : Session , canBeReplaced : Boolean , isNoisy : Boolean ): NotifiableEvent {
129+ private suspend fun resolveMessageEvent (event : TimelineEvent , session : Session , canBeReplaced : Boolean , isNoisy : Boolean ): NotifiableEvent {
124130 // The event only contains an eventId, and roomId (type is m.room.*) , we need to get the displayable content (names, avatar, text, etc...)
125131 val room = session.getRoom(event.root.roomId!! /* roomID cannot be null*/ )
126132
@@ -140,6 +146,7 @@ class NotifiableEventResolver @Inject constructor(
140146 senderName = senderDisplayName,
141147 senderId = event.root.senderId,
142148 body = body.toString(),
149+ imageUri = event.fetchImageIfPresent(session),
143150 roomId = event.root.roomId!! ,
144151 roomName = roomName,
145152 matrixID = session.myUserId
@@ -173,6 +180,7 @@ class NotifiableEventResolver @Inject constructor(
173180 senderName = senderDisplayName,
174181 senderId = event.root.senderId,
175182 body = body,
183+ imageUri = event.fetchImageIfPresent(session),
176184 roomId = event.root.roomId!! ,
177185 roomName = roomName,
178186 roomIsDirect = room.roomSummary()?.isDirect ? : false ,
@@ -192,6 +200,26 @@ class NotifiableEventResolver @Inject constructor(
192200 }
193201 }
194202
203+ private suspend fun TimelineEvent.fetchImageIfPresent (session : Session ): Uri ? {
204+ return when {
205+ root.isEncrypted() && root.mxDecryptionResult == null -> null
206+ root.isImageMessage() -> downloadAndExportImage(session)
207+ else -> null
208+ }
209+ }
210+
211+ private suspend fun TimelineEvent.downloadAndExportImage (session : Session ): Uri ? {
212+ return kotlin.runCatching {
213+ getLastMessageContent()?.takeAs<MessageWithAttachmentContent >()?.let { imageMessage ->
214+ val fileService = session.fileService()
215+ fileService.downloadFile(imageMessage)
216+ fileService.getTemporarySharableURI(imageMessage)
217+ }
218+ }.onFailure {
219+ Timber .e(it, " Failed to download and export image for notification" )
220+ }.getOrNull()
221+ }
222+
195223 private fun resolveStateRoomEvent (event : Event , session : Session , canBeReplaced : Boolean , isNoisy : Boolean ): NotifiableEvent ? {
196224 val content = event.content?.toModel<RoomMemberContent >() ? : return null
197225 val roomId = event.roomId ? : return null
0 commit comments