add back button to player
This commit is contained in:
+2
-1
@@ -59,7 +59,8 @@ fun PlayerScreen(component: PlayerComponent) {
|
|||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
VideoPlayer(
|
VideoPlayer(
|
||||||
component.playerController,
|
component.playerController,
|
||||||
Modifier.fillMaxSize()
|
Modifier.fillMaxSize(),
|
||||||
|
onBack = { component.onBack() }
|
||||||
)
|
)
|
||||||
PlayerActionOverlay(
|
PlayerActionOverlay(
|
||||||
effect is PlayerEffect.PlayNextEpisode,
|
effect is PlayerEffect.PlayNextEpisode,
|
||||||
|
|||||||
+8
-1
@@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
@@ -58,6 +59,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
|
import ru.shadowsparky.ui.components.BackButton
|
||||||
import ru.shadowsparky.ui.components.IconButton
|
import ru.shadowsparky.ui.components.IconButton
|
||||||
import ru.shadowsparky.ui.components.isTv
|
import ru.shadowsparky.ui.components.isTv
|
||||||
import ru.shadowsparky.ui.theme.focusBorder
|
import ru.shadowsparky.ui.theme.focusBorder
|
||||||
@@ -74,7 +76,8 @@ fun DefaultControls(
|
|||||||
state: PlayerState,
|
state: PlayerState,
|
||||||
controlsState: ControlsState,
|
controlsState: ControlsState,
|
||||||
controller: PlayerController,
|
controller: PlayerController,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
onBack: () -> Unit
|
||||||
) {
|
) {
|
||||||
val isTv = isTv()
|
val isTv = isTv()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -93,7 +96,11 @@ fun DefaultControls(
|
|||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(if (isUiLocked.value) Color.Transparent else Color.Black.copy(alpha = 0.4f))
|
.background(if (isUiLocked.value) Color.Transparent else Color.Black.copy(alpha = 0.4f))
|
||||||
|
.safeDrawingPadding()
|
||||||
) {
|
) {
|
||||||
|
Box(modifier = Modifier.align(Alignment.TopStart).padding(8.dp)) {
|
||||||
|
BackButton { onBack() }
|
||||||
|
}
|
||||||
SideDoubleTapSeekZones(controller)
|
SideDoubleTapSeekZones(controller)
|
||||||
Row(modifier = Modifier.align(Alignment.TopEnd).focusGroup().padding(8.dp)) {
|
Row(modifier = Modifier.align(Alignment.TopEnd).focusGroup().padding(8.dp)) {
|
||||||
if (audioTracksState.isNotEmpty() && !isUiLocked.value) {
|
if (audioTracksState.isNotEmpty() && !isUiLocked.value) {
|
||||||
|
|||||||
+9
-2
@@ -45,13 +45,20 @@ import ru.shadowsparky.videoplayer.ControlsState
|
|||||||
import ru.shadowsparky.videoplayer.PlayerController
|
import ru.shadowsparky.videoplayer.PlayerController
|
||||||
import ru.shadowsparky.videoplayer.PlayerEvent
|
import ru.shadowsparky.videoplayer.PlayerEvent
|
||||||
import ru.shadowsparky.videoplayer.PlayerState
|
import ru.shadowsparky.videoplayer.PlayerState
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoPlayer(
|
fun VideoPlayer(
|
||||||
controller: PlayerController,
|
controller: PlayerController,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
onBack: () -> Unit,
|
||||||
overlayContent: @Composable (PlayerState, ControlsState) -> Unit = { player, controls ->
|
overlayContent: @Composable (PlayerState, ControlsState) -> Unit = { player, controls ->
|
||||||
DefaultControls(player, controls, controller = controller)
|
DefaultControls(
|
||||||
|
player,
|
||||||
|
controls,
|
||||||
|
controller = controller,
|
||||||
|
onBack = onBack
|
||||||
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val isTv = isTv()
|
val isTv = isTv()
|
||||||
@@ -86,7 +93,7 @@ fun VideoPlayer(
|
|||||||
|
|
||||||
LaunchedEffect(areControlsVisible, state.isPlaying, lastErrorMessage, interactionCount) {
|
LaunchedEffect(areControlsVisible, state.isPlaying, lastErrorMessage, interactionCount) {
|
||||||
if (areControlsVisible && state.isPlaying && lastErrorMessage == null) {
|
if (areControlsVisible && state.isPlaying && lastErrorMessage == null) {
|
||||||
delay(5000)
|
delay(5.seconds)
|
||||||
areControlsVisible = false
|
areControlsVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
@@ -49,7 +48,6 @@ import androidx.compose.ui.graphics.painter.Painter
|
|||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ru.shadowsparky.ui.nav.Route
|
import ru.shadowsparky.ui.nav.Route
|
||||||
import ru.shadowsparky.ui.theme.focusBorder
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class NavigationEntry<out T : Route>(
|
data class NavigationEntry<out T : Route>(
|
||||||
@@ -159,6 +157,7 @@ private fun <T : Route> DynamicNavigationScaffold(
|
|||||||
) {
|
) {
|
||||||
val entries = navigationEntries.orEmpty()
|
val entries = navigationEntries.orEmpty()
|
||||||
val railState = rememberWideNavigationRailState(WideNavigationRailValue.Collapsed)
|
val railState = rememberWideNavigationRailState(WideNavigationRailValue.Collapsed)
|
||||||
|
val isExpanded = railState.targetValue == WideNavigationRailValue.Expanded
|
||||||
var railHasFocus by remember { mutableStateOf(false) }
|
var railHasFocus by remember { mutableStateOf(false) }
|
||||||
LaunchedEffect(railHasFocus) {
|
LaunchedEffect(railHasFocus) {
|
||||||
if (railHasFocus) railState.expand() else railState.collapse()
|
if (railHasFocus) railState.expand() else railState.collapse()
|
||||||
@@ -168,26 +167,17 @@ private fun <T : Route> DynamicNavigationScaffold(
|
|||||||
navigationSuite = {
|
navigationSuite = {
|
||||||
WideNavigationRail(
|
WideNavigationRail(
|
||||||
state = railState,
|
state = railState,
|
||||||
modifier = Modifier.onFocusChanged { railHasFocus = it.hasFocus }
|
modifier = Modifier.onFocusChanged { railHasFocus = it.hasFocus }.focusGroup()
|
||||||
.focusGroup(),
|
|
||||||
) {
|
) {
|
||||||
entries.forEach { entry ->
|
entries.forEach { entry ->
|
||||||
WideNavigationRailItem(
|
WideNavigationRailItem(
|
||||||
railExpanded =
|
railExpanded = isExpanded,
|
||||||
railState.targetValue == WideNavigationRailValue.Expanded,
|
|
||||||
selected = currentRoute == entry.route,
|
selected = currentRoute == entry.route,
|
||||||
onClick = {
|
onClick = { onSelectNavigation?.invoke(entry.route) },
|
||||||
onSelectNavigation?.invoke(entry.route)
|
icon = { Icon(entry.painter, entry.title) },
|
||||||
},
|
|
||||||
icon = {
|
|
||||||
Icon(entry.painter, entry.title)
|
|
||||||
},
|
|
||||||
label = {
|
label = {
|
||||||
if (railState.currentValue == WideNavigationRailValue.Expanded) {
|
if (isExpanded) Text(entry.title)
|
||||||
Text(entry.title)
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier.focusBorder(false, CircleShape)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user