Add series link to episode top bar

This commit is contained in:
2026-03-17 19:10:48 +01:00
parent 92342f1f35
commit e37006486e
3 changed files with 52 additions and 0 deletions

View File

@@ -1,7 +1,10 @@
package hu.bbara.purefin.app.content.episode
import android.content.Intent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
@@ -13,6 +16,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.ArrowBack
@@ -28,8 +32,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import hu.bbara.purefin.common.ui.MediaCastRow
@@ -45,9 +51,12 @@ import hu.bbara.purefin.player.PlayerActivity
@Composable
internal fun EpisodeTopBar(
seriesTitle: String?,
onBack: () -> Unit,
onSeriesClick: () -> Unit,
modifier: Modifier = Modifier
) {
val scheme = MaterialTheme.colorScheme
Row(
modifier = modifier
.fillMaxWidth()
@@ -61,6 +70,30 @@ internal fun EpisodeTopBar(
contentDescription = "Back",
onClick = onBack
)
if (!seriesTitle.isNullOrBlank()) {
Box(
modifier = Modifier
.weight(1f)
.padding(horizontal = 12.dp),
contentAlignment = Alignment.Center
) {
Text(
text = seriesTitle,
color = scheme.onBackground,
fontSize = 14.sp,
fontWeight = FontWeight.SemiBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.clip(RoundedCornerShape(999.dp))
.background(scheme.background.copy(alpha = 0.65f))
.clickable(onClick = onSeriesClick)
.padding(horizontal = 16.dp, vertical = 10.dp)
)
}
} else {
Spacer(modifier = Modifier.weight(1f))
}
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = { })
GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = { })

View File

@@ -41,6 +41,7 @@ fun EpisodeScreen(
}
val episode = viewModel.episode.collectAsState()
val seriesTitle = viewModel.seriesTitle.collectAsState()
val downloadState = viewModel.downloadState.collectAsState()
val notificationPermissionLauncher = rememberLauncherForActivityResult(
@@ -67,8 +68,10 @@ fun EpisodeScreen(
EpisodeScreenInternal(
episode = episode.value!!,
seriesTitle = seriesTitle.value,
downloadState = downloadState.value,
onBack = viewModel::onBack,
onSeriesClick = viewModel::onSeriesClick,
onPlaybackStarted = viewModel::onPlaybackStarted,
onDownloadClick = onDownloadClick,
modifier = modifier
@@ -78,8 +81,10 @@ fun EpisodeScreen(
@Composable
private fun EpisodeScreenInternal(
episode: Episode,
seriesTitle: String?,
downloadState: DownloadState,
onBack: () -> Unit,
onSeriesClick: () -> Unit,
onPlaybackStarted: () -> Unit,
onDownloadClick: () -> Unit,
modifier: Modifier = Modifier,
@@ -90,7 +95,9 @@ private fun EpisodeScreenInternal(
containerColor = MaterialTheme.colorScheme.background,
topBar = {
EpisodeTopBar(
seriesTitle = seriesTitle,
onBack = onBack,
onSeriesClick = onSeriesClick,
modifier = Modifier
)
}

View File

@@ -37,6 +37,13 @@ class EpisodeScreenViewModel @Inject constructor(
id?.let { episodesMap[it] }
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)
val seriesTitle: StateFlow<String?> = combine(
_seriesId,
appContentRepository.series
) { seriesId, seriesMap ->
seriesId?.let { id -> seriesMap[id]?.name }
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)
private val _downloadState = MutableStateFlow<DownloadState>(DownloadState.NotDownloaded)
val downloadState: StateFlow<DownloadState> = _downloadState.asStateFlow()
@@ -55,6 +62,11 @@ class EpisodeScreenViewModel @Inject constructor(
navigationManager.navigate(Route.SeriesRoute(SeriesDto(id = seriesId)))
}
fun onSeriesClick() {
val seriesId = _seriesId.value ?: return
navigationManager.navigate(Route.SeriesRoute(SeriesDto(id = seriesId)))
}
fun selectEpisode(seriesId: UUID, seasonId: UUID, episodeId: UUID) {
_episodeId.value = episodeId
_seriesId.value = seriesId