Refactor CatalogScreen to use HomePosterCard

This commit is contained in:
AdityasahuX07 2026-05-14 16:26:46 +05:30 committed by GitHub
parent 37203d1fc1
commit 83eca2fade
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -33,7 +33,6 @@ import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -44,17 +43,14 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.nuvio.app.core.network.NetworkCondition import com.nuvio.app.core.network.NetworkCondition
import com.nuvio.app.core.network.NetworkStatusRepository import com.nuvio.app.core.network.NetworkStatusRepository
import com.nuvio.app.core.ui.NuvioNetworkOfflineCard import com.nuvio.app.core.ui.NuvioNetworkOfflineCard
import coil3.compose.AsyncImage
import com.nuvio.app.core.format.formatReleaseDateForDisplay
import com.nuvio.app.core.ui.NuvioBackButton import com.nuvio.app.core.ui.NuvioBackButton
import com.nuvio.app.core.ui.rememberPosterCardStyleUiState
import com.nuvio.app.core.ui.posterCardClickable
import com.nuvio.app.core.ui.nuvioSafeBottomPadding import com.nuvio.app.core.ui.nuvioSafeBottomPadding
import com.nuvio.app.core.ui.withDuplicateSafeLazyKeys import com.nuvio.app.core.ui.withDuplicateSafeLazyKeys
import com.nuvio.app.features.home.MetaPreview 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.home.stableKey
import com.nuvio.app.features.home.components.HomePosterCard
import com.nuvio.app.features.watched.WatchedRepository
import com.nuvio.app.features.watching.application.WatchingState
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@ -72,17 +68,20 @@ fun CatalogScreen(
genre: String? = null, genre: String? = null,
onBack: () -> Unit, onBack: () -> Unit,
onPosterClick: ((MetaPreview) -> Unit)? = null, onPosterClick: ((MetaPreview) -> Unit)? = null,
onPosterLongClick: ((MetaPreview) -> Unit)? = null,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val uiState by CatalogRepository.uiState.collectAsStateWithLifecycle() val uiState by CatalogRepository.uiState.collectAsStateWithLifecycle()
val homeCatalogSettingsUiState by HomeCatalogSettingsRepository.uiState.collectAsStateWithLifecycle()
val posterCardStyle = rememberPosterCardStyleUiState()
val networkStatusUiState by NetworkStatusRepository.uiState.collectAsStateWithLifecycle() val networkStatusUiState by NetworkStatusRepository.uiState.collectAsStateWithLifecycle()
val watchedUiState by remember {
WatchedRepository.ensureLoaded()
WatchedRepository.uiState
}.collectAsStateWithLifecycle()
val gridState = rememberLazyGridState() val gridState = rememberLazyGridState()
var headerHeightPx by remember { mutableIntStateOf(0) } var headerHeightPx by remember { mutableIntStateOf(0) }
var observedOfflineState by remember { mutableStateOf(false) } var observedOfflineState by remember { mutableStateOf(false) }
LaunchedEffect(manifestUrl, type, catalogId, genre, supportsPagination, homeCatalogSettingsUiState.hideUnreleasedContent) { LaunchedEffect(manifestUrl, type, catalogId, genre, supportsPagination) {
CatalogRepository.load( CatalogRepository.load(
manifestUrl = manifestUrl, manifestUrl = manifestUrl,
type = type, type = type,
@ -110,7 +109,7 @@ fun CatalogScreen(
when (networkStatusUiState.condition) { when (networkStatusUiState.condition) {
NetworkCondition.NoInternet, NetworkCondition.NoInternet,
NetworkCondition.ServersUnreachable, NetworkCondition.ServersUnreachable,
-> { -> {
observedOfflineState = true observedOfflineState = true
} }
@ -129,7 +128,7 @@ fun CatalogScreen(
NetworkCondition.Unknown, NetworkCondition.Unknown,
NetworkCondition.Checking, NetworkCondition.Checking,
-> Unit -> Unit
} }
} }
@ -156,7 +155,7 @@ fun CatalogScreen(
) { ) {
if (uiState.items.isEmpty() && uiState.isLoading) { if (uiState.items.isEmpty() && uiState.isLoading) {
items(columns * 3) { items(columns * 3) {
CatalogSkeletonTile(cornerRadiusDp = posterCardStyle.cornerRadiusDp) CatalogSkeletonTile()
} }
} else if (uiState.items.isEmpty()) { } else if (uiState.items.isEmpty()) {
item(span = { GridItemSpan(maxLineSpan) }) { item(span = { GridItemSpan(maxLineSpan) }) {
@ -182,11 +181,14 @@ fun CatalogScreen(
key = { item -> item.lazyKey }, key = { item -> item.lazyKey },
) { keyedItem -> ) { keyedItem ->
val item = keyedItem.value val item = keyedItem.value
CatalogPosterTile( HomePosterCard(
item = item, item = item,
cornerRadiusDp = posterCardStyle.cornerRadiusDp, isWatched = WatchingState.isPosterWatched(
hideLabels = posterCardStyle.hideLabelsEnabled, watchedKeys = watchedUiState.watchedKeys,
item = item,
),
onClick = onPosterClick?.let { { it(item) } }, onClick = onPosterClick?.let { { it(item) } },
onLongClick = onPosterLongClick?.let { { it(item) } },
) )
} }
if (uiState.isLoading) { if (uiState.isLoading) {
@ -252,63 +254,12 @@ private fun CatalogHeader(
} }
@Composable @Composable
private fun CatalogPosterTile( private fun CatalogSkeletonTile() {
item: MetaPreview,
cornerRadiusDp: Int,
hideLabels: Boolean,
onClick: (() -> Unit)? = null,
) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(item.posterShape.catalogAspectRatio())
.clip(RoundedCornerShape(cornerRadiusDp.dp))
.background(MaterialTheme.colorScheme.surface)
.posterCardClickable(onClick = onClick, onLongClick = null),
) {
if (item.poster != null) {
AsyncImage(
model = item.poster,
contentDescription = item.name,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
}
}
if (!hideLabels) {
Text(
text = item.name,
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
color = MaterialTheme.colorScheme.onBackground,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
val detail = item.releaseInfo?.let { formatReleaseDateForDisplay(it) }
if (detail != null) {
Text(
text = detail,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
} else {
Spacer(modifier = Modifier.height(8.dp))
}
}
}
}
@Composable
private fun CatalogSkeletonTile(cornerRadiusDp: Int) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.aspectRatio(0.68f) .aspectRatio(0.68f)
.clip(RoundedCornerShape(cornerRadiusDp.dp)) .clip(RoundedCornerShape(12.dp))
.background(MaterialTheme.colorScheme.surface), .background(MaterialTheme.colorScheme.surface),
) )
} }
@ -363,13 +314,6 @@ private fun CatalogLoadingFooter() {
} }
} }
private fun PosterShape.catalogAspectRatio(): Float =
when (this) {
PosterShape.Poster -> 0.68f
PosterShape.Square -> 1f
PosterShape.Landscape -> 1.2f
}
private fun catalogGridColumnsForWidth(screenWidth: Dp): Int = private fun catalogGridColumnsForWidth(screenWidth: Dp): Int =
when { when {
screenWidth >= 1400.dp -> 7 screenWidth >= 1400.dp -> 7