diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt index d8bfbf27..cd25e0ea 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/MetaDetailsScreen.kt @@ -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 -> { diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt index d5be0d59..5e43d842 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/details/components/DetailActionButtons.kt @@ -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), + ) + } + } } } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt index 4a79954e..b228cd3e 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watching/application/WatchingActions.kt @@ -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))