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:
parent
ffe183c952
commit
a170d80cb3
174 changed files with 2152 additions and 340 deletions
|
|
@ -14,6 +14,8 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.features.messages.api)
|
||||
api(projects.features.messages.impl)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.mediaviewer.api)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.messages.test.attachments.video
|
||||
|
||||
import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorPresenter
|
||||
import io.element.android.features.messages.impl.attachments.video.MediaOptimizationSelectorState
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.mediaviewer.api.local.LocalMedia
|
||||
|
||||
class FakeMediaOptimizationSelectorPresenterFactory(
|
||||
private val fakePresenter: MediaOptimizationSelectorPresenter = MediaOptimizationSelectorPresenter {
|
||||
MediaOptimizationSelectorState(
|
||||
maxUploadSize = AsyncData.Uninitialized,
|
||||
videoSizeEstimations = AsyncData.Uninitialized,
|
||||
isImageOptimizationEnabled = null,
|
||||
selectedVideoPreset = null,
|
||||
displayMediaSelectorViews = null,
|
||||
displayVideoPresetSelectorDialog = false,
|
||||
eventSink = {},
|
||||
)
|
||||
}
|
||||
) : MediaOptimizationSelectorPresenter.Factory {
|
||||
override fun create(localMedia: LocalMedia): MediaOptimizationSelectorPresenter {
|
||||
return fakePresenter
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.messages.test.attachments.video
|
||||
|
||||
import android.net.Uri
|
||||
import android.util.Size
|
||||
import io.element.android.features.messages.impl.attachments.video.VideoMetadataExtractor
|
||||
|
||||
class FakeVideoMetadataExtractor(
|
||||
private val sizeResult: Result<Size> = Result.success(Size(1, 1)),
|
||||
private val duration: Result<Long> = Result.success(1L),
|
||||
) : VideoMetadataExtractor {
|
||||
override fun getSize(): Result<Size> = sizeResult
|
||||
|
||||
override fun getDuration(): Result<Long> = duration
|
||||
|
||||
override fun close() = Unit
|
||||
}
|
||||
|
||||
class FakeVideoMetadataExtractorFactory(
|
||||
private val fakeVideoMetadataExtractor: FakeVideoMetadataExtractor = FakeVideoMetadataExtractor(),
|
||||
) : VideoMetadataExtractor.Factory {
|
||||
override fun create(uri: Uri): VideoMetadataExtractor {
|
||||
return fakeVideoMetadataExtractor
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue