Skip to content

Commit

Permalink
refactor: some player ui adjustments
Browse files Browse the repository at this point in the history
make enter animation faster
make player controls buttons' clickable area larger
add shadow to the seek gesture indicator (for bright videos)
make controls fade after 4 seconds (was 3)
add gradients at the top and bottom (better than darkening the entire screen)
for the 5th or 6th time. fix crash caused by seekbar chapters not starting at 0

this should overall make using the player a smoother experience
  • Loading branch information
abdallahmehiz committed Sep 14, 2024
1 parent 1b6af37 commit ef408cb
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package live.mehiz.mpvkt.ui.player.controls

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
Expand Down Expand Up @@ -43,7 +44,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
Expand Down Expand Up @@ -103,14 +106,14 @@ fun PlayerControls(
resetControls,
) {
if (controlsShown && !paused && !isSeeking) {
delay(3_000)
delay(4_000)
viewModel.hideControls()
}
}
val transparentOverlay by animateColorAsState(
Color.Black.copy(if (controlsShown && !areControlsLocked) 0.5f else 0f),
animationSpec = tween(500),
label = "",
val transparentOverlay by animateFloatAsState(
if (controlsShown && !areControlsLocked) .9f else 0f,
animationSpec = playerControlsExitAnimationSpec(),
label = "controls_transparent_overlay",
)
GestureHandler()
CompositionLocalProvider(
Expand All @@ -124,7 +127,15 @@ fun PlayerControls(
ConstraintLayout(
modifier = modifier
.fillMaxSize()
.background(transparentOverlay)
.background(
Brush.verticalGradient(
Pair(0f, Color.Black),
Pair(.2f, Color.Transparent),
Pair(.7f, Color.Transparent),
Pair(1f, Color.Black),
),
alpha = transparentOverlay,
)
.padding(horizontal = MaterialTheme.spacing.medium),
) {
val (topLeftControls, topRightControls) = createRefs()
Expand All @@ -151,8 +162,12 @@ fun PlayerControls(
}
AnimatedVisibility(
isBrightnessSliderShown,
enter = slideInHorizontally(playControlsAnimationSpec()) { it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutHorizontally(playControlsAnimationSpec()) { it } + fadeOut(playControlsAnimationSpec()),
enter = slideInHorizontally(playerControlsEnterAnimationSpec()) { it } + fadeIn(
playerControlsEnterAnimationSpec(),
),
exit = slideOutHorizontally(playerControlsExitAnimationSpec()) { it } + fadeOut(
playerControlsExitAnimationSpec(),
),
modifier = Modifier.constrainAs(brightnessSlider) {
end.linkTo(parent.end, spacing.medium)
top.linkTo(parent.top)
Expand All @@ -162,8 +177,12 @@ fun PlayerControls(

AnimatedVisibility(
isVolumeSliderShown,
enter = slideInHorizontally(playControlsAnimationSpec()) { -it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutHorizontally(playControlsAnimationSpec()) { -it } + fadeOut(playControlsAnimationSpec()),
enter = slideInHorizontally(playerControlsEnterAnimationSpec()) { -it } + fadeIn(
playerControlsEnterAnimationSpec(),
),
exit = slideOutHorizontally(playerControlsExitAnimationSpec()) { -it } + fadeOut(
playerControlsExitAnimationSpec(),
),
modifier = Modifier.constrainAs(volumeSlider) {
start.linkTo(parent.start, spacing.medium)
top.linkTo(parent.top)
Expand All @@ -177,7 +196,7 @@ fun PlayerControls(
mpvVolume = mpvVolume,
range = 0..viewModel.maxVolume,
boostRange = if (boostCap > 0) 0..audioPreferences.volumeBoostCap.get() else null,
displayAsPercentage = displayVolumeAsPercentage
displayAsPercentage = displayVolumeAsPercentage,
)
}

Expand All @@ -192,8 +211,8 @@ fun PlayerControls(
}
AnimatedVisibility(
currentPlayerUpdate != PlayerUpdates.None,
enter = fadeIn(playControlsAnimationSpec()),
exit = fadeOut(playControlsAnimationSpec()),
enter = fadeIn(playerControlsEnterAnimationSpec()),
exit = fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(playerUpdates) {
linkTo(parent.start, parent.end)
linkTo(parent.top, parent.bottom, bias = 0.2f)
Expand Down Expand Up @@ -222,8 +241,8 @@ fun PlayerControls(
}
AnimatedVisibility(
visible = (controlsShown && !areControlsLocked || gestureSeekAmount != null) || isLoading,
enter = fadeIn(playControlsAnimationSpec()),
exit = fadeOut(playControlsAnimationSpec()),
enter = fadeIn(playerControlsEnterAnimationSpec()),
exit = fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(playerPauseButton) {
end.linkTo(parent.absoluteRight)
start.linkTo(parent.absoluteLeft)
Expand All @@ -243,7 +262,9 @@ fun PlayerControls(
Utils.prettyTime(abs(gestureSeekAmount!!.second)),
Utils.prettyTime(gestureSeekAmount!!.first + gestureSeekAmount!!.second),
),
style = MaterialTheme.typography.headlineMedium,
style = MaterialTheme.typography.headlineMedium.copy(
shadow = Shadow(Color.Black, blurRadius = 5f)
),
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
)
Expand All @@ -266,8 +287,10 @@ fun PlayerControls(
}
AnimatedVisibility(
visible = (controlsShown || seekBarShown) && !areControlsLocked,
enter = slideInVertically(playControlsAnimationSpec()) { it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutVertically(playControlsAnimationSpec()) { it } + fadeOut(playControlsAnimationSpec()),
enter = slideInVertically(playerControlsEnterAnimationSpec()) { it } +
fadeIn(playerControlsEnterAnimationSpec()),
exit = slideOutVertically(playerControlsExitAnimationSpec()) { it } +
fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(seekbar) {
bottom.linkTo(parent.bottom, spacing.medium)
},
Expand All @@ -293,8 +316,10 @@ fun PlayerControls(
}
AnimatedVisibility(
controlsShown && !areControlsLocked,
enter = slideInHorizontally(playControlsAnimationSpec()) { -it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutHorizontally(playControlsAnimationSpec()) { -it } + fadeOut(playControlsAnimationSpec()),
enter = slideInHorizontally(playerControlsEnterAnimationSpec()) { -it } +
fadeIn(playerControlsEnterAnimationSpec()),
exit = slideOutHorizontally(playerControlsExitAnimationSpec()) { -it } +
fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(topLeftControls) {
top.linkTo(parent.top, spacing.medium)
start.linkTo(parent.start)
Expand All @@ -305,8 +330,10 @@ fun PlayerControls(
// Top right controls
AnimatedVisibility(
controlsShown && !areControlsLocked,
enter = slideInHorizontally(playControlsAnimationSpec()) { it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutHorizontally(playControlsAnimationSpec()) { it } + fadeOut(playControlsAnimationSpec()),
enter = slideInHorizontally(playerControlsEnterAnimationSpec()) { it } +
fadeIn(playerControlsEnterAnimationSpec()),
exit = slideOutHorizontally(playerControlsExitAnimationSpec()) { it } +
fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(topRightControls) {
top.linkTo(parent.top, spacing.medium)
end.linkTo(parent.end)
Expand All @@ -315,8 +342,10 @@ fun PlayerControls(
// Bottom right controls
AnimatedVisibility(
controlsShown && !areControlsLocked,
enter = slideInHorizontally(playControlsAnimationSpec()) { it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutHorizontally(playControlsAnimationSpec()) { it } + fadeOut(playControlsAnimationSpec()),
enter = slideInHorizontally(playerControlsEnterAnimationSpec()) { it } +
fadeIn(playerControlsEnterAnimationSpec()),
exit = slideOutHorizontally(playerControlsExitAnimationSpec()) { it } +
fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(bottomRightControls) {
bottom.linkTo(seekbar.top)
end.linkTo(seekbar.end)
Expand All @@ -325,8 +354,10 @@ fun PlayerControls(
// Bottom left controls
AnimatedVisibility(
controlsShown && !areControlsLocked,
enter = slideInHorizontally(playControlsAnimationSpec()) { -it } + fadeIn(playControlsAnimationSpec()),
exit = slideOutHorizontally(playControlsAnimationSpec()) { -it } + fadeOut(playControlsAnimationSpec()),
enter = slideInHorizontally(playerControlsEnterAnimationSpec()) { -it } +
fadeIn(playerControlsEnterAnimationSpec()),
exit = slideOutHorizontally(playerControlsExitAnimationSpec()) { -it } +
fadeOut(playerControlsExitAnimationSpec()),
modifier = Modifier.constrainAs(bottomLeftControls) {
bottom.linkTo(seekbar.top)
start.linkTo(seekbar.start)
Expand All @@ -341,7 +372,12 @@ fun PlayerControls(
}
}

fun <T> playControlsAnimationSpec(): FiniteAnimationSpec<T> = tween(
durationMillis = 200,
fun <T> playerControlsExitAnimationSpec(): FiniteAnimationSpec<T> = tween(
durationMillis = 300,
easing = FastOutSlowInEasing,
)

fun <T> playerControlsEnterAnimationSpec(): FiniteAnimationSpec<T> = tween(
durationMillis = 100,
easing = LinearOutSlowInEasing,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package live.mehiz.mpvkt.ui.player.controls.components

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
Expand All @@ -24,6 +25,7 @@ import androidx.compose.ui.unit.dp
import live.mehiz.mpvkt.ui.player.controls.LocalPlayerButtonsClickEvent
import live.mehiz.mpvkt.ui.theme.spacing

@Suppress("ModifierClickableOrder")
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ControlsButton(
Expand All @@ -39,15 +41,19 @@ fun ControlsButton(
val clickEvent = LocalPlayerButtonsClickEvent.current
Box(
modifier = modifier
.clip(CircleShape)
.combinedClickable(
onClick = {
clickEvent()
onClick()
},
onLongClick = onLongClick,
interactionSource = interactionSource,
indication = ripple(),
indication = null,
)
.clip(CircleShape)
.indication(
interactionSource,
ripple()
)
.padding(MaterialTheme.spacing.medium),
) {
Expand All @@ -60,6 +66,7 @@ fun ControlsButton(
}
}

@Suppress("ModifierClickableOrder")
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ControlsButton(
Expand All @@ -74,15 +81,20 @@ fun ControlsButton(
val clickEvent = LocalPlayerButtonsClickEvent.current
Box(
modifier = modifier
.clip(CircleShape)
.combinedClickable(
onClick = {
clickEvent()
onClick()
},
onLongClick = onLongClick,
interactionSource = interactionSource,
indication = ripple(),
indication = null,

)
.clip(CircleShape)
.indication(
interactionSource,
ripple()
)
.padding(MaterialTheme.spacing.medium),
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ fun SeekbarWithTimers(
timersInverted: Pair<Boolean, Boolean>,
positionTimerOnClick: () -> Unit,
durationTimerOnCLick: () -> Unit,
chapters: ImmutableList<Segment>,
modifier: Modifier = Modifier,
chapters: ImmutableList<Segment>? = null,
) {
val clickEvent = LocalPlayerButtonsClickEvent.current
Row(
Expand All @@ -62,7 +62,16 @@ fun SeekbarWithTimers(
onValueChange = onValueChange,
onValueChangeFinished = onValueChangeFinished,
readAheadValue = readAheadValue,
segments = chapters?.filter { it.start in 0f..duration } ?: persistentListOf(),
segments = chapters
.filter { it.start in 0f..duration }
.let {
// add an extra segment at 0 if it doesn't exist.
if (it.isNotEmpty() && it[0].start != 0f) {
persistentListOf(Segment("", 0f)) + it
} else {
it
} + it
},
modifier = Modifier.weight(1f),
colors = SeekerDefaults.seekerColors(
progressColor = MaterialTheme.colorScheme.primary,
Expand Down Expand Up @@ -118,5 +127,6 @@ private fun PreviewSeekBar() {
Pair(false, true),
{},
{},
persistentListOf<Segment>()
)
}

0 comments on commit ef408cb

Please sign in to comment.