Display video/image compression progress
This commit is contained in:
parent
765380ab95
commit
e510de1ccc
|
@ -31,6 +31,8 @@ interface ContentUploadStateTracker {
|
|||
sealed class State {
|
||||
object Idle : State()
|
||||
object EncryptingThumbnail : State()
|
||||
object CompressingImage : State()
|
||||
data class CompressingVideo(val percent: Float) : State()
|
||||
data class UploadingThumbnail(val current: Long, val total: Long) : State()
|
||||
data class Encrypting(val current: Long, val total: Long) : State()
|
||||
data class Uploading(val current: Long, val total: Long) : State()
|
||||
|
|
|
@ -78,6 +78,16 @@ internal class DefaultContentUploadStateTracker @Inject constructor() : ContentU
|
|||
updateState(key, progressData)
|
||||
}
|
||||
|
||||
internal fun setCompressingImage(key: String) {
|
||||
val progressData = ContentUploadStateTracker.State.CompressingImage
|
||||
updateState(key, progressData)
|
||||
}
|
||||
|
||||
internal fun setCompressingVideo(key: String, percent: Float) {
|
||||
val progressData = ContentUploadStateTracker.State.CompressingVideo(percent)
|
||||
updateState(key, progressData)
|
||||
}
|
||||
|
||||
internal fun setProgress(key: String, current: Long, total: Long) {
|
||||
val progressData = ContentUploadStateTracker.State.Uploading(current, total)
|
||||
updateState(key, progressData)
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.graphics.BitmapFactory
|
|||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
|
||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
|
@ -156,6 +157,8 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
|
|||
// Do not compress gif
|
||||
&& attachment.mimeType != MimeTypes.Gif
|
||||
&& params.compressBeforeSending) {
|
||||
notifyTracker(params) { contentUploadStateTracker.setCompressingImage(it) }
|
||||
|
||||
fileToUpload = imageCompressor.compress(workingFile, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE)
|
||||
.also { compressedFile ->
|
||||
// Get new Bitmap size
|
||||
|
@ -174,7 +177,11 @@ internal class UploadContentWorker(val context: Context, params: WorkerParameter
|
|||
// Do not compress gif
|
||||
&& attachment.mimeType != MimeTypes.Gif
|
||||
&& params.compressBeforeSending) {
|
||||
fileToUpload = videoCompressor.compress(workingFile)
|
||||
fileToUpload = videoCompressor.compress(workingFile, object: ProgressListener {
|
||||
override fun onProgress(progress: Int, total: Int) {
|
||||
notifyTracker(params) { contentUploadStateTracker.setCompressingVideo(it, progress.toFloat()) }
|
||||
}
|
||||
})
|
||||
.also { compressedFile ->
|
||||
// Get new Video file size. For now video dimensions are not updated
|
||||
newAttachmentAttributes = newAttachmentAttributes.copy(newFileSize = compressedFile.length())
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.abedelazizshe.lightcompressorlibrary.VideoQuality
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
|
@ -30,6 +31,7 @@ import javax.inject.Inject
|
|||
|
||||
internal class VideoCompressor @Inject constructor(private val context: Context) {
|
||||
suspend fun compress(videoFile: File,
|
||||
progressListener: ProgressListener?,
|
||||
quality: VideoQuality = VideoQuality.MEDIUM,
|
||||
isMinBitRateEnabled: Boolean = false,
|
||||
keepOriginalResolution: Boolean = true): File {
|
||||
|
@ -46,14 +48,17 @@ internal class VideoCompressor @Inject constructor(private val context: Context)
|
|||
listener = object : CompressionListener {
|
||||
override fun onProgress(percent: Float) {
|
||||
Timber.d("Compressing: $percent%")
|
||||
progressListener?.onProgress(percent.toInt(), 100)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
Timber.d("Compressing: start")
|
||||
progressListener?.onProgress(0, 100)
|
||||
}
|
||||
|
||||
override fun onSuccess() {
|
||||
Timber.d("Compressing: success")
|
||||
progressListener?.onProgress(100, 100)
|
||||
job.complete()
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import im.vector.app.R
|
|||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import im.vector.app.core.di.ScreenScope
|
||||
import im.vector.app.core.error.ErrorFormatter
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.utils.TextUtils
|
||||
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
|
||||
import org.matrix.android.sdk.api.session.content.ContentUploadStateTracker
|
||||
|
@ -70,6 +71,9 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup,
|
|||
private val messageColorProvider: MessageColorProvider,
|
||||
private val errorFormatter: ErrorFormatter) : ContentUploadStateTracker.UpdateListener {
|
||||
|
||||
private val progressBar: ProgressBar = progressLayout.findViewById(R.id.mediaProgressBar)
|
||||
private val progressTextView: TextView = progressLayout.findViewById(R.id.mediaProgressTextView)
|
||||
|
||||
override fun onUpdate(state: ContentUploadStateTracker.State) {
|
||||
when (state) {
|
||||
is ContentUploadStateTracker.State.Idle -> handleIdle()
|
||||
|
@ -79,19 +83,19 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup,
|
|||
is ContentUploadStateTracker.State.Uploading -> handleProgress(state)
|
||||
is ContentUploadStateTracker.State.Failure -> handleFailure(/*state*/)
|
||||
is ContentUploadStateTracker.State.Success -> handleSuccess()
|
||||
}
|
||||
is ContentUploadStateTracker.State.CompressingImage -> handleCompressingImage()
|
||||
is ContentUploadStateTracker.State.CompressingVideo -> handleCompressingVideo(state)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleIdle() {
|
||||
if (isLocalFile) {
|
||||
progressLayout.isVisible = true
|
||||
val progressBar = progressLayout.findViewById<ProgressBar>(R.id.mediaProgressBar)
|
||||
val progressTextView = progressLayout.findViewById<TextView>(R.id.mediaProgressTextView)
|
||||
progressBar?.isVisible = true
|
||||
progressBar?.isIndeterminate = true
|
||||
progressBar?.progress = 0
|
||||
progressTextView?.text = progressLayout.context.getString(R.string.send_file_step_idle)
|
||||
progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.UNSENT))
|
||||
progressBar.isVisible = true
|
||||
progressBar.isIndeterminate = true
|
||||
progressBar.progress = 0
|
||||
progressTextView.text = progressLayout.context.getString(R.string.send_file_step_idle)
|
||||
progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.UNSENT))
|
||||
} else {
|
||||
progressLayout.isVisible = false
|
||||
}
|
||||
|
@ -113,38 +117,51 @@ private class ContentMediaProgressUpdater(private val progressLayout: ViewGroup,
|
|||
doHandleProgress(R.string.send_file_step_sending_file, state.current, state.total)
|
||||
}
|
||||
|
||||
private fun handleCompressingImage() {
|
||||
progressLayout.visibility = View.VISIBLE
|
||||
progressBar.isVisible = true
|
||||
progressBar.isIndeterminate = true
|
||||
progressTextView.isVisible = true
|
||||
progressTextView.text = progressLayout.context.getString(R.string.send_file_step_compressing_image)
|
||||
progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING))
|
||||
}
|
||||
|
||||
private fun handleCompressingVideo(state: ContentUploadStateTracker.State.CompressingVideo) {
|
||||
progressLayout.visibility = View.VISIBLE
|
||||
progressBar.isVisible = true
|
||||
progressBar.isIndeterminate = false
|
||||
progressBar.progress = state.percent.toInt()
|
||||
progressTextView.isVisible = true
|
||||
progressTextView.text = progressLayout.context.getString(R.string.send_file_step_compressing_video, state.percent.toInt())
|
||||
progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING))
|
||||
}
|
||||
|
||||
private fun doHandleEncrypting(resId: Int, current: Long, total: Long) {
|
||||
progressLayout.visibility = View.VISIBLE
|
||||
val percent = if (total > 0) (100L * (current.toFloat() / total.toFloat())) else 0f
|
||||
val progressBar = progressLayout.findViewById<ProgressBar>(R.id.mediaProgressBar)
|
||||
val progressTextView = progressLayout.findViewById<TextView>(R.id.mediaProgressTextView)
|
||||
progressBar?.isIndeterminate = false
|
||||
progressBar?.progress = percent.toInt()
|
||||
progressBar.isIndeterminate = false
|
||||
progressBar.progress = percent.toInt()
|
||||
progressTextView.isVisible = true
|
||||
progressTextView?.text = progressLayout.context.getString(resId)
|
||||
progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.ENCRYPTING))
|
||||
progressTextView.text = progressLayout.context.getString(resId)
|
||||
progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.ENCRYPTING))
|
||||
}
|
||||
|
||||
private fun doHandleProgress(resId: Int, current: Long, total: Long) {
|
||||
progressLayout.visibility = View.VISIBLE
|
||||
val percent = 100L * (current.toFloat() / total.toFloat())
|
||||
val progressBar = progressLayout.findViewById<ProgressBar>(R.id.mediaProgressBar)
|
||||
val progressTextView = progressLayout.findViewById<TextView>(R.id.mediaProgressTextView)
|
||||
progressBar?.isVisible = true
|
||||
progressBar?.isIndeterminate = false
|
||||
progressBar?.progress = percent.toInt()
|
||||
progressBar.isVisible = true
|
||||
progressBar.isIndeterminate = false
|
||||
progressBar.progress = percent.toInt()
|
||||
progressTextView.isVisible = true
|
||||
progressTextView?.text = progressLayout.context.getString(resId,
|
||||
progressTextView.text = progressLayout.context.getString(resId,
|
||||
TextUtils.formatFileSize(progressLayout.context, current, true),
|
||||
TextUtils.formatFileSize(progressLayout.context, total, true))
|
||||
progressTextView?.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING))
|
||||
progressTextView.setTextColor(messageColorProvider.getMessageTextColor(SendState.SENDING))
|
||||
}
|
||||
|
||||
private fun handleFailure(/*state: ContentUploadStateTracker.State.Failure*/) {
|
||||
progressLayout.visibility = View.VISIBLE
|
||||
val progressBar = progressLayout.findViewById<ProgressBar>(R.id.mediaProgressBar)
|
||||
val progressTextView = progressLayout.findViewById<TextView>(R.id.mediaProgressTextView)
|
||||
progressBar?.isVisible = false
|
||||
progressBar.isVisible = false
|
||||
// Do not show the message it's too technical for users, and unfortunate when upload is cancelled
|
||||
// in the middle by turning airplane mode for example
|
||||
progressTextView.isVisible = false
|
||||
|
|
|
@ -2174,6 +2174,8 @@
|
|||
<string name="send_file_step_sending_thumbnail">Sending thumbnail (%1$s / %2$s)</string>
|
||||
<string name="send_file_step_encrypting_file">Encrypting file…</string>
|
||||
<string name="send_file_step_sending_file">Sending file (%1$s / %2$s)</string>
|
||||
<string name="send_file_step_compressing_image">Compressing image…</string>
|
||||
<string name="send_file_step_compressing_video">Compressing video %d%%</string>
|
||||
|
||||
<string name="downloading_file">Downloading file %1$s…</string>
|
||||
<string name="downloaded_file">File %1$s has been downloaded!</string>
|
||||
|
|
Loading…
Reference in New Issue