Skip to content

Commit

Permalink
#71 Add trakt sync button to movie details screen
Browse files Browse the repository at this point in the history
  • Loading branch information
moallemi committed Jun 16, 2024
1 parent 6ee6790 commit 9739205
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 69 deletions.
6 changes: 4 additions & 2 deletions feature/movie-detail/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ android {
dependencies {

implementation(project(":data:model"))
implementation(project(":core:ui:common"))

implementation(project(":domain:tmdb-movies"))
implementation(project(":domain:stream"))
implementation(project(":domain:bookmarks"))
implementation(project(":data:trakt"))
implementation(project(":core:ui:common"))

implementation(project(":feature:trakt-buttons"))
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package io.filmtime.feature.movie.detail

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
Expand All @@ -23,9 +29,11 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
import io.filmtime.core.designsystem.composable.FilmTimeFilledTonalButton
import io.filmtime.core.designsystem.theme.FilmTimeTheme
import io.filmtime.core.designsystem.theme.PreviewFilmTimeTheme
import io.filmtime.core.designsystem.theme.ThemePreviews
Expand All @@ -37,9 +45,11 @@ import io.filmtime.data.model.Preview
import io.filmtime.data.model.PreviewCast
import io.filmtime.data.model.PreviewCrew
import io.filmtime.data.model.VideoDetail
import io.filmtime.data.model.VideoType
import io.filmtime.feature.movie.detail.components.VideoDescription
import io.filmtime.feature.movie.detail.components.VideoInfo
import io.filmtime.feature.movie.detail.components.VideoThumbnailInfo
import io.filmtime.feature.trakt.buttons.addremovehistory.TraktAddRemoveHistoryButton

@Composable
fun MovieDetailScreen(
Expand Down Expand Up @@ -83,6 +93,14 @@ fun MovieDetailScreen(
onSimilarRetry = viewModel::loadSimilar,
onAddBookmark = viewModel::addBookmark,
onRemoveBookmark = viewModel::removeBookmark,
traktHistoryButton = {
TraktAddRemoveHistoryButton(
modifier = Modifier
.weight(1f),
videoType = VideoType.Movie,
tmdbId = videoDetail.ids.tmdbId ?: 0,
)
},
)
}
}
Expand All @@ -98,39 +116,53 @@ private fun MovieDetailScreen(
onSimilarRetry: () -> Unit,
onAddBookmark: () -> Unit,
onRemoveBookmark: () -> Unit,
traktHistoryButton: @Composable RowScope.() -> Unit,
) {
var imageHeight by remember { mutableIntStateOf(4000) }
val density = LocalDensity.current
val boxHeight by remember(imageHeight) {
derivedStateOf {
with(density) {
(imageHeight + 150).toDp()
}
}
}
LazyColumn(
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
item {
Box {
var imageHeight by remember { mutableIntStateOf(500) }
AsyncImage(
FilmTimeTheme(
darkTheme = true,
) {
Box(
modifier = Modifier
.onGloballyPositioned {
imageHeight = it.size.height
}
.fillMaxWidth()
.aspectRatio(2 / 3f)
.drawWithCache {
val gradient = Brush.verticalGradient(
colors = listOf(Color.Transparent, Color(0x99000000), Color(0xDD000000)),
startY = imageHeight.toFloat() / 2,
endY = imageHeight.toFloat(),
)
// Draw the image
onDrawWithContent {
drawContent()
drawRect(gradient, blendMode = BlendMode.Multiply)
}
},
contentScale = ContentScale.Crop,
model = videoDetail.posterUrl,
contentDescription = "Poster Image",
)
FilmTimeTheme(
darkTheme = true,
.background(MaterialTheme.colorScheme.background)
.height(boxHeight),
) {
AsyncImage(
modifier = Modifier
.onGloballyPositioned {
imageHeight = it.size.height
}
.fillMaxWidth()
.aspectRatio(2 / 3f)
.drawWithCache {
val gradient = Brush.verticalGradient(
colors = listOf(Color.Transparent, Color(0x99000000), Color(0xDD000000)),
startY = imageHeight.toFloat() / 3,
endY = imageHeight.toFloat(),
)
// Draw the image
onDrawWithContent {
drawContent()
drawRect(gradient, blendMode = BlendMode.Multiply)
}
},
contentScale = ContentScale.Crop,
model = videoDetail.posterUrl,
contentDescription = "Poster Image",
)

VideoThumbnailInfo(
modifier = Modifier
.padding(16.dp)
Expand All @@ -139,6 +171,7 @@ private fun MovieDetailScreen(
isBookmarked = isBookmarked,
onAddBookmark = onAddBookmark,
onRemoveBookmark = onRemoveBookmark,
traktHistoryButton = traktHistoryButton,
)
}
}
Expand Down Expand Up @@ -198,6 +231,15 @@ private fun MovieDetailScreenPreview() {
onSimilarRetry = {},
onAddBookmark = {},
onRemoveBookmark = {},
traktHistoryButton = {
FilmTimeFilledTonalButton(
modifier = Modifier
.weight(1f),
onClick = {},
) {
Text("Add to history")
}
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import io.filmtime.core.ui.common.toUiMessage
import io.filmtime.data.model.Result.Failure
import io.filmtime.data.model.Result.Success
import io.filmtime.data.model.VideoType.Movie
import io.filmtime.data.trakt.TraktHistoryRepository
import io.filmtime.domain.bookmarks.AddBookmarkUseCase
import io.filmtime.domain.bookmarks.DeleteBookmarkUseCase
import io.filmtime.domain.bookmarks.ObserveBookmarkUseCase
Expand All @@ -32,7 +31,6 @@ class MovieDetailViewModel @Inject constructor(
private val getStreamInfo: GetStreamInfoUseCase,
private val getCredit: GetMovieCreditsUseCase,
private val getSimilar: GetSimilarUseCase,
private val traktHistoryRepository: TraktHistoryRepository,
private val addBookmark: AddBookmarkUseCase,
private val deleteBookmark: DeleteBookmarkUseCase,
private val observeBookmark: ObserveBookmarkUseCase,
Expand Down Expand Up @@ -124,18 +122,6 @@ class MovieDetailViewModel @Inject constructor(
.collect()
}

fun addItemToHistory() = viewModelScope.launch {
val traktId = _state.value.videoDetail?.ids?.traktId ?: return@launch
val result = traktHistoryRepository.addToHistory(traktId.toString())
when (result) {
is Failure -> TODO()
is Success -> {
val updated = _state.value.videoDetail?.copy(isWatched = true)
_state.value = _state.value.copy(videoDetail = updated)
}
}
}

private fun observeBookmark() = viewModelScope.launch {
observeBookmark(videoId, Movie)
.onEach { isBookmarked ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package io.filmtime.feature.movie.detail.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.Icons.Filled
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Icon
Expand Down Expand Up @@ -35,6 +36,7 @@ internal fun VideoThumbnailInfo(
modifier: Modifier = Modifier,
onAddBookmark: () -> Unit,
onRemoveBookmark: () -> Unit,
traktHistoryButton: @Composable RowScope.() -> Unit,
) {
Column(
modifier = modifier,
Expand Down Expand Up @@ -71,32 +73,17 @@ internal fun VideoThumbnailInfo(
) {
Text("Play")
}
Row {
if (isBookmarked) {
FilmTimeOutlinedButton(
onClick = onRemoveBookmark,
) {
Icon(
Icons.Filled.Check,
contentDescription = "",
modifier = Modifier.size(20.dp),
)
Spacer(modifier = Modifier.size(8.dp))
Text("Bookmarked")
}
} else {
FilmTimeFilledTonalButton(
onClick = onAddBookmark,
) {
Icon(
Icons.Filled.Add,
contentDescription = "",
modifier = Modifier.size(20.dp),
)
Spacer(modifier = Modifier.size(8.dp))
Text("Bookmark")
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
traktHistoryButton()
BookmarkButton(
modifier = Modifier
.weight(1f),
isBookmarked = isBookmarked,
onRemoveBookmark = onRemoveBookmark,
onAddBookmark = onAddBookmark,
)
}
ExpandableText(
text = videoDetail.description,
Expand All @@ -105,6 +92,42 @@ internal fun VideoThumbnailInfo(
}
}

@Composable
private fun BookmarkButton(
isBookmarked: Boolean,
onRemoveBookmark: () -> Unit,
onAddBookmark: () -> Unit,
modifier: Modifier = Modifier,
) {
if (isBookmarked) {
FilmTimeOutlinedButton(
modifier = modifier,
onClick = onRemoveBookmark,
) {
Icon(
Filled.Check,
contentDescription = "",
modifier = Modifier.size(20.dp),
)
Spacer(modifier = Modifier.size(8.dp))
Text("Bookmarked")
}
} else {
FilmTimeFilledTonalButton(
modifier = modifier,
onClick = onAddBookmark,
) {
Icon(
Filled.Add,
contentDescription = "",
modifier = Modifier.size(20.dp),
)
Spacer(modifier = Modifier.size(8.dp))
Text("Bookmark")
}
}
}

@ThemePreviews
@Composable
private fun MovieDetailScreenPreview() {
Expand All @@ -114,6 +137,15 @@ private fun MovieDetailScreenPreview() {
isBookmarked = false,
onAddBookmark = {},
onRemoveBookmark = {},
traktHistoryButton = {
FilmTimeFilledTonalButton(
modifier = Modifier
.weight(1f),
onClick = {},
) {
Text("Add to history")
}
},
)
}
}

0 comments on commit 9739205

Please sign in to comment.