diff --git a/app/src/main/java/com/nextcloud/talk/chat/ui/model/ChatMessageUi.kt b/app/src/main/java/com/nextcloud/talk/chat/ui/model/ChatMessageUi.kt index 48c29624ffa..f6fddb14fc0 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ui/model/ChatMessageUi.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ui/model/ChatMessageUi.kt @@ -7,6 +7,7 @@ package com.nextcloud.talk.chat.ui.model +import android.provider.Settings import androidx.compose.runtime.Stable import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication @@ -15,7 +16,9 @@ import com.nextcloud.talk.data.database.model.SendStatus import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.ui.PlaybackSpeed import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.CapabilitiesUtil import com.nextcloud.talk.utils.DrawableUtils +import com.nextcloud.talk.utils.MimetypeUtils import java.time.LocalDate // immutable class for chat message UI. only val, no vars! @@ -54,7 +57,12 @@ sealed interface MessageTypeContent { data class LinkPreview(val url: String) : MessageTypeContent - data class Media(val previewUrl: String?, val drawableResourceId: Int) : MessageTypeContent + data class Media( + val previewUrl: String?, + val drawableResourceId: Int, + val mimeType: String, + val animateGif: Boolean = false + ) : MessageTypeContent data class Geolocation(val id: String, val name: String, val lat: Double, val lon: Double) : MessageTypeContent @@ -203,16 +211,52 @@ fun getMessageTypeContent(user: User, message: ChatMessage): MessageTypeContent? } fun getMediaContent(user: User, message: ChatMessage): MessageTypeContent.Media { - val previewUrl = getPreviewImageUrl(user, message) val mimetype = message.fileParameters.mimetype val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype) + val animateGif = shouldAnimateGif(user, message, mimetype) + val previewUrl = if (animateGif) { + ApiUtils.getUrlForFileDownload( + user.baseUrl!!, + user.userId!!, + message.fileParameters.path + ) + } else { + getPreviewImageUrl(user, message) + } + return MessageTypeContent.Media( - previewUrl, - drawableResourceId + previewUrl = previewUrl, + drawableResourceId = drawableResourceId, + mimeType = mimetype, + animateGif = animateGif ) } +private fun shouldAnimateGif(user: User, message: ChatMessage, mimetype: String): Boolean { + val fileSize = message.fileParameters.size + val spreedCapabilities = user.capabilities?.spreedCapability + return MimetypeUtils.isGif(mimetype) && + fileSize != null && + message.fileParameters.path.isNotEmpty() && + spreedCapabilities != null && + fileSize <= CapabilitiesUtil.getMaxGifSize(spreedCapabilities) && + !isReduceAnimationsEnabled() +} + +/** + * Returns true if the user has the accessibility option + * for Remove/Reduce animations turned on + */ +private fun isReduceAnimationsEnabled(): Boolean { + val context = sharedApplication ?: return false + return Settings.Global.getFloat( + context.contentResolver, + Settings.Global.ANIMATOR_DURATION_SCALE, + 1f + ) == 0f +} + fun getPreviewImageUrl(user: User, message: ChatMessage): String? { if (message.fileParameters.previewAvailable) { return ApiUtils.getUrlForFilePreviewWithFileId( diff --git a/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageView.kt b/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageView.kt index e766b6ee174..b2fb5aed52e 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageView.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageView.kt @@ -234,7 +234,8 @@ private fun ChatMessageViewMediaPreview() { val uiMessage = createBaseMessage( MessageTypeContent.Media( previewUrl = null, - drawableResourceId = R.drawable.ic_mimetype_image + drawableResourceId = R.drawable.ic_mimetype_image, + mimeType = "" ) ) ChatMessageView(message = uiMessage) @@ -248,7 +249,8 @@ private fun ChatMessageViewMediaPreviewWithoutCaption() { val uiMessage = createBaseMessageWithoutCaption( MessageTypeContent.Media( previewUrl = null, - drawableResourceId = R.drawable.ic_mimetype_image + drawableResourceId = R.drawable.ic_mimetype_image, + mimeType = "" ) ) ChatMessageView(message = uiMessage) diff --git a/app/src/main/java/com/nextcloud/talk/ui/chat/MediaMessage.kt b/app/src/main/java/com/nextcloud/talk/ui/chat/MediaMessage.kt index d0964326cab..3aa80455021 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/chat/MediaMessage.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/chat/MediaMessage.kt @@ -31,6 +31,7 @@ import com.nextcloud.talk.R import com.nextcloud.talk.chat.ui.model.ChatMessageUi import com.nextcloud.talk.chat.ui.model.MessageTypeContent import com.nextcloud.talk.contacts.load +import com.nextcloud.talk.utils.MimetypeUtils private const val FILE_PLACEHOLDER_MESSAGE = "{file}" @@ -78,15 +79,18 @@ fun MediaMessage( Column { val context = LocalContext.current val resourceName = context.resources.getResourceEntryName(typeContent.drawableResourceId) + val isGif = MimetypeUtils.isGif(typeContent.mimeType) val showPlayButton = !typeContent.previewUrl.isNullOrEmpty() && - (resourceName.contains("video") || resourceName.contains("audio")) + (resourceName.contains("video") || resourceName.contains("audio") || + (isGif && !typeContent.animateGif)) Box(modifier = Modifier.fillMaxWidth()) { val loadedImage = remember(typeContent.previewUrl) { load( imageUri = typeContent.previewUrl, context = context, - errorPlaceholderImage = typeContent.drawableResourceId + errorPlaceholderImage = typeContent.drawableResourceId, + animated = typeContent.animateGif ) }