Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beautify show detail page #62

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions app/src/main/java/io/filmtime/ui/navigation/FilmTimeNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fun FilmTimeNavHost(
nestedGraphs = { rootRoute ->
videoThumbnailGridScreen(rootRoute, navController)
movieDetailScreen(rootRoute, navController)
showDetailScreen(rootRoute)
showDetailScreen(rootRoute, navController)
playerScreen(rootRoute)
},
)
Expand Down Expand Up @@ -85,7 +85,7 @@ fun FilmTimeNavHost(
},
nestedGraphs = { rootRoute ->
videoThumbnailGridScreen(rootRoute, navController)
showDetailScreen(rootRoute = rootRoute)
showDetailScreen(rootRoute = rootRoute, navController)
playerScreen(rootRoute = rootRoute)
},
)
Expand Down Expand Up @@ -119,7 +119,20 @@ private fun NavGraphBuilder.movieDetailScreen(
rootRoute = rootRoute,
onStreamReady = navController::navigateToPlayer,
onCastItemClick = { _, _ -> },
onMovieClick = navController::navigateToMovieDetail,
onSimilarClick = navController::navigateToMovieDetail,
onBack = navController::popBackStack,
)
}

private fun NavGraphBuilder.showDetailScreen(
rootRoute: DestinationRoute,
navController: NavHostController,
) {
showDetailScreen(
rootRoute = rootRoute,
onStreamReady = navController::navigateToPlayer,
onCastItemClick = { _, _ -> },
onSimilarClick = navController::navigateToMovieDetail,
onBack = navController::popBackStack,
)
}
Expand Down
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ plugins {
alias(libs.plugins.com.android.library) apply false
alias(libs.plugins.kotlinx.serialization) apply false
alias(libs.plugins.ksp) apply false

alias(libs.plugins.spotless)
alias(libs.plugins.hilt.android) apply false
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.filmtime.core.ui.common.componnents

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import io.filmtime.data.model.CreditItem

@Composable
fun CreditRowItem(item: CreditItem) {
Column(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(horizontal = 6.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
AsyncImage(
modifier = Modifier
.size(60.dp)
.clip(CircleShape) // clip to the circle shape
.border(1.dp, Color.Transparent, CircleShape),
contentScale = ContentScale.Crop,
model = item.profile,
contentDescription = "credit_profile",
alignment = Alignment.Center,
)
Text(
text = item.name,
style = TextStyle(
fontWeight = FontWeight.Light,
fontSize = 10.sp,
color = Color.Black,
),
modifier = Modifier.padding(vertical = 4.dp),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import io.filmtime.core.ui.common.graphics.shimmerBrush
@Composable
fun LoadingVideoSectionRow(
numberOfSections: Int,
modifier: Modifier = Modifier,
) {
LazyColumn(
modifier = modifier,
contentPadding = PaddingValues(top = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.filmtime.data.api.tmdb

import io.filmtime.data.model.CreditItem
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.VideoDetail
Expand Down Expand Up @@ -29,6 +30,9 @@ interface TmdbShowsRemoteSource {
page: Int,
): Result<List<VideoThumbnail>, GeneralError>

suspend fun getCredit(movieId: Int): Result<List<CreditItem>, GeneralError>
suspend fun getSimilar(movieId: Int): Result<List<VideoThumbnail>, GeneralError>

companion object {
const val PAGE_SIZE = 20 // TMDB API default page size
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.filmtime.data.api.tmdb

import io.filmtime.data.model.CreditItem
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.VideoDetail
import io.filmtime.data.model.VideoThumbnail
import io.filmtime.data.network.TmdbCreditsResponse
import io.filmtime.data.network.TmdbErrorResponse
import io.filmtime.data.network.TmdbShowListResponse
import io.filmtime.data.network.TmdbShowsService
Expand Down Expand Up @@ -75,6 +77,30 @@ class TmdbShowsRemoteSourceImpl @Inject constructor(
)
}

override suspend fun getCredit(seriesId: Int): Result<List<CreditItem>, GeneralError> =
getCredits { tmdbShowsService.getCredit(seriesId) }

override suspend fun getSimilar(seriesId: Int): Result<List<VideoThumbnail>, GeneralError> =
getShowsList { tmdbShowsService.getSimilar(seriesId) }

private suspend fun getCredits(
apiFunction: suspend () -> NetworkResponse<TmdbCreditsResponse, TmdbErrorResponse>,
): Result<List<CreditItem>, GeneralError> =
when (val result = apiFunction()) {
is NetworkResponse.Success -> {
val creditResponse = result.body?.cast ?: emptyList()
Result.Success(creditResponse.map { it.toCreditItem() })
}

is NetworkResponse.ApiError -> {
val errorResponse = result.body
Result.Failure(GeneralError.ApiError(errorResponse.statusMessage, errorResponse.statusCode))
}

is NetworkResponse.NetworkError -> Result.Failure(GeneralError.NetworkError)
is NetworkResponse.UnknownError -> Result.Failure(GeneralError.UnknownError(result.error))
}

private suspend fun getShowsList(
apiCall: suspend () -> NetworkResponse<TmdbShowListResponse, TmdbErrorResponse>,
): Result<List<VideoThumbnail>, GeneralError> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ fun TmdbShowDetailsResponse.toVideoDetail() =
spokenLanguages = spokenLanguages?.map { it.englishName ?: "" }?.filter { it.isNotEmpty() }
?: listOf(),
description = overview ?: "",
runtime = "",
releaseDate = "",
runtime = episodeRunTime?.firstOrNull()?.let { fromMinutesToHHmm(it) } ?: "N/A",
releaseDate = firstAirDate?.split("-")?.get(0) ?: "N/A",
voteAverage = voteAverage?.div(10)?.toFloat() ?: 0.0F,
voteColor = voteAverage.toRatingColor(),
)

fun TmdbVideoResultResponse.toVideoThumbnail() = VideoThumbnail(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,14 @@ interface TmdbShowsService {
@Query("page") page: Int,
@Query("timezone") timezone: String,
): NetworkResponse<TmdbShowListResponse, TmdbErrorResponse>

@GET("tv/{series_id}/credits")
suspend fun getCredit(
@Path("series_id") seriesId: Int,
): NetworkResponse<TmdbCreditsResponse, TmdbErrorResponse>

@GET("tv/{series_id}/similar")
suspend fun getSimilar(
@Path("series_id") seriesId: Int,
): NetworkResponse<TmdbShowListResponse, TmdbErrorResponse>
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.filmtime.data.tmdb.shows

import androidx.paging.PagingData
import io.filmtime.data.model.CreditItem
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.VideoDetail
Expand All @@ -22,6 +23,10 @@ interface TmdbShowsRepository {
suspend fun airingTodayShows(): Result<List<VideoThumbnail>, GeneralError>

fun showsStream(type: ShowListType): Flow<PagingData<VideoThumbnail>>

suspend fun getCredit(movieId: Int): Result<List<CreditItem>, GeneralError>

suspend fun getSimilar(movieId: Int): Result<List<VideoThumbnail>, GeneralError>
}

enum class ShowListType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import io.filmtime.data.api.tmdb.TmdbShowsRemoteSource
import io.filmtime.data.model.CreditItem
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.VideoDetail
Expand Down Expand Up @@ -48,4 +49,10 @@ internal class TmdbShowsRepositoryImpl @Inject constructor(
)
},
).flow

override suspend fun getCredit(movieId: Int): Result<List<CreditItem>, GeneralError> =
tmdbShowsRemoteSource.getCredit(movieId)

override suspend fun getSimilar(movieId: Int): Result<List<VideoThumbnail>, GeneralError> =
tmdbShowsRemoteSource.getSimilar(movieId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.filmtime.domain.tmdb.shows

import io.filmtime.data.model.CreditItem
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result

interface GetShowCreditUseCase {
suspend operator fun invoke(movieId: Int): Result<List<CreditItem>, GeneralError>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.filmtime.domain.tmdb.shows

import io.filmtime.data.model.CreditItem
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.tmdb.shows.TmdbShowsRepository
import javax.inject.Inject

class GetShowCreditUseCaseImpl @Inject constructor(
private val tmdbMovieRepository: TmdbShowsRepository,
) : GetShowCreditUseCase {
override suspend fun invoke(
movieId: Int,
): Result<List<CreditItem>, GeneralError> = tmdbMovieRepository.getCredit(movieId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.filmtime.domain.tmdb.shows

import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.VideoThumbnail

interface GetSimilarUseCase {

suspend operator fun invoke(movieId: Int): Result<List<VideoThumbnail>, GeneralError>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.filmtime.domain.tmdb.shows

import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.VideoThumbnail
import io.filmtime.data.tmdb.shows.TmdbShowsRepository
import javax.inject.Inject

class GetSimilarUseCaseImpl @Inject constructor(private val tmdbMovieRepository: TmdbShowsRepository) :
GetSimilarUseCase {
override suspend fun invoke(movieId: Int): Result<List<VideoThumbnail>, GeneralError> =
tmdbMovieRepository.getSimilar(movieId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ internal abstract class TmdbShowsDomainModule {

@Binds
abstract fun bindGetShowsListUseCase(impl: GetShowsListUseCaseImpl): GetShowsListUseCase

@Binds
abstract fun bindGetShowCredit(impl: GetShowCreditUseCaseImpl): GetShowCreditUseCase

@Binds
abstract fun bindGetSimilar(impl: GetSimilarUseCaseImpl): GetSimilarUseCase
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fun NavGraphBuilder.movieDetailScreen(
rootRoute: DestinationRoute,
onStreamReady: (DestinationRoute, streamUrl: String) -> Unit,
onCastItemClick: (DestinationRoute, castId: Long) -> Unit,
onMovieClick: (DestinationRoute, tmdbId: Int) -> Unit,
onSimilarClick: (DestinationRoute, tmdbId: Int) -> Unit,
onBack: () -> Unit,
) {
composable(
Expand All @@ -27,7 +27,7 @@ fun NavGraphBuilder.movieDetailScreen(
viewModel = hiltViewModel(),
onStreamReady = { onStreamReady(rootRoute, it) },
onCastItemClick = { onCastItemClick(rootRoute, it) },
onMovieClick = { onMovieClick(rootRoute, it) },
onSimilarClick = { onSimilarClick(rootRoute, it) },
onBackPressed = onBack,
)
}
Expand Down
Loading