Add media file limit size warning and media quality selection (#5131)

* Add `VideoCompressorPreset` enum

This represents the different compression presets used for processing videos before uploading them

* Add `VideoCompressorHelper` util class to calculate the scaled output size of the video given an input size and its optimal bitrate

Also add `MediaOptimizationConfig` which will be used to decide how to apply compression in `MediaPreProcessor`

* Add `RustMatrixClient.getMaxFileUploadSize()` function and `MaxUploadSizeProvider` so we can import only this functionality into other components

* Try preloading the max file upload size the first time we get network connectivity - it's a best effort

This should help ensure we'll have this value available later, even if we still need to load it asynchronously.

* Split the `compressMedia` preference into `compressImages` and `compressMediaPreset`

* Modify the media processing parts to use the new classes and utils

* Add `MediaOptimizationSelectorPresenter`, which will retrieve the compression values and the max file upload size, also estimating the compressed video file sizes if needed.

* Add a feature flag to allow selecting the media upload quality per upload

* Integrate the previous changes with the attachments preview screen

Add strings from localazy too.

* Adapt the rest of the app calls to upload media to using the media optimization configs

* Allow modifying the default compression values in advanced settings, based on the feature flag value

* Pass the `fileSize` in `MediaUploadInfo` too, to be able to check it against the `maxUploadSize`

* Update screenshots

---------

Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa 2025-08-11 17:22:46 +02:00 committed by GitHub
parent ffe183c952
commit a170d80cb3
174 changed files with 2152 additions and 340 deletions

View file

@ -46,6 +46,7 @@ class DefaultMediaViewerEntryPoint @Inject constructor() : MediaViewerEntryPoint
eventId = null,
mediaInfo = MediaInfo(
filename = filename,
fileSize = null,
caption = null,
mimeType = mimeType,
formattedFileSize = "",

View file

@ -92,6 +92,7 @@ class EventItemFactory @Inject constructor(
eventId = currentTimelineItem.eventId,
mediaInfo = MediaInfo(
filename = type.filename,
fileSize = type.info?.size,
caption = type.caption,
mimeType = type.info?.mimetype.orEmpty(),
formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(),
@ -111,6 +112,7 @@ class EventItemFactory @Inject constructor(
eventId = currentTimelineItem.eventId,
mediaInfo = MediaInfo(
filename = type.filename,
fileSize = type.info?.size,
caption = type.caption,
mimeType = type.info?.mimetype.orEmpty(),
formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(),
@ -131,6 +133,7 @@ class EventItemFactory @Inject constructor(
eventId = currentTimelineItem.eventId,
mediaInfo = MediaInfo(
filename = type.filename,
fileSize = type.info?.size,
caption = type.caption,
mimeType = type.info?.mimetype.orEmpty(),
formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(),
@ -151,6 +154,7 @@ class EventItemFactory @Inject constructor(
eventId = currentTimelineItem.eventId,
mediaInfo = MediaInfo(
filename = type.filename,
fileSize = type.info?.size,
caption = type.caption,
mimeType = type.info?.mimetype.orEmpty(),
formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(),
@ -171,6 +175,7 @@ class EventItemFactory @Inject constructor(
eventId = currentTimelineItem.eventId,
mediaInfo = MediaInfo(
filename = type.filename,
fileSize = type.info?.size,
caption = type.caption,
mimeType = type.info?.mimetype.orEmpty(),
formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(),
@ -191,6 +196,7 @@ class EventItemFactory @Inject constructor(
eventId = currentTimelineItem.eventId,
mediaInfo = MediaInfo(
filename = type.filename,
fileSize = type.info?.size,
caption = type.caption,
mimeType = type.info?.mimetype.orEmpty(),
formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(),

View file

@ -87,15 +87,17 @@ class AndroidLocalMediaFactory @Inject constructor(
): LocalMedia {
val resolvedMimeType = mimeType ?: context.getMimeType(uri) ?: MimeTypes.OctetStream
val fileName = name ?: context.getFileName(uri) ?: ""
val fileSize = formattedFileSize ?: fileSizeFormatter.format(context.getFileSize(uri))
val fileSize = context.getFileSize(uri)
val calculatedFormattedFileSize = formattedFileSize ?: fileSizeFormatter.format(fileSize)
val fileExtension = fileExtensionExtractor.extractFromName(fileName)
return LocalMedia(
uri = uri,
info = MediaInfo(
mimeType = resolvedMimeType,
filename = fileName,
fileSize = fileSize,
caption = caption,
formattedFileSize = fileSize,
formattedFileSize = calculatedFormattedFileSize,
fileExtension = fileExtension,
senderId = senderId,
senderName = senderName,