mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
Add play button to TV series screen
This commit is contained in:
@@ -3,11 +3,13 @@ package hu.bbara.purefin.app.content.series
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
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.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -19,6 +21,8 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusProperties
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
@@ -26,10 +30,13 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||||||
import hu.bbara.purefin.common.ui.MediaSynopsis
|
import hu.bbara.purefin.common.ui.MediaSynopsis
|
||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||||
import hu.bbara.purefin.common.ui.components.MediaHero
|
import hu.bbara.purefin.common.ui.components.MediaHero
|
||||||
|
import hu.bbara.purefin.common.ui.components.MediaResumeButton
|
||||||
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
||||||
|
import hu.bbara.purefin.core.model.Episode
|
||||||
import hu.bbara.purefin.core.model.Season
|
import hu.bbara.purefin.core.model.Season
|
||||||
import hu.bbara.purefin.core.model.Series
|
import hu.bbara.purefin.core.model.Series
|
||||||
import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
|
import hu.bbara.purefin.feature.shared.content.series.SeriesViewModel
|
||||||
|
import org.jellyfin.sdk.model.UUID
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SeriesScreen(
|
fun SeriesScreen(
|
||||||
@@ -48,6 +55,7 @@ fun SeriesScreen(
|
|||||||
SeriesScreenInternal(
|
SeriesScreenInternal(
|
||||||
series = seriesData,
|
series = seriesData,
|
||||||
onBack = viewModel::onBack,
|
onBack = viewModel::onBack,
|
||||||
|
onPlayEpisode = viewModel::onPlayEpisode,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -59,6 +67,7 @@ fun SeriesScreen(
|
|||||||
private fun SeriesScreenInternal(
|
private fun SeriesScreenInternal(
|
||||||
series: Series,
|
series: Series,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
|
onPlayEpisode: (UUID) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
@@ -72,9 +81,23 @@ private fun SeriesScreenInternal(
|
|||||||
}
|
}
|
||||||
return series.seasons.first()
|
return series.seasons.first()
|
||||||
}
|
}
|
||||||
val selectedSeason = remember { mutableStateOf<Season>(getDefaultSeason()) }
|
val selectedSeason = remember(series.id) { mutableStateOf(getDefaultSeason()) }
|
||||||
|
val nextUpEpisode = remember(series.id) {
|
||||||
|
series.seasons.firstNotNullOfOrNull { season ->
|
||||||
|
season.episodes.firstOrNull { !it.watched }
|
||||||
|
} ?: series.seasons.firstOrNull()?.episodes?.firstOrNull()
|
||||||
|
}
|
||||||
|
val playFocusRequester = remember { FocusRequester() }
|
||||||
val firstContentFocusRequester = remember { FocusRequester() }
|
val firstContentFocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
|
LaunchedEffect(series.id, nextUpEpisode?.id) {
|
||||||
|
if (nextUpEpisode != null) {
|
||||||
|
playFocusRequester.requestFocus()
|
||||||
|
} else {
|
||||||
|
firstContentFocusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -104,6 +127,22 @@ private fun SeriesScreenInternal(
|
|||||||
SeriesMetaChips(series = series)
|
SeriesMetaChips(series = series)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (nextUpEpisode != null) {
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
Row(modifier = hPad) {
|
||||||
|
MediaResumeButton(
|
||||||
|
text = nextUpEpisode.playButtonText(),
|
||||||
|
progress = nextUpEpisode.progress?.div(100)?.toFloat() ?: 0f,
|
||||||
|
onClick = { onPlayEpisode(nextUpEpisode.id) },
|
||||||
|
modifier = Modifier
|
||||||
|
.sizeIn(maxWidth = 200.dp)
|
||||||
|
.focusRequester(playFocusRequester)
|
||||||
|
.focusProperties { down = firstContentFocusRequester }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
MediaSynopsis(
|
MediaSynopsis(
|
||||||
@@ -150,8 +189,12 @@ private fun SeriesScreenInternal(
|
|||||||
}
|
}
|
||||||
SeriesTopBar(
|
SeriesTopBar(
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
downFocusRequester = firstContentFocusRequester,
|
downFocusRequester = nextUpEpisode?.let { playFocusRequester } ?: firstContentFocusRequester,
|
||||||
modifier = Modifier.align(Alignment.TopStart)
|
modifier = Modifier.align(Alignment.TopStart)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Episode.playButtonText(): String {
|
||||||
|
return if ((progress ?: 0.0) > 0.0 && !watched) "Resume" else "Play"
|
||||||
|
}
|
||||||
|
|||||||
@@ -114,6 +114,10 @@ class SeriesViewModel @Inject constructor(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onPlayEpisode(episodeId: UUID) {
|
||||||
|
navigationManager.navigate(Route.PlayerRoute(mediaId = episodeId.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
fun onBack() {
|
fun onBack() {
|
||||||
navigationManager.pop()
|
navigationManager.pop()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user