From 5026a8e96766d942bf89d0f99dafa131b60d57df Mon Sep 17 00:00:00 2001 From: Thalys Matias Carrara Date: Wed, 7 Jun 2023 22:16:02 -0400 Subject: [PATCH] feat: use SeekHandler component Closes #15 --- .../components/EnhancedVideoPlayer.kt | 40 ++++++++++++++----- .../playerOverlay/PlayerControls.kt | 8 ++-- .../playerOverlay/PlayerControlsScaffold.kt | 4 +- .../components/playerOverlay/PlayerIcons.kt | 18 +++++++++ 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt index a57745ec..6802150c 100644 --- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt +++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/EnhancedVideoPlayer.kt @@ -2,10 +2,14 @@ package com.profusion.androidenhancedvideoplayer.components import android.content.res.Configuration import android.net.Uri +import androidx.compose.animation.* // ktlint-disable no-wildcard-imports +import androidx.compose.animation.core.* // ktlint-disable no-wildcard-imports +import androidx.compose.foundation.* // ktlint-disable no-wildcard-imports import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* // ktlint-disable no-wildcard-imports import androidx.compose.foundation.layout.Box +import androidx.compose.material.* // ktlint-disable no-wildcard-imports +import androidx.compose.runtime.* // ktlint-disable no-wildcard-imports import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue @@ -14,10 +18,13 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.* // ktlint-disable no-wildcard-imports +import androidx.compose.ui.graphics.* // ktlint-disable no-wildcard-imports import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag +import androidx.compose.ui.unit.* // ktlint-disable no-wildcard-imports import androidx.compose.ui.viewinterop.AndroidView import androidx.media3.common.MediaItem import androidx.media3.common.Player @@ -27,6 +34,7 @@ import androidx.media3.ui.AspectRatioFrameLayout import androidx.media3.ui.PlayerView import com.profusion.androidenhancedvideoplayer.components.playerOverlay.ControlsCustomization import com.profusion.androidenhancedvideoplayer.components.playerOverlay.PlayerControls +import com.profusion.androidenhancedvideoplayer.components.playerOverlay.SeekHandler import com.profusion.androidenhancedvideoplayer.components.playerOverlay.SettingsControlsCustomization import com.profusion.androidenhancedvideoplayer.utils.TimeoutEffect import com.profusion.androidenhancedvideoplayer.utils.fillMaxSizeOnLandscape @@ -37,6 +45,8 @@ import com.profusion.androidenhancedvideoplayer.utils.setStatusBarVisibility private const val MAIN_PACKAGE_PATH_PREFIX = "android.resource://" private const val CURRENT_TIME_TICK_IN_MS = 50L +private const val DEFAULT_SEEK_TIME_MS = 10 * 1000L // 10 seconds + @androidx.annotation.OptIn(UnstableApi::class) @Composable fun EnhancedVideoPlayer( @@ -48,7 +58,8 @@ fun EnhancedVideoPlayer( soundOff: Boolean = true, currentTimeTickInMs: Long = CURRENT_TIME_TICK_IN_MS, controlsCustomization: ControlsCustomization = ControlsCustomization(), - settingsControlsCustomization: SettingsControlsCustomization = SettingsControlsCustomization() + settingsControlsCustomization: SettingsControlsCustomization = SettingsControlsCustomization(), + transformSeekIncrementRatio: (tapCount: Int) -> Long = { it -> it * DEFAULT_SEEK_TIME_MS } ) { val context = LocalContext.current val mainPackagePath = "$MAIN_PACKAGE_PATH_PREFIX${context.packageName}/" @@ -64,7 +75,8 @@ fun EnhancedVideoPlayer( soundOff = soundOff, currentTimeTickInMs = currentTimeTickInMs, controlsCustomization = controlsCustomization, - settingsControlsCustomization = settingsControlsCustomization + settingsControlsCustomization = settingsControlsCustomization, + transformSeekIncrementRatio = { transformSeekIncrementRatio(it) } ) } @@ -79,6 +91,7 @@ fun EnhancedVideoPlayer( soundOff: Boolean = true, currentTimeTickInMs: Long = CURRENT_TIME_TICK_IN_MS, controlsCustomization: ControlsCustomization = ControlsCustomization(), + transformSeekIncrementRatio: (tapCount: Int) -> Long = { it -> it * DEFAULT_SEEK_TIME_MS }, settingsControlsCustomization: SettingsControlsCustomization = SettingsControlsCustomization() ) { val context = LocalContext.current @@ -95,7 +108,6 @@ fun EnhancedVideoPlayer( prepare() } } - var isPlaying by remember { mutableStateOf(exoPlayer.isPlaying) } var hasEnded by remember { mutableStateOf(exoPlayer.playbackState == ExoPlayer.STATE_ENDED) } var isControlsVisible by remember { mutableStateOf(false) } @@ -113,6 +125,10 @@ fun EnhancedVideoPlayer( ) } + fun setIsControlsVisible(value: Boolean) { + isControlsVisible = value + } + DisposableEffect(context) { val listener = object : Player.Listener { override fun onEvents(player: Player, events: Player.Events) { @@ -141,11 +157,6 @@ fun EnhancedVideoPlayer( Box( modifier = Modifier - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - onClick = { isControlsVisible = !isControlsVisible } - ) .background(Color.Black) .fillMaxSizeOnLandscape(orientation) .testTag("VideoPlayerParent"), @@ -166,6 +177,15 @@ fun EnhancedVideoPlayer( } } ) + + SeekHandler( + toggleIsControlsVisible = { isControlsVisible = !isControlsVisible }, + exoPlayer = exoPlayer, + controlsCustomization = controlsCustomization, + setIsControlsVisible = ::setIsControlsVisible, + transformSeekIncrementRatio = { transformSeekIncrementRatio(it) } + ) + PlayerControls( title = title, isVisible = isControlsVisible, diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt index 446cdce8..56ae75d8 100644 --- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt +++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControls.kt @@ -13,11 +13,14 @@ class ControlsCustomization( val nextIconContent: @Composable () -> Unit = { NextIcon() }, val fullScreenIconContent: @Composable () -> Unit = { FullScreenIcon() }, val exitFullScreenIconContent: @Composable () -> Unit = { ExitFullScreenIcon() }, - val settingsIconContent: @Composable () -> Unit = { SettingsIcon() } + val settingsIconContent: @Composable () -> Unit = { SettingsIcon() }, + val forwardIconContent: @Composable (modifier: Modifier) -> Unit = { ForwardIcon(it) }, + val rewindIconContent: @Composable (modifier: Modifier) -> Unit = { RewindIcon(it) } ) @Composable fun PlayerControls( + modifier: Modifier = Modifier, title: String? = null, isVisible: Boolean, isPlaying: Boolean, @@ -33,8 +36,7 @@ fun PlayerControls( onSpeedSelected: (Float) -> Unit, onSeekBarValueChange: (Long) -> Unit, customization: ControlsCustomization, - settingsControlsCustomization: SettingsControlsCustomization, - modifier: Modifier = Modifier + settingsControlsCustomization: SettingsControlsCustomization ) { PlayerControlsScaffold( modifier = modifier.testTag("PlayerControlsParent"), diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControlsScaffold.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControlsScaffold.kt index 7b56cb77..9473c98f 100644 --- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControlsScaffold.kt +++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerControlsScaffold.kt @@ -10,7 +10,7 @@ import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color +import com.profusion.androidenhancedvideoplayer.styling.Colors @Composable fun PlayerControlsScaffold( @@ -25,7 +25,7 @@ fun PlayerControlsScaffold( enter = fadeIn(), exit = fadeOut(), modifier = modifier - .background(Color.Black.copy(alpha = 0.6f)) + .background(Colors.controlsShadow) ) { Column( modifier = Modifier.fillMaxSize(), diff --git a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerIcons.kt b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerIcons.kt index 758a83f0..3621b307 100644 --- a/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerIcons.kt +++ b/androidenhancedvideoplayer/src/main/java/com/profusion/androidenhancedvideoplayer/components/playerOverlay/PlayerIcons.kt @@ -95,3 +95,21 @@ fun CheckIcon(modifier: Modifier = Modifier) { modifier = modifier ) } + +@Composable +fun ForwardIcon(modifier: Modifier = Modifier) { + Image( + painter = painterResource(id = R.drawable.ic_forward), + contentDescription = stringResource(R.string.controls_forward_description), + modifier = modifier.testTag("ForwardIcon") + ) +} + +@Composable +fun RewindIcon(modifier: Modifier = Modifier) { + Image( + painter = painterResource(id = R.drawable.ic_rewind), + contentDescription = stringResource(R.string.controls_rewind_description), + modifier = modifier.testTag("RewindIcon") + ) +}