Skip to content

Commit

Permalink
Add feature images to detail screen
Browse files Browse the repository at this point in the history
  • Loading branch information
sLee0306 committed Feb 10, 2024
1 parent 0f8e1ad commit 7866462
Show file tree
Hide file tree
Showing 25 changed files with 464 additions and 43 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dependencies {
implementation project(path: BuildModules.FEATURE_PAGING)
implementation project(path: BuildModules.FEATURE_DETAIL)
implementation project(path: BuildModules.FEATURE_CREDIT)
implementation project(path: BuildModules.FEATURE_IMAGE)

implementation Deps.material
implementation Deps.composeMaterial
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/java/com/sample/tmdb/ui/TMDbApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ import com.sample.tmdb.detail.MovieDetailScreen
import com.sample.tmdb.detail.TVShowDetailScreen
import com.sample.tmdb.domain.model.Cast
import com.sample.tmdb.domain.model.Crew
import com.sample.tmdb.domain.model.TMDbImage
import com.sample.tmdb.feed.MovieFeedScreen
import com.sample.tmdb.feed.TVShowFeedScreen
import com.sample.tmdb.image.ImagesScreen
import com.sample.tmdb.paging.AiringTodayTVShowScreen
import com.sample.tmdb.paging.DiscoverMovieScreen
import com.sample.tmdb.paging.DiscoverTVShowScreen
Expand Down Expand Up @@ -92,6 +94,7 @@ fun TMDbApp() {
onAllCastSelected = appState::navigateToCastList,
onAllCrewSelected = appState::navigateToCrewList,
onCreditSelected = appState::navigateToPerson,
onImagesSelected = appState::navigateToImages,
upPress = appState::upPress
)
moviePagingScreens(
Expand All @@ -114,6 +117,7 @@ fun TMDbApp() {
upPress = appState::upPress
)
personScreen(upPress = appState::upPress)
imagesScreen()
}
}
}
Expand Down Expand Up @@ -192,6 +196,7 @@ private fun NavGraphBuilder.detailScreens(
onAllCastSelected: (String) -> Unit,
onAllCrewSelected: (String) -> Unit,
onCreditSelected: (String) -> Unit,
onImagesSelected: (String, Int) -> Unit,
upPress: () -> Unit
) {
composable(
Expand All @@ -209,6 +214,11 @@ private fun NavGraphBuilder.detailScreens(
)
}, onCreditSelected = {
onCreditSelected(it)
}, onImagesSelected = { images, index ->
onImagesSelected(
Uri.encode(gson.toJson(images, object : TypeToken<List<TMDbImage>>() {}.type)),
index
)
})
}
composable(
Expand All @@ -226,6 +236,11 @@ private fun NavGraphBuilder.detailScreens(
)
}, onCreditSelected = {
onCreditSelected(it)
}, onImagesSelected = { images, index ->
onImagesSelected(
Uri.encode(gson.toJson(images, object : TypeToken<List<TMDbImage>>() {}.type)),
index
)
})
}
}
Expand Down Expand Up @@ -393,6 +408,24 @@ private fun NavGraphBuilder.personScreen(
}
}

private fun NavGraphBuilder.imagesScreen() {
composable(
route = "${MainDestinations.TMDB_IMAGES_ROUTE}/{${MainDestinations.TMDB_IMAGES_KEY}}/{${MainDestinations.TMDB_IMAGE_ID}}",
arguments = listOf(
navArgument(MainDestinations.TMDB_IMAGES_KEY) { type = NavType.StringType },
navArgument(MainDestinations.TMDB_IMAGE_ID) { type = NavType.IntType }
)
) { from ->
ImagesScreen(
images = gson.fromJson(
from.arguments?.getString(MainDestinations.TMDB_IMAGES_KEY),
object : TypeToken<List<TMDbImage>>() {}.type
),
initialPage = from.arguments?.getInt(MainDestinations.TMDB_IMAGE_ID)!!
)
}
}

