mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 23:12:12 +00:00
Merge b3cca180db into 37203d1fc1
This commit is contained in:
commit
ba99c69007
6 changed files with 136 additions and 0 deletions
|
|
@ -38,6 +38,7 @@ import com.nuvio.app.core.format.formatReleaseDateForDisplay
|
|||
import com.nuvio.app.features.home.MetaPreview
|
||||
import kotlinx.coroutines.launch
|
||||
import nuvio.composeapp.generated.resources.Res
|
||||
import nuvio.composeapp.generated.resources.action_saved
|
||||
import nuvio.composeapp.generated.resources.episodes_cd_watched
|
||||
import nuvio.composeapp.generated.resources.hero_add_to_library
|
||||
import nuvio.composeapp.generated.resources.hero_mark_unwatched
|
||||
|
|
@ -151,6 +152,41 @@ fun NuvioAnimatedWatchedBadge(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NuvioBookmarkedBadge(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(22.dp)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.primary),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Bookmark,
|
||||
contentDescription = stringResource(Res.string.action_saved),
|
||||
tint = MaterialTheme.colorScheme.onPrimary,
|
||||
modifier = Modifier.size(12.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NuvioAnimatedBookmarkedBadge(
|
||||
isVisible: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = isVisible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
NuvioBookmarkedBadge()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PosterSheetHeader(
|
||||
item: MetaPreview,
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ fun NuvioPosterCard(
|
|||
bottomLeftLogoUrl: String? = null,
|
||||
bottomLeftText: String? = null,
|
||||
isWatched: Boolean = false,
|
||||
isSaved: Boolean = false,
|
||||
onClick: (() -> Unit)? = null,
|
||||
onLongClick: (() -> Unit)? = null,
|
||||
) {
|
||||
|
|
@ -185,6 +186,13 @@ fun NuvioPosterCard(
|
|||
.align(Alignment.TopEnd)
|
||||
.padding(6.dp),
|
||||
)
|
||||
|
||||
NuvioAnimatedBookmarkedBadge(
|
||||
isVisible = isSaved,
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.padding(6.dp),
|
||||
)
|
||||
}
|
||||
if (shouldShowTitleBelow) {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ import com.nuvio.app.core.network.NetworkStatusRepository
|
|||
import com.nuvio.app.core.ui.NuvioNetworkOfflineCard
|
||||
import coil3.compose.AsyncImage
|
||||
import com.nuvio.app.core.format.formatReleaseDateForDisplay
|
||||
import com.nuvio.app.core.ui.NuvioAnimatedBookmarkedBadge
|
||||
import com.nuvio.app.core.ui.NuvioAnimatedWatchedBadge
|
||||
import com.nuvio.app.core.ui.NuvioBackButton
|
||||
import com.nuvio.app.core.ui.rememberPosterCardStyleUiState
|
||||
import com.nuvio.app.core.ui.posterCardClickable
|
||||
|
|
@ -55,6 +57,9 @@ import com.nuvio.app.features.home.MetaPreview
|
|||
import com.nuvio.app.features.home.HomeCatalogSettingsRepository
|
||||
import com.nuvio.app.features.home.PosterShape
|
||||
import com.nuvio.app.features.home.stableKey
|
||||
import com.nuvio.app.features.library.LibraryRepository
|
||||
import com.nuvio.app.features.watched.WatchedRepository
|
||||
import com.nuvio.app.features.watching.application.WatchingState
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -81,6 +86,11 @@ fun CatalogScreen(
|
|||
val gridState = rememberLazyGridState()
|
||||
var headerHeightPx by remember { mutableIntStateOf(0) }
|
||||
var observedOfflineState by remember { mutableStateOf(false) }
|
||||
val libraryUiState by remember {
|
||||
LibraryRepository.ensureLoaded()
|
||||
LibraryRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(manifestUrl, type, catalogId, genre, supportsPagination, homeCatalogSettingsUiState.hideUnreleasedContent) {
|
||||
CatalogRepository.load(
|
||||
|
|
@ -182,10 +192,24 @@ fun CatalogScreen(
|
|||
key = { item -> item.lazyKey },
|
||||
) { keyedItem ->
|
||||
val item = keyedItem.value
|
||||
val isSaved = remember(
|
||||
libraryUiState.items,
|
||||
libraryUiState.sections,
|
||||
libraryUiState.sourceMode,
|
||||
item.id,
|
||||
item.type,
|
||||
) {
|
||||
LibraryRepository.isSaved(item.id, item.type)
|
||||
}
|
||||
CatalogPosterTile(
|
||||
item = item,
|
||||
cornerRadiusDp = posterCardStyle.cornerRadiusDp,
|
||||
hideLabels = posterCardStyle.hideLabelsEnabled,
|
||||
isSaved = isSaved,
|
||||
isWatched = WatchingState.isPosterWatched(
|
||||
watchedKeys = watchedUiState.watchedKeys,
|
||||
item = item,
|
||||
),
|
||||
onClick = onPosterClick?.let { { it(item) } },
|
||||
)
|
||||
}
|
||||
|
|
@ -256,6 +280,8 @@ private fun CatalogPosterTile(
|
|||
item: MetaPreview,
|
||||
cornerRadiusDp: Int,
|
||||
hideLabels: Boolean,
|
||||
isWatched: Boolean = false,
|
||||
isSaved: Boolean = false,
|
||||
onClick: (() -> Unit)? = null,
|
||||
) {
|
||||
Column(
|
||||
|
|
@ -277,6 +303,20 @@ private fun CatalogPosterTile(
|
|||
contentScale = ContentScale.Crop,
|
||||
)
|
||||
}
|
||||
|
||||
NuvioAnimatedWatchedBadge(
|
||||
isVisible = isWatched,
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.padding(6.dp),
|
||||
)
|
||||
|
||||
NuvioAnimatedBookmarkedBadge(
|
||||
isVisible = isSaved,
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.padding(6.dp),
|
||||
)
|
||||
}
|
||||
if (!hideLabels) {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import com.nuvio.app.core.ui.NuvioPosterCard
|
||||
import com.nuvio.app.core.ui.NuvioPosterShape
|
||||
|
|
@ -61,6 +62,9 @@ import com.nuvio.app.features.home.PosterShape
|
|||
import com.nuvio.app.features.home.canOpenCatalog
|
||||
import com.nuvio.app.features.home.stableKey
|
||||
import com.nuvio.app.features.home.components.HomeCatalogRowSection
|
||||
import com.nuvio.app.features.library.LibraryRepository
|
||||
import com.nuvio.app.features.watched.WatchedRepository
|
||||
import com.nuvio.app.features.watching.application.WatchingState
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -204,6 +208,11 @@ private fun TabbedGridContent(
|
|||
onPosterClick: (MetaPreview) -> Unit,
|
||||
) {
|
||||
val gridState = rememberLazyGridState()
|
||||
val libraryUiState by remember {
|
||||
LibraryRepository.ensureLoaded()
|
||||
LibraryRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(gridState, uiState.selectedTabIndex, uiState.selectedTabCanLoadMore, uiState.selectedTabIsLoadingMore) {
|
||||
snapshotFlow { gridState.layoutInfo }
|
||||
|
|
@ -280,11 +289,25 @@ private fun TabbedGridContent(
|
|||
key = { item -> item.lazyKey },
|
||||
) { keyedItem ->
|
||||
val item = keyedItem.value
|
||||
val isSaved = remember(
|
||||
libraryUiState.items,
|
||||
libraryUiState.sections,
|
||||
libraryUiState.sourceMode,
|
||||
item.id,
|
||||
item.type,
|
||||
) {
|
||||
LibraryRepository.isSaved(item.id, item.type)
|
||||
}
|
||||
NuvioPosterCard(
|
||||
title = item.name,
|
||||
imageUrl = item.poster,
|
||||
shape = NuvioPosterShape.Poster,
|
||||
detailLine = item.releaseInfo,
|
||||
isWatched = WatchingState.isPosterWatched(
|
||||
watchedKeys = watchedUiState.watchedKeys,
|
||||
item = item,
|
||||
),
|
||||
isSaved = isSaved,
|
||||
onClick = { onPosterClick(item) },
|
||||
)
|
||||
}
|
||||
|
|
@ -309,6 +332,7 @@ private fun RowsContent(
|
|||
onPosterClick: (MetaPreview) -> Unit,
|
||||
) {
|
||||
val sections = FolderDetailRepository.getCatalogSectionsForRows()
|
||||
val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
if (uiState.isLoading && sections.isEmpty()) {
|
||||
LoadingIndicator()
|
||||
|
|
@ -335,6 +359,7 @@ private fun RowsContent(
|
|||
HomeCatalogRowSection(
|
||||
section = section,
|
||||
entries = section.items.take(18),
|
||||
watchedKeys = watchedUiState.watchedKeys,
|
||||
onViewAllClick = if (section.canOpenCatalog(18)) {
|
||||
{ onCatalogClick(section) }
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
package com.nuvio.app.features.home.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.nuvio.app.core.format.formatReleaseDateForDisplay
|
||||
import com.nuvio.app.core.ui.NuvioPosterCard
|
||||
import com.nuvio.app.core.ui.NuvioPosterShape
|
||||
import com.nuvio.app.core.ui.rememberPosterCardStyleUiState
|
||||
import com.nuvio.app.features.home.MetaPreview
|
||||
import com.nuvio.app.features.home.PosterShape
|
||||
import com.nuvio.app.features.library.LibraryRepository
|
||||
|
||||
@Composable
|
||||
fun HomePosterCard(
|
||||
|
|
@ -18,6 +22,19 @@ fun HomePosterCard(
|
|||
onClick: (() -> Unit)? = null,
|
||||
onLongClick: (() -> Unit)? = null,
|
||||
) {
|
||||
val libraryUiState by remember {
|
||||
LibraryRepository.ensureLoaded()
|
||||
LibraryRepository.uiState
|
||||
}.collectAsStateWithLifecycle()
|
||||
val isSaved = remember(
|
||||
libraryUiState.items,
|
||||
libraryUiState.sections,
|
||||
libraryUiState.sourceMode,
|
||||
item.id,
|
||||
item.type,
|
||||
) {
|
||||
LibraryRepository.isSaved(item.id, item.type)
|
||||
}
|
||||
val posterCardStyle = rememberPosterCardStyleUiState()
|
||||
val isLandscapeMode = useLandscapeBackdropMode || posterCardStyle.catalogLandscapeModeEnabled
|
||||
|
||||
|
|
@ -31,6 +48,7 @@ fun HomePosterCard(
|
|||
bottomLeftLogoUrl = if (isLandscapeMode) item.logo else null,
|
||||
bottomLeftText = if (isLandscapeMode && item.logo.isNullOrBlank() && !posterCardStyle.hideLabelsEnabled) item.name else null,
|
||||
isWatched = isWatched,
|
||||
isSaved = isSaved,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import com.nuvio.app.features.home.components.HomeEmptyStateCard
|
|||
import com.nuvio.app.features.home.components.HomePosterCard
|
||||
import com.nuvio.app.features.home.components.HomeSkeletonRow
|
||||
import com.nuvio.app.features.profiles.ProfileRepository
|
||||
import com.nuvio.app.features.watched.WatchedRepository
|
||||
import com.nuvio.app.features.watching.application.WatchingState
|
||||
import kotlinx.coroutines.launch
|
||||
import nuvio.composeapp.generated.resources.*
|
||||
import org.jetbrains.compose.resources.getString
|
||||
|
|
@ -64,6 +66,7 @@ fun LibraryScreen(
|
|||
LibraryRepository.pullFromServer(ProfileRepository.activeProfileId)
|
||||
}
|
||||
}
|
||||
val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(networkStatusUiState.condition, isTraktSource) {
|
||||
when (networkStatusUiState.condition) {
|
||||
|
|
@ -170,6 +173,7 @@ fun LibraryScreen(
|
|||
|
||||
else -> {
|
||||
librarySections(
|
||||
watchedKeys = watchedUiState.watchedKeys,
|
||||
sections = uiState.sections,
|
||||
onPosterClick = onPosterClick,
|
||||
onSectionViewAllClick = onSectionViewAllClick,
|
||||
|
|
@ -228,6 +232,7 @@ fun LibraryScreen(
|
|||
|
||||
private fun LazyListScope.librarySections(
|
||||
sections: List<LibrarySection>,
|
||||
watchedKeys: Set<String>,
|
||||
onPosterClick: ((LibraryItem) -> Unit)?,
|
||||
onSectionViewAllClick: ((LibrarySection) -> Unit)?,
|
||||
onPosterLongClick: (LibraryItem, LibrarySection) -> Unit,
|
||||
|
|
@ -251,6 +256,10 @@ private fun LazyListScope.librarySections(
|
|||
key = { item -> "${item.type}:${item.id}" },
|
||||
) { item ->
|
||||
HomePosterCard(
|
||||
isWatched = WatchingState.isPosterWatched(
|
||||
watchedKeys = watchedKeys,
|
||||
item = item.toMetaPreview(),
|
||||
),
|
||||
item = item.toMetaPreview(),
|
||||
onClick = onPosterClick?.let { { it(item) } },
|
||||
onLongClick = { onPosterLongClick(item, section) },
|
||||
|
|
|
|||
Loading…
Reference in a new issue