Skip to content

Commit 8c3f569

Browse files
committed
Auto play GIF media.
Respect Remove/Reduce animations accessibility setting for GIF playback. Signed-off-by: Jens Zalzala <jens@shakingearthdigital.com>
1 parent 5cbb5be commit 8c3f569

3 files changed

Lines changed: 58 additions & 8 deletions

File tree

app/src/main/java/com/nextcloud/talk/chat/ui/model/ChatMessageUi.kt

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77

88
package com.nextcloud.talk.chat.ui.model
99

10+
import android.provider.Settings
1011
import androidx.compose.runtime.Stable
1112
import com.nextcloud.talk.R
1213
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
1314
import com.nextcloud.talk.chat.data.model.ChatMessage
1415
import com.nextcloud.talk.data.database.model.SendStatus
1516
import com.nextcloud.talk.data.user.model.User
1617
import com.nextcloud.talk.utils.ApiUtils
18+
import com.nextcloud.talk.utils.CapabilitiesUtil
1719
import com.nextcloud.talk.utils.DrawableUtils
20+
import com.nextcloud.talk.utils.MimetypeUtils
1821
import com.nextcloud.talk.ui.PlaybackSpeed
1922
import java.time.LocalDate
2023

@@ -54,7 +57,12 @@ sealed interface MessageTypeContent {
5457

5558
data class LinkPreview(val url: String) : MessageTypeContent
5659

57-
data class Media(val previewUrl: String?, val drawableResourceId: Int) : MessageTypeContent
60+
data class Media(
61+
val previewUrl: String?,
62+
val drawableResourceId: Int,
63+
val mimeType: String,
64+
val animateGif: Boolean = false
65+
) : MessageTypeContent
5866

5967
data class Geolocation(val id: String, val name: String, val lat: Double, val lon: Double) : MessageTypeContent
6068

@@ -203,16 +211,52 @@ fun getMessageTypeContent(user: User, message: ChatMessage): MessageTypeContent?
203211
}
204212

205213
fun getMediaContent(user: User, message: ChatMessage): MessageTypeContent.Media {
206-
val previewUrl = getPreviewImageUrl(user, message)
207214
val mimetype = message.fileParameters.mimetype
208215
val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype)
209216

217+
val animateGif = shouldAnimateGif(user, message, mimetype)
218+
val previewUrl = if (animateGif) {
219+
ApiUtils.getUrlForFileDownload(
220+
user.baseUrl!!,
221+
user.userId!!,
222+
message.fileParameters.path
223+
)
224+
} else {
225+
getPreviewImageUrl(user, message)
226+
}
227+
210228
return MessageTypeContent.Media(
211-
previewUrl,
212-
drawableResourceId
229+
previewUrl = previewUrl,
230+
drawableResourceId = drawableResourceId,
231+
mimeType = mimetype,
232+
animateGif = animateGif
213233
)
214234
}
215235

236+
private fun shouldAnimateGif(user: User, message: ChatMessage, mimetype: String): Boolean {
237+
val fileSize = message.fileParameters.size
238+
val spreedCapabilities = user.capabilities?.spreedCapability
239+
return MimetypeUtils.isGif(mimetype) &&
240+
fileSize != null &&
241+
message.fileParameters.path.isNotEmpty() &&
242+
spreedCapabilities != null &&
243+
fileSize <= CapabilitiesUtil.getMaxGifSize(spreedCapabilities) &&
244+
!isReduceAnimationsEnabled()
245+
}
246+
247+
/**
248+
* Returns true if the user has the accessibility option
249+
* for Remove/Reduce animations turned on
250+
*/
251+
private fun isReduceAnimationsEnabled(): Boolean {
252+
val context = sharedApplication ?: return false
253+
return Settings.Global.getFloat(
254+
context.contentResolver,
255+
Settings.Global.ANIMATOR_DURATION_SCALE,
256+
1f
257+
) == 0f
258+
}
259+
216260
fun getPreviewImageUrl(user: User, message: ChatMessage): String? {
217261
if (message.fileParameters.previewAvailable) {
218262
return ApiUtils.getUrlForFilePreviewWithFileId(

app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageView.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ private fun ChatMessageViewMediaPreview() {
234234
val uiMessage = createBaseMessage(
235235
MessageTypeContent.Media(
236236
previewUrl = null,
237-
drawableResourceId = R.drawable.ic_mimetype_image
237+
drawableResourceId = R.drawable.ic_mimetype_image,
238+
mimeType = ""
238239
)
239240
)
240241
ChatMessageView(message = uiMessage)
@@ -248,7 +249,8 @@ private fun ChatMessageViewMediaPreviewWithoutCaption() {
248249
val uiMessage = createBaseMessageWithoutCaption(
249250
MessageTypeContent.Media(
250251
previewUrl = null,
251-
drawableResourceId = R.drawable.ic_mimetype_image
252+
drawableResourceId = R.drawable.ic_mimetype_image,
253+
mimeType = ""
252254
)
253255
)
254256
ChatMessageView(message = uiMessage)

app/src/main/java/com/nextcloud/talk/ui/chat/MediaMessage.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.nextcloud.talk.R
3131
import com.nextcloud.talk.chat.ui.model.ChatMessageUi
3232
import com.nextcloud.talk.chat.ui.model.MessageTypeContent
3333
import com.nextcloud.talk.contacts.load
34+
import com.nextcloud.talk.utils.MimetypeUtils
3435

3536
private const val FILE_PLACEHOLDER_MESSAGE = "{file}"
3637

@@ -78,15 +79,18 @@ fun MediaMessage(
7879
Column {
7980
val context = LocalContext.current
8081
val resourceName = context.resources.getResourceEntryName(typeContent.drawableResourceId)
82+
val isGif = MimetypeUtils.isGif(typeContent.mimeType)
8183
val showPlayButton = !typeContent.previewUrl.isNullOrEmpty() &&
82-
(resourceName.contains("video") || resourceName.contains("audio"))
84+
(resourceName.contains("video") || resourceName.contains("audio") ||
85+
(isGif && !typeContent.animateGif))
8386

8487
Box(modifier = Modifier.fillMaxWidth()) {
8588
val loadedImage = remember(typeContent.previewUrl) {
8689
load(
8790
imageUri = typeContent.previewUrl,
8891
context = context,
89-
errorPlaceholderImage = typeContent.drawableResourceId
92+
errorPlaceholderImage = typeContent.drawableResourceId,
93+
animated = typeContent.animateGif
9094
)
9195
}
9296

0 commit comments

Comments
 (0)