mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
refactor(player): replace side sliders with centered adjustment indicators
- Replace the horizontal `PlayerSideSliders` with a new vertical `PlayerAdjustmentIndicator` for brightness and volume, displaying it in the center of the screen. - Create `PlayerAdjustmentIndicator.kt`, a new composable that shows an icon, a vertical progress bar, and a percentage value within a semi-transparent black background. - Update `PlayerScreen` to use the new centered indicator instead of the old side-aligned sliders when brightness or volume is adjusted via gestures. - Pass a `modifier` to `ValueChangeTimedVisibility` to correctly position the new indicators. - Change the background color of the "Seek to" toast message from a theme surface color to semi-transparent black for better consistency.
This commit is contained in:
@@ -9,6 +9,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,8 @@ import kotlinx.coroutines.delay
|
||||
fun <T> EmptyValueTimedVisibility(
|
||||
value: T?,
|
||||
hideAfterMillis: Long = 1_000,
|
||||
content: @Composable (T) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (T) -> Unit
|
||||
) {
|
||||
val shownValue = remember { mutableStateOf<T?>(null) }
|
||||
|
||||
@@ -55,7 +57,8 @@ fun <T> EmptyValueTimedVisibility(
|
||||
fun <T> ValueChangeTimedVisibility(
|
||||
value: T,
|
||||
hideAfterMillis: Long = 1_000,
|
||||
content: @Composable (T) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable (T) -> Unit
|
||||
) {
|
||||
var displayedValue by remember { mutableStateOf(value) }
|
||||
var isVisible by remember { mutableStateOf(false) }
|
||||
@@ -75,6 +78,7 @@ fun <T> ValueChangeTimedVisibility(
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isVisible,
|
||||
modifier = modifier,
|
||||
enter = EnterTransition.None,
|
||||
exit = ExitTransition.None
|
||||
) {
|
||||
|
||||
@@ -15,6 +15,9 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.BrightnessMedium
|
||||
import androidx.compose.material.icons.outlined.VolumeUp
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -27,6 +30,7 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
@@ -35,12 +39,12 @@ import androidx.media3.ui.AspectRatioFrameLayout
|
||||
import androidx.media3.ui.PlayerView
|
||||
import hu.bbara.purefin.common.ui.components.EmptyValueTimedVisibility
|
||||
import hu.bbara.purefin.common.ui.components.ValueChangeTimedVisibility
|
||||
import hu.bbara.purefin.player.ui.components.PlayerAdjustmentIndicator
|
||||
import hu.bbara.purefin.player.ui.components.PlayerControlsOverlay
|
||||
import hu.bbara.purefin.player.ui.components.PlayerGesturesLayer
|
||||
import hu.bbara.purefin.player.ui.components.PlayerLoadingErrorEndCard
|
||||
import hu.bbara.purefin.player.ui.components.PlayerQueuePanel
|
||||
import hu.bbara.purefin.player.ui.components.PlayerSettingsSheet
|
||||
import hu.bbara.purefin.player.ui.components.PlayerSideSliders
|
||||
import hu.bbara.purefin.player.viewmodel.PlayerViewModel
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
@@ -135,27 +139,33 @@ fun PlayerScreen(
|
||||
|
||||
ValueChangeTimedVisibility(
|
||||
value = brightness,
|
||||
hideAfterMillis = 800
|
||||
hideAfterMillis = 800,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.padding(start = 20.dp)
|
||||
) { currentBrightness ->
|
||||
PlayerSideSliders(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
brightness = currentBrightness,
|
||||
volume = volume,
|
||||
showBrightness = true,
|
||||
showVolume = false,
|
||||
PlayerAdjustmentIndicator(
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center),
|
||||
icon = Icons.Outlined.BrightnessMedium,
|
||||
contentDescription = "Brightness",
|
||||
value = currentBrightness
|
||||
)
|
||||
}
|
||||
|
||||
ValueChangeTimedVisibility(
|
||||
value = volume,
|
||||
hideAfterMillis = 800
|
||||
hideAfterMillis = 800,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.padding(end = 20.dp)
|
||||
) { currentVolume ->
|
||||
PlayerSideSliders(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
brightness = brightness,
|
||||
volume = currentVolume,
|
||||
showBrightness = false,
|
||||
showVolume = true,
|
||||
PlayerAdjustmentIndicator(
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center),
|
||||
icon = Icons.Outlined.VolumeUp,
|
||||
contentDescription = "Volume",
|
||||
value = currentVolume
|
||||
)
|
||||
}
|
||||
|
||||
@@ -235,7 +245,7 @@ private fun SeekAmountIndicator(deltaMs: Long, modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(scheme.surface.copy(alpha = 0.9f))
|
||||
.background(Color.Black.copy(alpha = 0.9f))
|
||||
.padding(horizontal = 20.dp, vertical = 12.dp)
|
||||
) {
|
||||
Text(
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package hu.bbara.purefin.player.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Composable
|
||||
fun PlayerAdjustmentIndicator(
|
||||
modifier: Modifier = Modifier,
|
||||
icon: ImageVector,
|
||||
contentDescription: String?,
|
||||
value: Float,
|
||||
sliderHeight: Dp = 140.dp,
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
val percent = (value.coerceIn(0f, 1f) * 100).roundToInt()
|
||||
val clamped = value.coerceIn(0f, 1f)
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.background(Color.Black.copy(alpha = 0.5f))
|
||||
.padding(horizontal = 20.dp, vertical = 16.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = contentDescription,
|
||||
tint = scheme.onSurface
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(10.dp)
|
||||
.height(sliderHeight)
|
||||
.clip(RoundedCornerShape(5.dp))
|
||||
.background(scheme.onSurface.copy(alpha = 0.2f))
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.width(10.dp)
|
||||
.height(sliderHeight * clamped)
|
||||
.clip(RoundedCornerShape(5.dp))
|
||||
.background(scheme.primary)
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "$percent%",
|
||||
color = scheme.onSurface,
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package hu.bbara.purefin.player.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.BrightnessMedium
|
||||
import androidx.compose.material.icons.outlined.VolumeUp
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun PlayerSideSliders(
|
||||
modifier: Modifier = Modifier,
|
||||
brightness: Float,
|
||||
volume: Float,
|
||||
showBrightness: Boolean,
|
||||
showVolume: Boolean,
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
|
||||
Box(modifier = modifier.fillMaxWidth()) {
|
||||
if (showBrightness) {
|
||||
SideOverlay(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.padding(start = 16.dp),
|
||||
icon = { Icon(Icons.Outlined.BrightnessMedium, contentDescription = null, tint = scheme.onBackground) },
|
||||
progress = brightness,
|
||||
scheme = scheme
|
||||
)
|
||||
}
|
||||
if (showVolume) {
|
||||
SideOverlay(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.padding(end = 16.dp),
|
||||
icon = { Icon(Icons.Outlined.VolumeUp, contentDescription = null, tint = scheme.onBackground) },
|
||||
progress = volume,
|
||||
scheme = scheme
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SideOverlay(
|
||||
modifier: Modifier = Modifier,
|
||||
icon: @Composable () -> Unit,
|
||||
progress: Float,
|
||||
scheme: androidx.compose.material3.ColorScheme
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxHeight(0.3f)
|
||||
.wrapContentHeight(align = Alignment.CenterVertically)
|
||||
.clip(RoundedCornerShape(18.dp))
|
||||
.background(scheme.background.copy(alpha = 0.8f))
|
||||
.padding(horizontal = 14.dp, vertical = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
icon()
|
||||
LinearProgressIndicator(
|
||||
progress = { progress.coerceIn(0f, 1f) },
|
||||
modifier = Modifier
|
||||
.padding(top = 10.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(RoundedCornerShape(8.dp)),
|
||||
color = scheme.primary,
|
||||
trackColor = scheme.onBackground.copy(alpha = 0.2f)
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user