@@ -5406,6 +5406,30 @@ private fun ContinueWatchingCard(
54065406 filterQuality = FilterQuality.Low,
54075407 modifier = Modifier.fillMaxSize()
54085408 )
5409+ } else {
5410+ Box(
5411+ modifier =
5412+ Modifier.fillMaxSize()
5413+ .background(
5414+ Brush.verticalGradient(
5415+ listOf(colors.surfaceAlt, colors.surface)
5416+ )
5417+ ),
5418+ contentAlignment = Alignment.Center
5419+ ) {
5420+ val placeholderIcon =
5421+ if (entry.resumeItem.contentType == ContentType.MOVIES) {
5422+ R.drawable.ic_category_movies
5423+ } else {
5424+ R.drawable.ic_category_series
5425+ }
5426+ Icon(
5427+ painter = painterResource(placeholderIcon),
5428+ contentDescription = null,
5429+ tint = colors.textSecondary.copy(alpha = 0.35f),
5430+ modifier = Modifier.size(48.dp)
5431+ )
5432+ }
54095433 }
54105434 if (isFavorite) {
54115435 FavoriteIndicator(modifier = Modifier.align(Alignment.TopEnd).padding(6.dp))
@@ -8744,6 +8768,24 @@ private data class ContinueWatchingDisplayEntry(
87448768 val timestampMs: Long
87458769)
87468770
8771+ private fun provisionalContinueWatchingSeriesParent(item: ContentItem): ContentItem? {
8772+ if (item.contentType != ContentType.SERIES || item.containerExtension.isNullOrBlank()) {
8773+ return null
8774+ }
8775+ val parentSeriesId = item.parentSeriesId?.takeUnless { it.isBlank() } ?: return null
8776+ val parentTitle = stripEpisodeSuffixes(item.title).takeUnless { it.isBlank() } ?: item.title
8777+ return item.copy(
8778+ id = parentSeriesId,
8779+ title = parentTitle,
8780+ subtitle = "",
8781+ section = Section.SERIES,
8782+ contentType = ContentType.SERIES,
8783+ streamId = parentSeriesId,
8784+ containerExtension = null,
8785+ parentSeriesId = null
8786+ )
8787+ }
8788+
87478789@Composable
87488790fun ContinueWatchingScreen(
87498791 title: String,
@@ -8781,9 +8823,8 @@ fun ContinueWatchingScreen(
87818823 remember { androidx.compose.runtime.mutableStateMapOf<String, Boolean>() }
87828824 val posterFontScale = remember(columns) { 4f / columns.toFloat() }
87838825 val resolvedParentsSnapshot = resolvedParents.toMap()
8784- val parentResolutionAttemptedSnapshot = parentResolutionAttempted.toMap()
87858826 val displayEntries =
8786- remember(continueWatchingItems, resolvedParentsSnapshot, parentResolutionAttemptedSnapshot ) {
8827+ remember(continueWatchingItems, resolvedParentsSnapshot) {
87878828 fun displayGroupingKey(entry: ContinueWatchingEntry): String {
87888829 val canonicalSeriesId =
87898830 entry.parentItem?.streamId?.takeUnless { it.isBlank() }
@@ -8820,17 +8861,11 @@ fun ContinueWatchingScreen(
88208861 }
88218862 .maxByOrNull { it.first }
88228863 ?.second
8823- val waitingForParentResolution =
8824- group.any { entry ->
8825- entry.item.contentType == ContentType.SERIES &&
8826- entry.parentItem == null &&
8827- !resolvedParentsSnapshot.containsKey(entry.key) &&
8828- parentResolutionAttemptedSnapshot[entry.key] != true
8829- }
8830- if (latestSeriesParent == null && waitingForParentResolution) {
8831- return@mapNotNull null
8832- }
8833- val displayItem = latestSeriesParent ?: latest.item
8864+ val provisionalSeriesParent =
8865+ latestSeriesParent
8866+ ?: latest.parentItem
8867+ ?: provisionalContinueWatchingSeriesParent(latest.item)
8868+ val displayItem = provisionalSeriesParent ?: latest.item
88348869 val resumeLabel =
88358870 if (latest.item.contentType == ContentType.SERIES) {
88368871 formatEpisodeLabel(latest.item, separator = " - ")?.let { "Resume $it" }
@@ -9210,6 +9245,10 @@ fun ContinueWatchingScreen(
92109245 val seriesItem =
92119246 resolvedParent
92129247 ?: entry.parentItem
9248+ ?: item.takeIf {
9249+ it.contentType == ContentType.SERIES &&
9250+ it.containerExtension.isNullOrBlank()
9251+ }
92139252 if (seriesItem != null) {
92149253 returnFocusItem = item
92159254 pendingResumeItem = entry.resumeItem
0 commit comments