Implement Mode.ANIMATED_THUMBNAIL used for autoplaying animated images

This patch introduces a new `ImageContentRenderer` mode used for
autoplaying animated images. The mode shares url resolving semantics
with `FULL_SIZE` and `STICKER`, as such not just fetching thumbnail data
but shares sizing semantics with `THUMBNAIL` (scaling by image height).

This change fixes animated images not playing in cases in which only a
static thumbnail would be loaded.

This new mode will only be chosen if the message content is actually a
playable image, as such limiting bandwith usage to the required amount
by avoiding to load normal images fully (still fetching animated images
will increase bandwith usage as a whole of course).

Signed-off-by: networkException <git@nwex.de>
This commit is contained in:
networkException 2022-05-31 21:53:47 +02:00
parent cc49e96d36
commit dccc64384c
No known key found for this signature in database
GPG Key ID: C1F2658DC370C8FC
2 changed files with 11 additions and 1 deletions

View File

@ -453,12 +453,15 @@ class MessageItemFactory @Inject constructor(
maxWidth = maxWidth, maxWidth = maxWidth,
allowNonMxcUrls = informationData.sendState.isSending() allowNonMxcUrls = informationData.sendState.isSending()
) )
val playable = messageContent.mimeType == MimeTypes.Gif
return MessageImageVideoItem_() return MessageImageVideoItem_()
.attributes(attributes) .attributes(attributes)
.leftGuideline(avatarSizeProvider.leftGuideline) .leftGuideline(avatarSizeProvider.leftGuideline)
.imageContentRenderer(imageContentRenderer) .imageContentRenderer(imageContentRenderer)
.contentUploadStateTrackerBinder(contentUploadStateTrackerBinder) .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
.playable(messageContent.mimeType == MimeTypes.Gif) .playable(playable)
.highlighted(highlight) .highlighted(highlight)
.mediaData(data) .mediaData(data)
.apply { .apply {
@ -472,6 +475,10 @@ class MessageItemFactory @Inject constructor(
callback?.onImageMessageClicked(messageContent, data, view, emptyList()) callback?.onImageMessageClicked(messageContent, data, view, emptyList())
} }
} }
}.apply {
if (playable && vectorPreferences.autoplayAnimatedImages()) {
mode(ImageContentRenderer.Mode.ANIMATED_THUMBNAIL)
}
} }
} }

View File

@ -85,6 +85,7 @@ class ImageContentRenderer @Inject constructor(
enum class Mode { enum class Mode {
FULL_SIZE, FULL_SIZE,
ANIMATED_THUMBNAIL,
THUMBNAIL, THUMBNAIL,
STICKER STICKER
} }
@ -231,6 +232,7 @@ class ImageContentRenderer @Inject constructor(
val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver() val contentUrlResolver = activeSessionHolder.getActiveSession().contentUrlResolver()
val resolvedUrl = when (mode) { val resolvedUrl = when (mode) {
Mode.FULL_SIZE, Mode.FULL_SIZE,
Mode.ANIMATED_THUMBNAIL,
Mode.STICKER -> resolveUrl(data) Mode.STICKER -> resolveUrl(data)
Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, size.width, size.height, ContentUrlResolver.ThumbnailMethod.SCALE) Mode.THUMBNAIL -> contentUrlResolver.resolveThumbnail(data.url, size.width, size.height, ContentUrlResolver.ThumbnailMethod.SCALE)
} }
@ -269,6 +271,7 @@ class ImageContentRenderer @Inject constructor(
finalHeight = height finalHeight = height
finalWidth = width finalWidth = width
} }
Mode.ANIMATED_THUMBNAIL,
Mode.THUMBNAIL -> { Mode.THUMBNAIL -> {
finalHeight = min(maxImageWidth * height / width, maxImageHeight) finalHeight = min(maxImageWidth * height / width, maxImageHeight)
finalWidth = finalHeight * width / height finalWidth = finalHeight * width / height