feat: add dedicated Mark as Watched button to details page (#958)

This commit is contained in:
MukeshCheekatla 2026-05-07 21:22:13 +05:30
parent fda5812060
commit 5ab7ea8dfc
3 changed files with 63 additions and 0 deletions

View file

@ -93,6 +93,7 @@ import com.nuvio.app.features.trailer.TrailerPlaybackSource
import com.nuvio.app.features.watched.WatchedRepository
import com.nuvio.app.features.watched.previousReleasedEpisodesBefore
import com.nuvio.app.features.watched.releasedEpisodesForSeason
import com.nuvio.app.features.watched.watchedItemKey
import com.nuvio.app.features.watchprogress.CurrentDateProvider
import com.nuvio.app.features.watchprogress.WatchProgressEntry
import com.nuvio.app.features.watchprogress.WatchProgressRepository
@ -662,10 +663,12 @@ fun MetaDetailsScreen(
isTablet = isTablet,
playButtonLabel = playButtonLabel,
isSaved = isSaved,
isMarkedAsWatched = watchedUiState.watchedKeys.contains(watchedItemKey(meta.type, meta.id)),
onPrimaryPlayClick = onPrimaryPlayClick,
onPrimaryPlayLongClick = onPrimaryPlayLongClick,
onSaveClick = toggleSaved,
onSaveLongClick = openLibraryListPicker,
onWatchedClick = { WatchingActions.toggleMetaWatched(meta) },
showManualPlayOption = showManualPlayOption,
preferredEpisodeSeasonNumber = seriesAction?.seasonNumber,
preferredEpisodeNumber = seriesAction?.episodeNumber,
@ -996,10 +999,12 @@ private fun ConfiguredMetaSections(
isTablet: Boolean,
playButtonLabel: String,
isSaved: Boolean,
isMarkedAsWatched: Boolean,
onPrimaryPlayClick: () -> Unit,
onPrimaryPlayLongClick: (() -> Unit)?,
onSaveClick: () -> Unit,
onSaveLongClick: (() -> Unit)?,
onWatchedClick: () -> Unit,
showManualPlayOption: Boolean,
preferredEpisodeSeasonNumber: Int?,
preferredEpisodeNumber: Int?,
@ -1062,11 +1067,13 @@ private fun ConfiguredMetaSections(
stringResource(Res.string.action_save)
},
isSaved = isSaved,
isWatched = isMarkedAsWatched,
isTablet = isTablet,
onPlayClick = onPrimaryPlayClick,
onPlayLongClick = if (showManualPlayOption) onPrimaryPlayLongClick else null,
onSaveClick = onSaveClick,
onSaveLongClick = onSaveLongClick,
onWatchedClick = onWatchedClick,
)
}
MetaScreenSectionKey.OVERVIEW -> {

View file

@ -13,6 +13,8 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material3.IconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
@ -37,11 +39,13 @@ fun DetailActionButtons(
playLabel: String = stringResource(Res.string.action_play),
saveLabel: String = stringResource(Res.string.action_save),
isSaved: Boolean = false,
isWatched: Boolean = false,
isTablet: Boolean = false,
onPlayClick: () -> Unit = {},
onPlayLongClick: (() -> Unit)? = null,
onSaveClick: () -> Unit = {},
onSaveLongClick: (() -> Unit)? = null,
onWatchedClick: () -> Unit = {},
) {
val playPainter = appIconPainter(AppIconResource.PlayerPlay)
val libraryAddPainter = appIconPainter(AppIconResource.LibraryAddPlus)
@ -138,5 +142,21 @@ fun DetailActionButtons(
)
}
}
Surface(
modifier = Modifier.size(50.dp),
shape = RoundedCornerShape(40.dp),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline),
color = if (isWatched) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface.copy(alpha = 0f),
contentColor = if (isWatched) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface,
) {
IconButton(onClick = onWatchedClick) {
Icon(
imageVector = Icons.Default.Visibility,
contentDescription = null,
modifier = Modifier.size(20.dp),
)
}
}
}
}

View file

@ -22,6 +22,42 @@ import kotlinx.coroutines.launch
object WatchingActions {
private val actionScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
fun toggleMetaWatched(meta: MetaDetails) {
if (meta.type != "series" && meta.type != "show" && meta.type != "tv") {
WatchedRepository.toggleWatched(
WatchedItem(
id = meta.id,
type = meta.type,
name = meta.name,
poster = meta.poster,
releaseInfo = meta.releaseInfo,
markedAtEpochMs = 0L
)
)
return
}
val isCurrentlyWatched = WatchedRepository.isWatched(
id = meta.id,
type = meta.type,
)
val todayIsoDate = CurrentDateProvider.todayIsoDate()
val seriesItems = buildList {
add(meta.toSeriesWatchedItem())
addAll(meta.releasedPlayableEpisodes(todayIsoDate).map(meta::toEpisodeWatchedItem))
}
if (isCurrentlyWatched) {
WatchedRepository.unmarkWatched(seriesItems)
} else {
WatchedRepository.markWatched(seriesItems)
WatchProgressRepository.clearProgress(
meta.releasedPlayableEpisodes(todayIsoDate).map(meta::episodePlaybackId),
)
}
}
suspend fun togglePosterWatched(preview: MetaPreview) {
if (preview.type != "series") {
WatchedRepository.toggleWatched(preview.toWatchedItem(markedAtEpochMs = 0L))