mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
Fix interactive episode navigation buttons
This commit is contained in:
@@ -34,6 +34,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||
import hu.bbara.purefin.core.data.client.JellyfinApiClient
|
||||
import hu.bbara.purefin.core.data.client.JellyfinAuthInterceptor
|
||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationBackStack
|
||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationManager
|
||||
import hu.bbara.purefin.core.data.navigation.NavigationCommand
|
||||
import hu.bbara.purefin.core.data.navigation.NavigationManager
|
||||
@@ -164,7 +165,10 @@ class TvActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalNavigationManager provides navigationManager) {
|
||||
CompositionLocalProvider(
|
||||
LocalNavigationManager provides navigationManager,
|
||||
LocalNavigationBackStack provides backStack.toList()
|
||||
) {
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
onBack = { navigationManager.pop() },
|
||||
|
||||
@@ -34,6 +34,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||
import hu.bbara.purefin.core.data.client.JellyfinApiClient
|
||||
import hu.bbara.purefin.core.data.client.JellyfinAuthInterceptor
|
||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationBackStack
|
||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationManager
|
||||
import hu.bbara.purefin.core.data.navigation.NavigationCommand
|
||||
import hu.bbara.purefin.core.data.navigation.NavigationManager
|
||||
@@ -165,7 +166,10 @@ class PurefinActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalNavigationManager provides navigationManager) {
|
||||
CompositionLocalProvider(
|
||||
LocalNavigationManager provides navigationManager,
|
||||
LocalNavigationBackStack provides backStack.toList()
|
||||
) {
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
onBack = { navigationManager.pop() },
|
||||
|
||||
@@ -16,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.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Add
|
||||
@@ -49,9 +50,23 @@ import hu.bbara.purefin.core.model.Episode
|
||||
import hu.bbara.purefin.feature.download.DownloadState
|
||||
import hu.bbara.purefin.player.PlayerActivity
|
||||
|
||||
internal sealed interface EpisodeTopBarShortcut {
|
||||
val label: String
|
||||
val onClick: () -> Unit
|
||||
|
||||
data class Series(override val onClick: () -> Unit) : EpisodeTopBarShortcut {
|
||||
override val label: String = "Series"
|
||||
}
|
||||
|
||||
data class Home(override val onClick: () -> Unit) : EpisodeTopBarShortcut {
|
||||
override val label: String = "Home"
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun EpisodeTopBar(
|
||||
seriesTitle: String?,
|
||||
shortcut: EpisodeTopBarShortcut?,
|
||||
onBack: () -> Unit,
|
||||
onSeriesClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
@@ -70,29 +85,50 @@ internal fun EpisodeTopBar(
|
||||
contentDescription = "Back",
|
||||
onClick = onBack
|
||||
)
|
||||
if (!seriesTitle.isNullOrBlank()) {
|
||||
when {
|
||||
shortcut != null -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(52.dp)
|
||||
.clickable(onClick = shortcut.onClick),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = shortcut.label,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.background(scheme.background.copy(alpha = 0.65f))
|
||||
.padding(horizontal = 16.dp, vertical = 10.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
!seriesTitle.isNullOrBlank() -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 12.dp),
|
||||
.height(52.dp)
|
||||
.clickable(onClick = onSeriesClick),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = seriesTitle,
|
||||
color = scheme.onBackground,
|
||||
fontSize = 14.sp,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(999.dp))
|
||||
.clip(CircleShape)
|
||||
.background(scheme.background.copy(alpha = 0.65f))
|
||||
.clickable(onClick = onSeriesClick)
|
||||
.padding(horizontal = 16.dp, vertical = 10.dp)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
else -> Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
GhostIconButton(icon = Icons.Outlined.Cast, contentDescription = "Cast", onClick = { })
|
||||
|
||||
@@ -15,12 +15,16 @@ import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||
import hu.bbara.purefin.common.ui.components.MediaHero
|
||||
import hu.bbara.purefin.core.data.navigation.EpisodeDto
|
||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationBackStack
|
||||
import hu.bbara.purefin.core.data.navigation.LocalNavigationManager
|
||||
import hu.bbara.purefin.core.data.navigation.Route
|
||||
import hu.bbara.purefin.core.model.Episode
|
||||
import hu.bbara.purefin.feature.download.DownloadState
|
||||
import hu.bbara.purefin.feature.shared.content.episode.EpisodeScreenViewModel
|
||||
@@ -31,6 +35,9 @@ fun EpisodeScreen(
|
||||
viewModel: EpisodeScreenViewModel = hiltViewModel(),
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val navigationManager = LocalNavigationManager.current
|
||||
val backStack = LocalNavigationBackStack.current
|
||||
val previousRoute = remember(backStack) { backStack.getOrNull(backStack.lastIndex - 1) }
|
||||
|
||||
LaunchedEffect(episode) {
|
||||
viewModel.selectEpisode(
|
||||
@@ -69,6 +76,15 @@ fun EpisodeScreen(
|
||||
EpisodeScreenInternal(
|
||||
episode = episode.value!!,
|
||||
seriesTitle = seriesTitle.value,
|
||||
topBarShortcut = remember(previousRoute) {
|
||||
when (previousRoute) {
|
||||
is Route.SeriesRoute -> EpisodeTopBarShortcut.Home {
|
||||
navigationManager.replaceAll(Route.Home)
|
||||
}
|
||||
Route.Home -> EpisodeTopBarShortcut.Series(viewModel::onSeriesClick)
|
||||
else -> null
|
||||
}
|
||||
},
|
||||
downloadState = downloadState.value,
|
||||
onBack = viewModel::onBack,
|
||||
onSeriesClick = viewModel::onSeriesClick,
|
||||
@@ -81,6 +97,7 @@ fun EpisodeScreen(
|
||||
private fun EpisodeScreenInternal(
|
||||
episode: Episode,
|
||||
seriesTitle: String?,
|
||||
topBarShortcut: EpisodeTopBarShortcut?,
|
||||
downloadState: DownloadState,
|
||||
onBack: () -> Unit,
|
||||
onSeriesClick: () -> Unit,
|
||||
@@ -94,6 +111,7 @@ private fun EpisodeScreenInternal(
|
||||
topBar = {
|
||||
EpisodeTopBar(
|
||||
seriesTitle = seriesTitle,
|
||||
shortcut = topBarShortcut,
|
||||
onBack = onBack,
|
||||
onSeriesClick = onSeriesClick,
|
||||
modifier = Modifier
|
||||
@@ -123,3 +141,5 @@ private fun EpisodeScreenInternal(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package hu.bbara.purefin.core.data.navigation
|
||||
|
||||
import androidx.compose.runtime.ProvidableCompositionLocal
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
@@ -43,3 +44,5 @@ class DefaultNavigationManager : NavigationManager {
|
||||
|
||||
val LocalNavigationManager: ProvidableCompositionLocal<NavigationManager> =
|
||||
staticCompositionLocalOf { error("NavigationManager not provided") }
|
||||
|
||||
val LocalNavigationBackStack = compositionLocalOf<List<Route>> { emptyList() }
|
||||
|
||||
@@ -5,6 +5,8 @@ import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import hu.bbara.purefin.core.data.AppContentRepository
|
||||
import hu.bbara.purefin.core.data.navigation.NavigationManager
|
||||
import hu.bbara.purefin.core.data.navigation.Route
|
||||
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
||||
import hu.bbara.purefin.core.model.Episode
|
||||
import hu.bbara.purefin.feature.download.DownloadState
|
||||
import hu.bbara.purefin.feature.download.MediaDownloadManager
|
||||
@@ -50,7 +52,8 @@ class EpisodeScreenViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun onSeriesClick() {
|
||||
navigationManager.pop()
|
||||
val seriesId = _seriesId.value ?: return
|
||||
navigationManager.navigate(Route.SeriesRoute(SeriesDto(id = seriesId)))
|
||||
}
|
||||
|
||||
fun selectEpisode(seriesId: UUID, seasonId: UUID, episodeId: UUID) {
|
||||
|
||||
Reference in New Issue
Block a user