Skip to content

Commit

Permalink
#16 Add ability to sync show episodes with trakt
Browse files Browse the repository at this point in the history
  • Loading branch information
moallemi committed Jul 7, 2024
1 parent 536190a commit 03b98b0
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ internal fun ShowDetailScreen(
onAddBookmark = viewModel::addBookmark,
onRemoveBookmark = viewModel::removeBookmark,
onSeasonChange = viewModel::changeSeason,
addToHistory = viewModel::addEpisodeToHistory,
removeFromHistory = viewModel::removeEpisodeFromHistory,
)
}

Expand All @@ -68,6 +70,8 @@ private fun ShowDetailScreen(
onAddBookmark: () -> Unit,
onRemoveBookmark: () -> Unit,
onSeasonChange: (Int) -> Unit,
addToHistory: (EpisodeThumbnail) -> Unit,
removeFromHistory: (EpisodeThumbnail) -> Unit,
) {
val videoDetail = state.videoDetail

Expand All @@ -91,6 +95,8 @@ private fun ShowDetailScreen(
onRemoveBookmark = onRemoveBookmark,
seasonsState = state.seasonsState,
onSeasonChange = onSeasonChange,
addToHistory = addToHistory,
removeFromHistory = removeFromHistory,
credits = {
CreditsRow(
tmdbId = videoDetail.ids.tmdbId ?: 0,
Expand All @@ -117,6 +123,8 @@ private fun ShowDetailContent(
onAddBookmark: () -> Unit,
onRemoveBookmark: () -> Unit,
onSeasonChange: (Int) -> Unit,
addToHistory: (EpisodeThumbnail) -> Unit,
removeFromHistory: (EpisodeThumbnail) -> Unit,
credits: @Composable () -> Unit,
similar: @Composable () -> Unit,
) {
Expand Down Expand Up @@ -176,6 +184,8 @@ private fun ShowDetailContent(
error = seasonsState.error,
onSeasonChange = onSeasonChange,
onRetryClick = onSeasonChange,
addToHistory = addToHistory,
removeFromHistory = removeFromHistory,
)
}
item(
Expand Down Expand Up @@ -223,6 +233,8 @@ private fun ShowDetailScreenPreview() {
),
),
onSeasonChange = {},
addToHistory = {},
removeFromHistory = {},
credits = {
Text("Credit goes here")
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import io.filmtime.core.ui.common.toUiMessage
import io.filmtime.data.model.EpisodeThumbnail
import io.filmtime.data.model.Result.Failure
import io.filmtime.data.model.Result.Success
import io.filmtime.data.model.VideoType.Show
import io.filmtime.domain.bookmarks.AddBookmarkUseCase
import io.filmtime.domain.bookmarks.DeleteBookmarkUseCase
import io.filmtime.domain.bookmarks.ObserveBookmarkUseCase
import io.filmtime.domain.tmdb.shows.GetEpisodesBySeasonUseCase
import io.filmtime.domain.tmdb.shows.GetShowDetailsUseCase
import io.filmtime.domain.trakt.GetRatingsUseCase
import io.filmtime.domain.trakt.history.AddEpisodeToHistoryUseCase
import io.filmtime.domain.trakt.history.IsShowWatchedUseCase
import io.filmtime.domain.trakt.history.RemoveEpisodeFromHistoryUseCase
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collect
Expand All @@ -31,6 +36,8 @@ internal class ShowDetailViewModel @Inject constructor(
private val getRatings: GetRatingsUseCase,
private val getEpisodesBySeason: GetEpisodesBySeasonUseCase,
private val isShowWatched: IsShowWatchedUseCase,
private val addToHistory: AddEpisodeToHistoryUseCase,
private val removeFromHistory: RemoveEpisodeFromHistoryUseCase,
) : ViewModel() {

private val videoId: Int = savedStateHandle["video_id"] ?: throw IllegalStateException("videoId is required")
Expand Down Expand Up @@ -137,4 +144,120 @@ internal class ShowDetailViewModel @Inject constructor(
loadEpisodesBySeason(seasonNumber)
}
}

fun addEpisodeToHistory(episodeThumbnail: EpisodeThumbnail) = viewModelScope.launch {
_state.update { state ->
state.copy(
seasonsState = state.seasonsState.copy(
seasons = state.seasonsState.seasons.mapValues { seasons ->
seasons.value.map { episode ->
if (episode.episodeNumber == episodeThumbnail.episodeNumber) {
episode.copy(isLoading = true)
} else {
episode
}
}
},
),
)
}

when (
addToHistory(
tmdbId = videoId,
seasonNumber = episodeThumbnail.seasonNumber,
episodeNumber = episodeThumbnail.episodeNumber,
)
) {
is Success -> _state.update { state ->
state.copy(
seasonsState = state.seasonsState.copy(
seasons = state.seasonsState.seasons.mapValues { seasons ->
seasons.value.map { episode ->
if (episode.episodeNumber == episodeThumbnail.episodeNumber) {
episode.copy(isLoading = false, isWatched = true)
} else {
episode
}
}
},
),
)
}

is Failure -> _state.update { state ->
state.copy(
seasonsState = state.seasonsState.copy(
seasons = state.seasonsState.seasons.mapValues { seasons ->
seasons.value.map { episode ->
if (episode.episodeNumber == episodeThumbnail.episodeNumber) {
episode.copy(isLoading = false, isWatched = false)
} else {
episode
}
}
},
),
)
}
}
}

fun removeEpisodeFromHistory(episodeThumbnail: EpisodeThumbnail) = viewModelScope.launch {
_state.update { state ->
state.copy(
seasonsState = state.seasonsState.copy(
seasons = state.seasonsState.seasons.mapValues { seasons ->
seasons.value.map { episode ->
if (episode.episodeNumber == episodeThumbnail.episodeNumber) {
episode.copy(isLoading = true)
} else {
episode
}
}
},
),
)
}

when (
removeFromHistory(
tmdbId = videoId,
seasonNumber = episodeThumbnail.seasonNumber,
episodeNumber = episodeThumbnail.episodeNumber,
)
) {
is Success -> _state.update { state ->
state.copy(
seasonsState = state.seasonsState.copy(
seasons = state.seasonsState.seasons.mapValues { seasons ->
seasons.value.map { episode ->
if (episode.episodeNumber == episodeThumbnail.episodeNumber) {
episode.copy(isLoading = false, isWatched = false)
} else {
episode
}
}
},
),
)
}

is Failure -> _state.update { state ->
state.copy(
seasonsState = state.seasonsState.copy(
seasons = state.seasonsState.seasons.mapValues { seasons ->
seasons.value.map { episode ->
if (episode.episodeNumber == episodeThumbnail.episodeNumber) {
episode.copy(isLoading = false, isWatched = true)
} else {
episode
}
}
},
),
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package io.filmtime.feature.show.detail.components

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Card
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
Expand All @@ -27,11 +36,14 @@ import io.filmtime.data.model.EpisodeThumbnail
import io.filmtime.data.model.Preview
import io.filmtime.feature.show.detail.R

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun EpisodeThumbnailCard(
modifier: Modifier = Modifier,
episodeThumbnail: EpisodeThumbnail,
placeHolderVisible: Boolean = false,
placeHolderVisible: Boolean,
addToHistory: (EpisodeThumbnail) -> Unit,
removeFromHistory: (EpisodeThumbnail) -> Unit,
) {
if (placeHolderVisible) {
ElevatedCard(
Expand All @@ -43,13 +55,36 @@ fun EpisodeThumbnailCard(
)
}
} else {
var expanded by remember { mutableStateOf(false) }
Card(
modifier = modifier,
modifier = modifier
.combinedClickable(
onClick = { /* Handle click */ },
onLongClick = { expanded = true },
),
) {
CardContent(
episodeThumbnail = episodeThumbnail,
placeHolderVisible = placeHolderVisible,
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
DropdownMenuItem(
onClick = {
if (episodeThumbnail.isWatched) {
removeFromHistory(episodeThumbnail)
} else {
addToHistory(episodeThumbnail)
}
expanded = false
},
text = {
Text(text = if (episodeThumbnail.isWatched) "Mark As Unwatched" else "Mark As Watched")
},
)
}
}
}
}
Expand All @@ -76,7 +111,8 @@ private fun CardContent(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp, bottom = 4.dp)
.padding(horizontal = 12.dp),
.padding(horizontal = 12.dp)
.height(24.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
Expand Down Expand Up @@ -134,6 +170,9 @@ private fun Preview() {
PreviewFilmTimeTheme {
EpisodeThumbnailCard(
episodeThumbnail = EpisodeThumbnail.Preview,
placeHolderVisible = false,
addToHistory = {},
removeFromHistory = {},
)
}
}
Expand All @@ -145,6 +184,8 @@ private fun PreviewLoading() {
EpisodeThumbnailCard(
episodeThumbnail = EpisodeThumbnail.Preview,
placeHolderVisible = true,
addToHistory = {},
removeFromHistory = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ internal fun SeasonsSection(
onSeasonChange: (Int) -> Unit,
error: UiMessage? = null,
onRetryClick: (Int) -> Unit,
addToHistory: (EpisodeThumbnail) -> Unit,
removeFromHistory: (EpisodeThumbnail) -> Unit,
) {
var selectedSeason by rememberSaveable { mutableIntStateOf(1) }
val lazyListState = rememberLazyListState()
Expand Down Expand Up @@ -86,6 +88,8 @@ internal fun SeasonsSection(
.width(300.dp),
episodeThumbnail = EpisodeThumbnail.Preview,
placeHolderVisible = true,
addToHistory = {},
removeFromHistory = {},
)
}
}
Expand All @@ -108,6 +112,9 @@ internal fun SeasonsSection(
modifier = Modifier
.width(300.dp),
episodeThumbnail = item,
placeHolderVisible = item.isLoading,
addToHistory = addToHistory,
removeFromHistory = removeFromHistory,
)
}
}
Expand All @@ -129,6 +136,8 @@ private fun SeasonsSectionPreview() {
onSeasonChange = {},
error = null,
onRetryClick = {},
addToHistory = {},
removeFromHistory = {},
)

Spacer(modifier = Modifier.padding(16.dp))
Expand All @@ -144,6 +153,8 @@ private fun SeasonsSectionPreview() {
onSeasonChange = {},
error = null,
onRetryClick = {},
addToHistory = {},
removeFromHistory = {},
)
}
}
Expand Down

0 comments on commit 03b98b0

Please sign in to comment.