enum class HomeSections(
val route: String,
@StringRes val title: Int,
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/com/sample/tmdb/ui/TMDbAppState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ class TMDbAppState(
fun navigateToSearchTVShow() {
navController.navigate(MainDestinations.TMDB_SEARCH_TV_SHOW_ROUTE)
}

fun navigateToImages(images: String, id: Int) {
navController.navigate("${MainDestinations.TMDB_IMAGES_ROUTE}/$images/$id")
}

}

private val NavGraph.startDestination: NavDestination?
Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/java/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ object BuildModules {
const val FEATURE_PAGING = ":features:feature-paging"
const val FEATURE_DETAIL = ":features:feature-detail"
const val FEATURE_CREDIT = ":features:feature-credit"
const val FEATURE_IMAGE = ":features:feature-image"
}

object Deps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ object MainDestinations {
const val TMDB_CREDIT_KEY = "credit_list"
const val TMDB_PERSON_ROUTE = "person"
const val TMDB_PERSON_KEY = "personId"
const val TMDB_IMAGES_ROUTE = "image"
const val TMDB_IMAGES_KEY = "imagesKey"
const val TMDB_IMAGE_ID = "imageId"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.sample.tmdb.common.utils
object Constants {
const val BASE_WIDTH_342_PATH = "http://image.tmdb.org/t/p/w342%s"
const val BASE_WIDTH_780_PATH = "http://image.tmdb.org/t/p/w780%s"
const val BASE_IMAGE_PATH = "https://image.tmdb.org/t/p/original%s"
const val ID = "id"
const val NAME = "name"
const val TITLE = "title"
Expand Down
1 change: 1 addition & 0 deletions common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
<string name="back">Back</string>

<string name="person_content_description">Photo of %1$s the %2$s</string>
<string name="poster_content_description">Poster</string>
</resources>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sample.tmdb.data.network

import com.sample.tmdb.data.response.ImagesResponse
import com.sample.tmdb.data.response.MovieDetailResponse
import com.sample.tmdb.data.response.NetworkCreditWrapper
import com.sample.tmdb.data.response.NetworkMovie
Expand Down Expand Up @@ -57,4 +58,7 @@ interface MovieService {
@Query("page") page: Int,
@Query("query") query: String
): TMDbWrapper<NetworkMovie>

@GET("3/movie/{movie_id}/images")
suspend fun fetchImages(@Path("movie_id") movieId: Int): ImagesResponse
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sample.tmdb.data.network

import com.sample.tmdb.data.response.ImagesResponse
import com.sample.tmdb.data.response.NetworkCreditWrapper
import com.sample.tmdb.data.response.NetworkTVShow
import com.sample.tmdb.data.response.TMDbWrapper
Expand Down Expand Up @@ -49,12 +50,15 @@ interface TVShowService {
@GET("3/tv/{tvId}/credits")
suspend fun tvCredit(@Path("tvId") tvId: Int): NetworkCreditWrapper

@GET("3/tv/{tv_id}")
suspend fun fetchTvDetail(@Path("tv_id") tvId: Int): TvDetailResponse
@GET("3/tv/{tvId}")
suspend fun fetchTvDetail(@Path("tvId") tvId: Int): TvDetailResponse

@GET("3/search/tv")
suspend fun searchTVSeries(
@Query("page") page: Int,
@Query("query") query: String
): TMDbWrapper<NetworkTVShow>

@GET("3/tv/{tvId}/images")
suspend fun fetchImages(@Path("tvId") tvId: Int): ImagesResponse
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.sample.tmdb.data.repository

import android.content.Context
import com.sample.tmdb.data.di.IoDispatcher
import com.sample.tmdb.data.network.MovieService
import com.sample.tmdb.data.response.asCastDomainModel
import com.sample.tmdb.data.response.asCrewDomainModel
import com.sample.tmdb.data.response.asDomainModel
import com.sample.tmdb.data.di.IoDispatcher
import com.sample.tmdb.domain.model.Cast
import com.sample.tmdb.domain.model.Crew
import com.sample.tmdb.domain.model.MovieDetails
import com.sample.tmdb.domain.model.TMDbImage
import com.sample.tmdb.domain.repository.BaseDetailRepository
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
Expand All @@ -32,4 +33,7 @@ class MovieDetailRepository @Inject constructor(
networkCreditWrapper.crew.asCrewDomainModel()
)
}

override suspend fun getImages(id: Int): List<TMDbImage> =
movieApi.fetchImages(id).asDomainModel()
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package com.sample.tmdb.data.repository

import android.content.Context
import com.sample.tmdb.data.di.IoDispatcher
import com.sample.tmdb.data.network.TVShowService
import com.sample.tmdb.data.response.asCastDomainModel
import com.sample.tmdb.data.response.asCrewDomainModel
import com.sample.tmdb.data.response.asDomainModel
import com.sample.tmdb.data.di.IoDispatcher
import com.sample.tmdb.domain.model.Cast
import com.sample.tmdb.domain.model.Crew
import com.sample.tmdb.domain.repository.BaseDetailRepository
import com.sample.tmdb.domain.model.TMDbImage
import com.sample.tmdb.domain.model.TvDetails
import com.sample.tmdb.domain.repository.BaseDetailRepository
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import javax.inject.Inject
Expand All @@ -32,4 +33,7 @@ class TVShowDetailRepository @Inject constructor(
networkCreditWrapper.crew.asCrewDomainModel()
)
}

override suspend fun getImages(id: Int): List<TMDbImage> =
tvShowApi.fetchImages(id).asDomainModel()
}
30 changes: 30 additions & 0 deletions core/data/src/main/java/com/sample/tmdb/data/response/ImageDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sample.tmdb.data.response

import com.sample.tmdb.common.utils.Constants.BASE_IMAGE_PATH
import com.sample.tmdb.domain.model.TMDbImage
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
data class ImagesResponse(
@Json(name = "backdrops") val backdrops: List<ImageResponse>,
@Json(name = "id") val id: Int,
@Json(name = "posters") val posters: List<ImageResponse>,
)

@JsonClass(generateAdapter = true)
data class ImageResponse(
@Json(name = "aspect_ratio") val aspectRatio: Double,
@Json(name = "file_path") val filePath: String,
@Json(name = "height") val height: Int,
@Json(name = "iso_639_1") val iso6391: String?,
@Json(name = "vote_average") val voteAverage: Double,
@Json(name = "vote_count") val voteCount: Int,
@Json(name = "width") val width: Int,
)

fun ImagesResponse.asDomainModel(): List<TMDbImage> = buildList {
addAll(backdrops.map { TMDbImage(String.format(BASE_IMAGE_PATH, it.filePath), it.voteCount) })
addAll(posters.map { TMDbImage(String.format(BASE_IMAGE_PATH, it.filePath), it.voteCount) })
sortByDescending { it.voteCount }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ package com.sample.tmdb.domain.model
class DetailWrapper<T : TMDbItemDetails>(
val cast: List<Cast>,
val crew: List<Crew>,
val details: T
val details: T,
val images: List<TMDbImage>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.sample.tmdb.domain.model

data class TMDbImage(val url: String, val voteCount: Int)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.sample.tmdb.common.base.BaseRepository
import com.sample.tmdb.domain.model.Cast
import com.sample.tmdb.domain.model.Crew
import com.sample.tmdb.domain.model.DetailWrapper
import com.sample.tmdb.domain.model.TMDbImage
import com.sample.tmdb.domain.model.TMDbItemDetails
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Deferred
Expand All @@ -20,16 +21,21 @@ abstract class BaseDetailRepository<T : TMDbItemDetails>(

protected abstract suspend fun getCredit(id: Int): Pair<List<Cast>, List<Crew>>

protected abstract suspend fun getImages(id: Int): List<TMDbImage>

override suspend fun getSuccessResult(id: Any?): DetailWrapper<T> {
val detailsDeferred: Deferred<T>
val creditDeferred: Deferred<Pair<List<Cast>, List<Crew>>>
val imageDeferred: Deferred<List<TMDbImage>>
coroutineScope {
detailsDeferred = async { getDetails(id as Int) }
creditDeferred = async { getCredit(id as Int) }
imageDeferred= async { getImages(id as Int) }
}
val details = detailsDeferred.await()
val creditWrapper = creditDeferred.await()
val images = imageDeferred.await()

return DetailWrapper(creditWrapper.first, creditWrapper.second, details)
return DetailWrapper(creditWrapper.first, creditWrapper.second, details, images)
}
}
Loading

0 comments on commit 7866462

Please sign in to comment.