Skip to content

Commit

Permalink
Add simple error to the player on tv
Browse files Browse the repository at this point in the history
  • Loading branch information
StaehliJ committed Dec 15, 2023
1 parent e210118 commit b9f7c3e
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) SRG SSR. All rights reserved.
* License information is available from the LICENSE file.
*/
package ch.srgssr.pillarbox.demo.tv.player.compose

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.media3.common.PlaybackException
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.Text
import ch.srgssr.pillarbox.core.business.SRGErrorMessageProvider

/**
* Player error
*
* @param playerError The player error.
* @param modifier The modifier to layout the view.
* @param onRetry Action to retry.
* @receiver
*/
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun PlayerError(playerError: PlaybackException, modifier: Modifier = Modifier, onRetry: () -> Unit) {
val context = LocalContext.current
val errorMessageProvider = remember(context) {
SRGErrorMessageProvider(context)
}
Box(
modifier = Modifier
.fillMaxSize()
.clickable { onRetry.invoke() }
) {
Column(modifier = Modifier.align(Alignment.Center), horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = errorMessageProvider.getErrorMessage(playerError).second,
color = Color.White
)
Text(text = "Click to retry!", color = Color.LightGray, fontStyle = FontStyle.Italic)
}
}
}

@Preview
@Composable
private fun PlayerErrorPreview() {
PlayerError(playerError = PlaybackException("", null, PlaybackException.ERROR_CODE_UNSPECIFIED)) {
// Nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
Expand All @@ -24,11 +26,12 @@ import androidx.tv.material3.DrawerValue
import androidx.tv.material3.ExperimentalTvMaterial3Api
import androidx.tv.material3.Icon
import androidx.tv.material3.IconButton
import androidx.tv.material3.LocalContentColor
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.rememberDrawerState
import ch.srgssr.pillarbox.demo.tv.R
import ch.srgssr.pillarbox.demo.tv.ui.theme.paddings
import ch.srgssr.pillarbox.ui.extension.handleDPadKeyEvents
import ch.srgssr.pillarbox.ui.extension.playerErrorAsState
import ch.srgssr.pillarbox.ui.widget.maintainVisibleOnFocus
import ch.srgssr.pillarbox.ui.widget.player.PlayerSurface
import ch.srgssr.pillarbox.ui.widget.rememberDelayedVisibilityState
Expand Down Expand Up @@ -60,46 +63,55 @@ fun TvPlayerView(
drawerState = drawerState,
modifier = modifier
) {
PlayerSurface(
player = player,
modifier = Modifier
.fillMaxSize()
.handleDPadKeyEvents(onEnter = {
visibilityState.show()
})
.focusable(true)
)
AnimatedVisibility(
visible = visibilityState.isVisible,
enter = expandVertically { it },
exit = shrinkVertically { it }
) {
Box(
val error by player.playerErrorAsState()
if (error != null) {
CompositionLocalProvider(
LocalContentColor provides MaterialTheme.colorScheme.onSurface
) {
PlayerError(modifier = Modifier.fillMaxSize(), playerError = error!!, onRetry = player::prepare)
}
} else {
PlayerSurface(
player = player,
modifier = Modifier
.fillMaxSize()
.maintainVisibleOnFocus(delayedVisibilityState = visibilityState),
contentAlignment = Alignment.Center
.handleDPadKeyEvents(onEnter = {
visibilityState.show()
})
.focusable(true)
)
AnimatedVisibility(
visible = visibilityState.isVisible,
enter = expandVertically { it },
exit = shrinkVertically { it }
) {
TvPlaybackRow(
player = player,
state = visibilityState
)

IconButton(
onClick = { drawerState.setValue(DrawerValue.Open) },
Box(
modifier = Modifier
.padding(MaterialTheme.paddings.baseline)
.align(Alignment.BottomEnd)
.fillMaxSize()
.maintainVisibleOnFocus(delayedVisibilityState = visibilityState),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = stringResource(R.string.settings)
TvPlaybackRow(
player = player,
state = visibilityState
)

IconButton(
onClick = { drawerState.setValue(DrawerValue.Open) },
modifier = Modifier
.padding(MaterialTheme.paddings.baseline)
.align(Alignment.BottomEnd)
) {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = stringResource(ch.srgssr.pillarbox.demo.tv.R.string.settings)
)
}
}
}
}
BackHandler(enabled = visibilityState.isVisible) {
visibilityState.hide()
BackHandler(enabled = visibilityState.isVisible) {
visibilityState.hide()
}
}
}
}

0 comments on commit b9f7c3e

Please sign in to comment.