88package com.nextcloud.talk.chat.ui.model
99
1010import android.text.TextUtils
11+ import android.util.Log
1112import androidx.compose.runtime.Immutable
1213import androidx.compose.runtime.Stable
1314import androidx.compose.ui.text.AnnotatedString
1415import androidx.compose.ui.text.buildAnnotatedString
16+ import com.nextcloud.talk.R
17+ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
1518import com.nextcloud.talk.chat.data.model.ChatMessage
1619import com.nextcloud.talk.data.database.model.SendStatus
20+ import com.nextcloud.talk.data.user.model.User
21+ import com.nextcloud.talk.utils.ApiUtils
1722import com.nextcloud.talk.utils.DrawableUtils
23+ import java.security.MessageDigest
1824import java.time.LocalDate
25+ import kotlin.collections.component1
26+ import kotlin.collections.component2
27+ import kotlin.collections.iterator
1928
2029// immutable class for chat message UI. only val, no vars!
2130@Stable // TODO: or @Immutable ?
@@ -46,7 +55,7 @@ sealed interface MessageTypeContent {
4655 val todo : String
4756 ) : MessageTypeContent
4857
49- data class Image (val imageUrl : String , val drawableResourceId : Int ) : MessageTypeContent
58+ data class Image (val imageUrl : String? , val drawableResourceId : Int ) : MessageTypeContent
5059
5160 data class Geolocation (val lat : Double , val lon : Double ) : MessageTypeContent
5261
@@ -70,6 +79,7 @@ enum class MessageStatusIcon {
7079
7180// Domain model (ChatMessage) to UI model (ChatMessageUi)
7281fun ChatMessage.toUiModel (
82+ user : User ,
7383 chatMessage : ChatMessage ,
7484 lastCommonReadMessageId : Int ,
7585 parentMessage : ChatMessage ?
@@ -93,10 +103,10 @@ fun ChatMessage.toUiModel(
93103 ),
94104 timestamp = timestamp,
95105 date = dateKey(),
96- content = getMessageTypeContent(chatMessage),
106+ content = getMessageTypeContent(user, chatMessage),
97107 // setting parent message recursively might be a problem regarding recompositions? extract only what is needed
98108 // for UI?
99- parentMessage = parentMessage?.toUiModel(parentMessage, 0 , null )
109+ parentMessage = parentMessage?.toUiModel(user, parentMessage, 0 , null )
100110 )
101111
102112fun resolveStatusIcon (
@@ -117,13 +127,16 @@ fun resolveStatusIcon(
117127 return status
118128}
119129
120- fun getMessageTypeContent (message : ChatMessage ): MessageTypeContent ? =
130+ fun getMessageTypeContent (
131+ user : User ,
132+ message : ChatMessage
133+ ): MessageTypeContent ? =
121134 if (! TextUtils .isEmpty(message.systemMessage)) {
122135 MessageTypeContent .SystemMessage
123136 } else if (message.isVoiceMessage) {
124137 getVoiceContent(message)
125138 } else if (message.hasFileAttachment()) {
126- getImageContent(message)
139+ getImageContent(user, message)
127140 } else if (message.hasGeoLocation()) {
128141 getGeolocationContent(message)
129142 } else if (message.isLinkPreview()) {
@@ -141,17 +154,59 @@ fun getLinkPreviewContent(message: ChatMessage): MessageTypeContent.LinkPreview
141154 todo = " still todo..."
142155 )
143156
144- fun getImageContent (message : ChatMessage ): MessageTypeContent .Image {
145- val imageUri = message.imageUrl
146- val mimetype = message.selectedIndividualHashMap!! [" mimetype" ]
157+ fun getImageContent (
158+ user : User ,
159+ message : ChatMessage
160+ ): MessageTypeContent .Image {
161+ val imageUri = getImageUrl(user, message)
162+ val mimetype = getMimetype(message)
147163 val drawableResourceId = DrawableUtils .getDrawableResourceIdForMimeType(mimetype)
148164
149165 return MessageTypeContent .Image (
150- imageUri!! ,
166+ imageUri,
151167 drawableResourceId
152168 )
153169}
154170
171+ fun getImageUrl (
172+ user : User ,
173+ message : ChatMessage
174+ ): String? {
175+ if (message.messageParameters != null && message.messageParameters!! .size > 0 ) {
176+ for ((_, individualHashMap) in message.messageParameters!! ) {
177+ if (isHashMapEntryEqualTo(individualHashMap, " type" , " file" )) {
178+ if (! message.isVoiceMessage) {
179+ if (user != null && user!! .baseUrl != null ) {
180+ return ApiUtils .getUrlForFilePreviewWithFileId(
181+ user!! .baseUrl!! ,
182+ individualHashMap[" id" ]!! ,
183+ sharedApplication!! .resources.getDimensionPixelSize(R .dimen.maximum_file_preview_size)
184+ )
185+ }
186+ }
187+ }
188+ }
189+ }
190+ return null
191+ }
192+
193+ fun getMimetype (
194+ message : ChatMessage
195+ ): String? {
196+ if (message.messageParameters != null && message.messageParameters!! .size > 0 ) {
197+ for ((_, individualHashMap) in message.messageParameters!! ) {
198+ if (isHashMapEntryEqualTo(individualHashMap, " type" , " file" )) {
199+ return individualHashMap[" mimetype" ]
200+ }
201+ }
202+ }
203+ return null
204+ }
205+
206+ private fun isHashMapEntryEqualTo (map : HashMap <String ?, String ?>, key : String , searchTerm : String ): Boolean =
207+ map != null && MessageDigest .isEqual(map[key]!! .toByteArray(), searchTerm.toByteArray())
208+
209+
155210fun getGeolocationContent (message : ChatMessage ): MessageTypeContent .Geolocation ? {
156211 if (message.messageParameters != null && message.messageParameters!! .isNotEmpty()) {
157212 for (key in message.messageParameters!! .keys) {
0 commit comments