mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
refactor: improve player gesture feedback with timed visibility components
- Replace `LaunchedEffect` and manual state handling for showing/hiding player overlays (brightness, volume, seek feedback) with new reusable timed visibility composables. - Introduce `ValueChangeTimedVisibility` to automatically show brightness and volume sliders for a short duration when their values change. - Implement `EmptyValueTimedVisibility` to display the horizontal seek amount indicator and hide it after a delay. - Remove redundant state variables (`brightnessOverlayVisible`, `volumeOverlayVisible`, `showFeedbackPreview`) and related logic from `PlayerScreen`. - Clean up `PlayerGesturesLayer` by removing the `setFeedBackPreview` callback, simplifying its responsibility. - Remove the auto-hide `LaunchedEffect` from `PlayerSideSliders` as this is now handled externally.
This commit is contained in:
@@ -33,6 +33,8 @@ import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
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.PlayerControlsOverlay
|
||||
import hu.bbara.purefin.player.ui.components.PlayerGesturesLayer
|
||||
import hu.bbara.purefin.player.ui.components.PlayerLoadingErrorEndCard
|
||||
@@ -40,7 +42,6 @@ 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 kotlinx.coroutines.delay
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -61,18 +62,8 @@ fun PlayerScreen(
|
||||
var volume by remember { mutableStateOf(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) / maxVolume.toFloat()) }
|
||||
var brightness by remember { mutableStateOf(readCurrentBrightness(activity)) }
|
||||
var showSettings by remember { mutableStateOf(false) }
|
||||
var brightnessOverlayVisible by remember { mutableStateOf(false) }
|
||||
var volumeOverlayVisible by remember { mutableStateOf(false) }
|
||||
var showQueuePanel by remember { mutableStateOf(false) }
|
||||
var horizontalSeekFeedback by remember { mutableStateOf<Long?>(null) }
|
||||
var showFeedbackPreview by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(showFeedbackPreview) {
|
||||
if (!showFeedbackPreview) {
|
||||
delay(1000)
|
||||
horizontalSeekFeedback = null
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(uiState.isPlaying) {
|
||||
if (uiState.isPlaying) {
|
||||
@@ -111,22 +102,17 @@ fun PlayerScreen(
|
||||
onVerticalDragLeft = { delta ->
|
||||
val diff = (-delta / 800f)
|
||||
brightness = (brightness + diff).coerceIn(0f, 1f)
|
||||
brightnessOverlayVisible = true
|
||||
applyBrightness(activity, brightness)
|
||||
},
|
||||
onVerticalDragRight = { delta ->
|
||||
val diff = (-delta / 800f)
|
||||
volume = (volume + diff).coerceIn(0f, 1f)
|
||||
volumeOverlayVisible = true
|
||||
audioManager.setStreamVolume(
|
||||
AudioManager.STREAM_MUSIC,
|
||||
(volume * maxVolume).roundToInt(),
|
||||
0
|
||||
)
|
||||
},
|
||||
setFeedBackPreview = {
|
||||
showFeedbackPreview = it
|
||||
},
|
||||
onHorizontalDragPreview = {
|
||||
horizontalSeekFeedback = it
|
||||
},
|
||||
@@ -136,30 +122,40 @@ fun PlayerScreen(
|
||||
}
|
||||
)
|
||||
|
||||
horizontalSeekFeedback?.let { delta ->
|
||||
EmptyValueTimedVisibility(
|
||||
value = horizontalSeekFeedback,
|
||||
hideAfterMillis = 1_000
|
||||
) {
|
||||
SeekAmountIndicator(
|
||||
deltaMs = delta,
|
||||
deltaMs = it,
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = volumeOverlayVisible || brightnessOverlayVisible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut()
|
||||
) {
|
||||
ValueChangeTimedVisibility(
|
||||
value = brightness,
|
||||
hideAfterMillis = 800
|
||||
) { currentBrightness ->
|
||||
PlayerSideSliders(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
brightness = brightness,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
brightness = currentBrightness,
|
||||
volume = volume,
|
||||
showBrightness = brightnessOverlayVisible,
|
||||
showVolume = volumeOverlayVisible,
|
||||
onHide = {
|
||||
brightnessOverlayVisible = false
|
||||
volumeOverlayVisible = false
|
||||
}
|
||||
showBrightness = true,
|
||||
showVolume = false,
|
||||
)
|
||||
}
|
||||
|
||||
ValueChangeTimedVisibility(
|
||||
value = volume,
|
||||
hideAfterMillis = 800
|
||||
) { currentVolume ->
|
||||
PlayerSideSliders(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
brightness = brightness,
|
||||
volume = currentVolume,
|
||||
showBrightness = false,
|
||||
showVolume = true,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ fun PlayerGesturesLayer(
|
||||
onVerticalDragRight: (delta: Float) -> Unit,
|
||||
onHorizontalDragPreview: (deltaMs: Long?) -> Unit = {},
|
||||
onHorizontalDrag: (deltaMs: Long) -> Unit,
|
||||
setFeedBackPreview: (show: Boolean) -> Unit
|
||||
) {
|
||||
val density = LocalDensity.current
|
||||
val horizontalThresholdPx = with(density) { HorizontalSeekGestureHelper.START_THRESHOLD.toPx() }
|
||||
@@ -66,14 +65,12 @@ fun PlayerGesturesLayer(
|
||||
accumulatedHorizontalDrag = 0f
|
||||
isHorizontalDragActive = false
|
||||
lastPreviewDelta = null
|
||||
setFeedBackPreview(false)
|
||||
onHorizontalDragPreview(null)
|
||||
},
|
||||
onHorizontalDrag = { change, dragAmount ->
|
||||
accumulatedHorizontalDrag += dragAmount
|
||||
if (!isHorizontalDragActive && kotlin.math.abs(accumulatedHorizontalDrag) >= horizontalThresholdPx) {
|
||||
isHorizontalDragActive = true
|
||||
setFeedBackPreview(true)
|
||||
}
|
||||
if (isHorizontalDragActive) {
|
||||
change.consume()
|
||||
@@ -95,14 +92,12 @@ fun PlayerGesturesLayer(
|
||||
accumulatedHorizontalDrag = 0f
|
||||
isHorizontalDragActive = false
|
||||
lastPreviewDelta = null
|
||||
setFeedBackPreview(false)
|
||||
onHorizontalDragPreview(null)
|
||||
},
|
||||
onDragCancel = {
|
||||
accumulatedHorizontalDrag = 0f
|
||||
isHorizontalDragActive = false
|
||||
lastPreviewDelta = null
|
||||
setFeedBackPreview(false)
|
||||
onHorizontalDragPreview(null)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -15,12 +15,10 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
fun PlayerSideSliders(
|
||||
@@ -29,17 +27,9 @@ fun PlayerSideSliders(
|
||||
volume: Float,
|
||||
showBrightness: Boolean,
|
||||
showVolume: Boolean,
|
||||
onHide: () -> Unit
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
|
||||
LaunchedEffect(showBrightness, showVolume) {
|
||||
if (showBrightness || showVolume) {
|
||||
delay(800)
|
||||
onHide()
|
||||
}
|
||||
}
|
||||
|
||||
Box(modifier = modifier.fillMaxWidth()) {
|
||||
if (showBrightness) {
|
||||
SideOverlay(
|
||||
|
||||
Reference in New Issue
Block a user