Skip to content

Commit

Permalink
259 compose toggleable view for tv and mobile (#262)
Browse files Browse the repository at this point in the history
Co-authored-by: Samuel Défago <[email protected]>
  • Loading branch information
StaehliJ and defagos authored Oct 6, 2023
1 parent 7b2fdf4 commit 7760ce9
Show file tree
Hide file tree
Showing 14 changed files with 657 additions and 534 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
accompanist = "0.33.0-alpha"
activityCompose = "1.7.2"
androidGradlePlugin = "8.1.1"
androidGradlePlugin = "8.1.2"
dataProvider = "0.5.0"
kotlinPlugin = "1.9.0"
detekt = "1.22.0" # https://github.com/detekt/detekt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,28 @@ import ch.srgssr.pillarbox.player.canSeekToNext
import ch.srgssr.pillarbox.player.canSeekToPrevious
import ch.srgssr.pillarbox.ui.availableCommandsAsState
import ch.srgssr.pillarbox.ui.isPlayingAsState
import ch.srgssr.pillarbox.ui.layout.DelayedVisibilityState

/**
* Tv playback row
*
* @param player
* @param state
* @param modifier
*/
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun TvPlaybackRow(
player: Player,
state: DelayedVisibilityState,
modifier: Modifier = Modifier,
) {
val isPlaying = player.isPlayingAsState()
val focusRequester = remember {
FocusRequester()
}
LaunchedEffect(Unit) {
focusRequester.requestFocus()
val focusRequester = remember { FocusRequester() }
LaunchedEffect(state.isVisible) {
if (state.isVisible) {
focusRequester.requestFocus()
}
}
Row(
modifier = modifier,
Expand All @@ -75,8 +78,7 @@ fun TvPlaybackRow(
}

IconButton(
modifier = Modifier
.focusRequester(focusRequester),
modifier = Modifier.focusRequester(focusRequester),
onClick = {
player.playWhenReady = !player.playWhenReady
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@
*/
package ch.srgssr.pillarbox.demo.tv.player.compose

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.media3.common.Player
import ch.srgssr.pillarbox.ui.PlayerSurface
import ch.srgssr.pillarbox.ui.ToggleView
import ch.srgssr.pillarbox.ui.rememberToggleState
import kotlin.time.Duration.Companion.seconds
import ch.srgssr.pillarbox.ui.layout.ToggleableBox
import ch.srgssr.pillarbox.ui.layout.rememberDelayedVisibilityState

/**
* Tv player view
Expand All @@ -27,27 +25,20 @@ fun TvPlayerView(
player: Player,
modifier: Modifier = Modifier
) {
Box(modifier = modifier) {
PlayerSurface(
player = player,
modifier = Modifier.fillMaxSize()
) {
val toggleState = rememberToggleState(visible = true, duration = 4.seconds)
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.clickable {
toggleState.toggleVisible()
}
) {
ToggleView(toggleState = toggleState) {
TvPlaybackRow(
player = player,
modifier = Modifier.matchParentSize()
)
}
val visibilityState = rememberDelayedVisibilityState(player = player, visible = true)
ToggleableBox(
modifier = modifier,
visibilityState = visibilityState,
toggleableContent = {
Box(modifier = Modifier, contentAlignment = Alignment.Center) {
TvPlaybackRow(player = player, state = visibilityState)
}
},
content = {
PlayerSurface(
player = player,
modifier = Modifier.fillMaxSize()
)
}
}
)
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ private fun PlayerContent(
SimplePlayerView(
modifier = Modifier.fillMaxSize(),
player = player,
controlVisible = !pictureInPicture,
controlsToggleable = !pictureInPicture,
controlsVisible = !pictureInPicture,
fullScreenEnabled = fullScreenState,
fullScreenClicked = fullScreenToggle,
pictureInPictureClicked = pictureInPictureClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
package ch.srgssr.pillarbox.demo.ui.player

import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsDraggedAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
Expand All @@ -17,22 +22,31 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalView
import androidx.media3.common.Player
import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerBottomToolbar
import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerError
import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerPlaybackRow
import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerTimeSlider
import ch.srgssr.pillarbox.ui.ScaleMode
import ch.srgssr.pillarbox.ui.currentMediaMetadataAsState
import ch.srgssr.pillarbox.ui.hasMediaItemsAsState
import ch.srgssr.pillarbox.ui.isPlayingAsState
import ch.srgssr.pillarbox.ui.layout.ToggleableBox
import ch.srgssr.pillarbox.ui.layout.rememberDelayedVisibilityState
import ch.srgssr.pillarbox.ui.playbackStateAsState
import ch.srgssr.pillarbox.ui.playerErrorAsState

/**
* Simple player view
*
* @param player The [Player] to observe.
* @param modifier The modifier to be applied to the layout.
* @param controlVisible The control visibility.
* @param controlsVisible The control visibility.
* @param controlsToggleable The controls are toggleable.
* @param fullScreenEnabled The fullscreen state.
* @param fullScreenClicked The fullscreen button action. If null no button.
* @param pictureInPictureClicked The picture in picture button action. If null no button.
Expand All @@ -42,7 +56,8 @@ import ch.srgssr.pillarbox.ui.playerErrorAsState
fun SimplePlayerView(
player: Player,
modifier: Modifier = Modifier,
controlVisible: Boolean = true,
controlsVisible: Boolean = true,
controlsToggleable: Boolean = true,
fullScreenEnabled: Boolean = false,
fullScreenClicked: ((Boolean) -> Unit)? = null,
pictureInPictureClicked: (() -> Unit)? = null,
Expand All @@ -64,13 +79,13 @@ fun SimplePlayerView(
)
}
}

return
}
var pinchScaleMode by remember {
mutableStateOf(ScaleMode.Fit)
}
val surfaceModifier = if (fullScreenEnabled) {

val scalableModifier = if (fullScreenEnabled) {
modifier.then(
Modifier.pointerInput(pinchScaleMode) {
var lastZoomValue = 1.0f
Expand All @@ -83,22 +98,71 @@ fun SimplePlayerView(
} else {
modifier
}
LocalView.current.keepScreenOn = player.isPlayingAsState()
DemoPlayerSurface(
modifier = surfaceModifier,
val isPlaying = player.isPlayingAsState()
LocalView.current.keepScreenOn = isPlaying
val interactionSource = remember {
MutableInteractionSource()
}
val isDragged = interactionSource.collectIsDraggedAsState().value
val visibilityState = rememberDelayedVisibilityState(
player = player,
scaleMode = if (fullScreenEnabled) pinchScaleMode else ScaleMode.Fit
autoHideEnabled = !isDragged,
visible = controlsVisible
)

ToggleableBox(
modifier = scalableModifier,
toggleable = controlsToggleable,
visibilityState = visibilityState,
toggleableContent = {
val mediaMetadata = player.currentMediaMetadataAsState()
Box(
modifier = Modifier
.fillMaxSize()
.drawBehind {
drawRect(color = Color.Black.copy(0.5f))
},
contentAlignment = Alignment.Center
) {
Text(
modifier = Modifier.align(Alignment.TopStart),
text = mediaMetadata.title.toString(), color = Color.Gray
)
PlayerPlaybackRow(
modifier = Modifier
.fillMaxWidth()
.align(Alignment.Center),
player = player
)
Column(
modifier = Modifier
.align(Alignment.BottomCenter)
) {
PlayerTimeSlider(
modifier = Modifier,
player = player,
interactionSource = interactionSource
)
PlayerBottomToolbar(
modifier = Modifier
.fillMaxWidth(),
fullScreenEnabled = fullScreenEnabled,
fullScreenClicked = fullScreenClicked,
pictureInPictureClicked = pictureInPictureClicked,
optionClicked = optionClicked
)
}
}
}
) {
DemoPlaybackControls(
modifier = Modifier
.matchParentSize(),
DemoPlayerSurface(
modifier = Modifier.fillMaxSize(),
player = player,
controlVisible = controlVisible,
autoHideEnabled = true,
fullScreenEnabled = fullScreenEnabled,
fullScreenClicked = fullScreenClicked,
pictureInPictureClicked = pictureInPictureClicked,
optionClicked = optionClicked
)
scaleMode = if (fullScreenEnabled) pinchScaleMode else ScaleMode.Fit
) {
if (player.playbackStateAsState() == Player.STATE_BUFFERING) {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center), color = Color.White)
}
}
}
}
Loading

0 comments on commit 7760ce9

Please sign in to comment.