mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
[UI] Add playback overlay dark gradient background (#505)
## Description This PR adds a background dimming effect behind the playback controls to fix readability issues against bright video content. It implements a full-screen vertical gradient that ensures white text and buttons remain legible. I added a vertical gradient fading from transparent at the top to ~95% black at the bottom which adds contrast for UI elements without obscuring the center of the video. ### Related issues Solves [#485](https://github.com/damontecres/Wholphin/issues/485) ### Screenshots <img width="1948" height="1112" alt="playback" src="https://github.com/user-attachments/assets/f671072c-e37a-491d-b82f-fb6f888a42c7" /> <img width="1918" height="1081" alt="no_gradient" src="https://github.com/user-attachments/assets/30bc2fee-ef5a-4d63-87a6-953e401cd84b" /> ### AI/LLM usage This change was developed with the assistance of AI, but was not wholly generated by AI. --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Damontecres <damontecres@gmail.com> Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
This commit is contained in:
parent
0c823b91cd
commit
e60748a0d0
4 changed files with 63 additions and 31 deletions
|
|
@ -17,6 +17,7 @@ fun BoxScope.TimeDisplay(modifier: Modifier = Modifier) {
|
|||
text = LocalClock.current.timeString,
|
||||
fontSize = 18.sp,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier =
|
||||
modifier
|
||||
.align(Alignment.TopEnd)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
|
@ -34,6 +35,8 @@ import androidx.compose.ui.focus.FocusRequester
|
|||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.focusRestorer
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
|
|
@ -127,10 +130,37 @@ fun PlaybackOverlay(
|
|||
var controllerHeight by remember { mutableStateOf(0.dp) }
|
||||
var state by remember { mutableStateOf(OverlayViewState.CONTROLLER) }
|
||||
|
||||
// Background scrim for OSD readability
|
||||
val scrimBrush =
|
||||
remember {
|
||||
Brush.verticalGradient(
|
||||
colors =
|
||||
listOf(
|
||||
Color.Transparent,
|
||||
Color.Black.copy(alpha = 0.5f),
|
||||
Color.Black.copy(alpha = 0.80f),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = modifier,
|
||||
contentAlignment = Alignment.BottomCenter,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = controllerViewState.controlsVisible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
modifier = Modifier.matchParentSize(),
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(scrimBrush),
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
state == OverlayViewState.CONTROLLER,
|
||||
enter = slideInVertically() + fadeIn(),
|
||||
|
|
|
|||
|
|
@ -332,37 +332,6 @@ fun PlaybackPage(
|
|||
}
|
||||
}
|
||||
|
||||
// Subtitles
|
||||
if (skipIndicatorDuration == 0L && currentItemPlayback.subtitleIndexEnabled) {
|
||||
val maxSize by animateFloatAsState(if (controllerViewState.controlsVisible) .7f else 1f)
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
SubtitleView(context).apply {
|
||||
preferences.appPreferences.interfacePreferences.subtitlesPreferences.let {
|
||||
setStyle(it.toSubtitleStyle())
|
||||
setFixedTextSize(Dimension.SP, it.fontSize.toFloat())
|
||||
setBottomPaddingFraction(it.margin.toFloat() / 100f)
|
||||
}
|
||||
}
|
||||
},
|
||||
update = {
|
||||
it.setCues(cues)
|
||||
Media3SubtitleOverride(
|
||||
preferences.appPreferences.interfacePreferences.subtitlesPreferences
|
||||
.calculateEdgeSize(density),
|
||||
).apply(it)
|
||||
},
|
||||
onReset = {
|
||||
it.setCues(null)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize(maxSize)
|
||||
.align(Alignment.TopCenter)
|
||||
.background(Color.Transparent),
|
||||
)
|
||||
}
|
||||
|
||||
// The playback controls
|
||||
AnimatedVisibility(
|
||||
controllerViewState.controlsVisible,
|
||||
|
|
@ -402,6 +371,37 @@ fun PlaybackPage(
|
|||
showClock = preferences.appPreferences.interfacePreferences.showClock,
|
||||
)
|
||||
}
|
||||
|
||||
// Subtitles
|
||||
if (skipIndicatorDuration == 0L && currentItemPlayback.subtitleIndexEnabled) {
|
||||
val maxSize by animateFloatAsState(if (controllerViewState.controlsVisible) .7f else 1f)
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
SubtitleView(context).apply {
|
||||
preferences.appPreferences.interfacePreferences.subtitlesPreferences.let {
|
||||
setStyle(it.toSubtitleStyle())
|
||||
setFixedTextSize(Dimension.SP, it.fontSize.toFloat())
|
||||
setBottomPaddingFraction(it.margin.toFloat() / 100f)
|
||||
}
|
||||
}
|
||||
},
|
||||
update = {
|
||||
it.setCues(cues)
|
||||
Media3SubtitleOverride(
|
||||
preferences.appPreferences.interfacePreferences.subtitlesPreferences
|
||||
.calculateEdgeSize(density),
|
||||
).apply(it)
|
||||
},
|
||||
onReset = {
|
||||
it.setCues(null)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize(maxSize)
|
||||
.align(Alignment.TopCenter)
|
||||
.background(Color.Transparent),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Ask to skip intros, etc button
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ fun SkipIndicator(
|
|||
modifier = Modifier.align(Alignment.Center),
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontSize = 13.sp,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
text = abs(durationMs / 1000).toString(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue