From 2ec2c9b16f51ca2102c0992f7bf58894b9b90ec5 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 26 May 2023 11:29:49 +0200 Subject: [PATCH] Media: continue improving VideoView --- .../impl/media/local/LocalMediaView.kt | 12 +++-- .../media/local/exoplayer/ExoPlayerWrapper.kt | 49 +++++++++++++++++++ .../impl/media/viewer/MediaViewerView.kt | 48 ++++++++++-------- 3 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/exoplayer/ExoPlayerWrapper.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt index 8c94822947..3040f0bfbd 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt @@ -35,9 +35,9 @@ import androidx.media3.common.MediaItem import androidx.media3.common.MimeTypes import androidx.media3.common.Player import androidx.media3.common.util.UnstableApi -import androidx.media3.exoplayer.ExoPlayer import androidx.media3.ui.AspectRatioFrameLayout import androidx.media3.ui.PlayerView +import io.element.android.features.messages.impl.media.local.exoplayer.ExoPlayerWrapper import io.element.android.libraries.designsystem.R import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import me.saket.telephoto.zoomable.ZoomSpec @@ -114,8 +114,7 @@ fun MediaVideoView( } } val exoPlayer = remember { - ExoPlayer.Builder(context) - .build() + ExoPlayerWrapper.create(context) .apply { addListener(playerListener) this.prepare() @@ -133,6 +132,8 @@ fun MediaVideoView( factory = { PlayerView(context).apply { player = exoPlayer + setShowPreviousButton(false) + setShowNextButton(false) resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) controllerShowTimeoutMs = 3000 @@ -145,7 +146,10 @@ fun MediaVideoView( when (event) { Lifecycle.Event.ON_RESUME -> exoPlayer.play() Lifecycle.Event.ON_PAUSE -> exoPlayer.pause() - Lifecycle.Event.ON_DESTROY -> exoPlayer.release() + Lifecycle.Event.ON_DESTROY -> { + exoPlayer.release() + exoPlayer.removeListener(playerListener) + } else -> Unit } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/exoplayer/ExoPlayerWrapper.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/exoplayer/ExoPlayerWrapper.kt new file mode 100644 index 0000000000..a69db1ef2c --- /dev/null +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/exoplayer/ExoPlayerWrapper.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.features.messages.impl.media.local.exoplayer + +import android.content.Context +import androidx.media3.common.Player +import androidx.media3.common.util.UnstableApi +import androidx.media3.exoplayer.ExoPlayer + +/** + * Wrapper around ExoPlayer to disable some commands. + * Necessary to hide the settings wheels from the player. + */ +@UnstableApi +class ExoPlayerWrapper(private val exoPlayer: ExoPlayer) : ExoPlayer by exoPlayer { + + override fun isCommandAvailable(command: Int): Boolean { + return availableCommands.contains(command) + } + + override fun getAvailableCommands(): Player.Commands { + return exoPlayer.availableCommands + .buildUpon() + .remove(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS) + .build() + } + + companion object { + fun create(context: Context): ExoPlayer { + return ExoPlayerWrapper( + ExoPlayer.Builder(context).build() + ) + } + } +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt index b2957cac18..ae598688d1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt @@ -17,6 +17,9 @@ package io.element.android.features.messages.impl.media.viewer +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding @@ -116,28 +119,33 @@ private fun ThumbnailView( showThumbnail: Boolean, showProgress: Boolean, ) { - if (!showThumbnail) return - - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center + AnimatedVisibility( + visible = showThumbnail, + enter = fadeIn(), + exit = fadeOut() ) { - val mediaRequestData = MediaRequestData( - source = thumbnailSource, - kind = MediaRequestData.Kind.Content - ) - AsyncImage( + Box( modifier = Modifier.fillMaxSize(), - model = mediaRequestData, - contentScale = ContentScale.Fit, - contentDescription = null, - ) - if (showProgress) { - Box( - modifier = Modifier.roundedBackground(), - contentAlignment = Alignment.Center, - ) { - CircularProgressIndicator() + contentAlignment = Alignment.Center + ) { + val mediaRequestData = MediaRequestData( + source = thumbnailSource, + kind = MediaRequestData.Kind.Content + ) + AsyncImage( + modifier = Modifier.fillMaxSize(), + model = mediaRequestData, + alpha = 0.8f, + contentScale = ContentScale.Fit, + contentDescription = null, + ) + if (showProgress) { + Box( + modifier = Modifier.roundedBackground(), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator() + } } } }