add tv page

This commit is contained in:
Owen LeJeune
2022-02-10 00:45:48 -05:00
parent 05afce953e
commit 09982636b2
11 changed files with 154 additions and 73 deletions

View File

@@ -26,6 +26,10 @@ class TmdbClient: KoinComponent {
return client.create(MoviesApi::class.java)
}
fun createTvService(): TvApi {
return client.create(TvApi::class.java)
}
private inner class TmdbInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val apiParam = QueryParam("api_key", BuildConfig.TMDB_ApiKey)

View File

@@ -0,0 +1,13 @@
package com.owenlejeune.tvtime.api.tmdb
import com.owenlejeune.tvtime.api.tmdb.model.PopularTvResponse
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface TvApi {
@GET("tv/popular")
fun getPoplarTv(@Query("page") page: Int = 1): Call<PopularTvResponse>
}

View File

@@ -0,0 +1,28 @@
package com.owenlejeune.tvtime.api.tmdb
import com.owenlejeune.tvtime.api.tmdb.model.PopularTvResponse
import org.koin.core.component.KoinComponent
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class TvService: KoinComponent {
private val service by lazy { TmdbClient().createTvService() }
fun getPopularTv(page: Int = 1, callback: (isSuccessful: Boolean, response: PopularTvResponse?) -> Unit) {
service.getPoplarTv(page = page).enqueue(object : Callback<PopularTvResponse> {
override fun onResponse(call: Call<PopularTvResponse>, response: Response<PopularTvResponse>) {
response.body()?.let { body ->
callback.invoke(true, body)
} ?: run {
callback.invoke(false, null)
}
}
override fun onFailure(call: Call<PopularTvResponse>, t: Throwable) {
callback.invoke(false, null)
}
})
}
}

View File

@@ -0,0 +1,6 @@
package com.owenlejeune.tvtime.api.tmdb.model
abstract class MediaItem(
open val posterPath: String?,
@Transient open val title: String
)

View File

@@ -2,7 +2,7 @@ package com.owenlejeune.tvtime.api.tmdb.model
import com.google.gson.annotations.SerializedName
class PopularMovie(
@SerializedName("poster_path") val posterPath: String?,
@SerializedName("title") val title: String
)
data class PopularMovie(
@SerializedName("poster_path") override val posterPath: String?,
@SerializedName("title") override val title: String
): MediaItem(posterPath, title)

View File

@@ -0,0 +1,8 @@
package com.owenlejeune.tvtime.api.tmdb.model
import com.google.gson.annotations.SerializedName
data class PopularTv(
@SerializedName("poster_path") override val posterPath: String?,
@SerializedName("name") val name: String
): MediaItem(posterPath, name)

View File

@@ -0,0 +1,9 @@
package com.owenlejeune.tvtime.api.tmdb.model
import com.google.gson.annotations.SerializedName
data class PopularTvResponse(
@SerializedName("total_results") val count: Int,
@SerializedName("page") val page: Int,
@SerializedName("results") val tv: List<PopularTv>
)

View File

@@ -19,7 +19,7 @@ fun <T: Any> LazyGridScope.items(
@OptIn(ExperimentalFoundationApi::class)
fun <T: Any> LazyGridScope.items(
items: List<T>,
itemContent: @Composable (value: T?) -> Unit
itemContent: @Composable (value: T) -> Unit
) {
items(items.size) { index ->
itemContent(items[index])

View File

@@ -0,0 +1,64 @@
package com.owenlejeune.tvtime.ui.components
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.runtime.Composable
import com.owenlejeune.tvtime.api.tmdb.model.MediaItem
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import coil.compose.rememberImagePainter
import coil.transform.RoundedCornersTransformation
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.extensions.dpToPx
import com.owenlejeune.tvtime.extensions.items
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PosterGrid(fetchMedia: (MutableState<List<MediaItem>>) -> Unit) {
val mediaList = remember { mutableStateOf(emptyList<MediaItem>()) }
fetchMedia(mediaList)
LazyVerticalGrid(
cells = GridCells.Fixed(count = 3),
contentPadding = PaddingValues(8.dp)
) {
items(mediaList.value) { item ->
PosterItem(mediaItem = item)
}
}
}
@Composable
fun PosterItem(mediaItem: MediaItem) {
val context = LocalContext.current
val poster = "https://image.tmdb.org/t/p/original${mediaItem.posterPath}"
Image(
painter = rememberImagePainter(
data = poster,
builder = {
transformations(RoundedCornersTransformation(5f.dpToPx(context)))
placeholder(R.drawable.placeholder)
}
),
contentDescription = mediaItem.title,
modifier = Modifier
.size(190.dp)
.padding(5.dp)
.clickable {
Toast
.makeText(context, "${mediaItem.title} clicked", Toast.LENGTH_SHORT)
.show()
}
)
}

View File

@@ -1,68 +1,22 @@
package com.owenlejeune.tvtime.ui.screens
import android.widget.Toast
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import coil.compose.rememberImagePainter
import coil.transform.RoundedCornersTransformation
import com.owenlejeune.tvtime.R
import com.owenlejeune.tvtime.api.tmdb.MoviesService
import com.owenlejeune.tvtime.api.tmdb.model.PopularMovie
import com.owenlejeune.tvtime.extensions.dpToPx
import com.owenlejeune.tvtime.extensions.items
import com.owenlejeune.tvtime.ui.components.PosterGrid
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MoviesTab() {
val context = LocalContext.current
// val moviesViewModel = viewModel(PopularMovieViewModel::class.java)
// val moviesList = moviesViewModel.moviePage
// val movieListItems: LazyPagingItems<PopularMovie> = moviesList.collectAsLazyPagingItems()
val moviesList = remember { mutableStateOf(emptyList<PopularMovie>()) }
PosterGrid { moviesList ->
val service = MoviesService()
service.getPopularMovies { isSuccessful, response ->
if (isSuccessful) {
moviesList.value = response!!.movies
}
}
LazyVerticalGrid(
cells = GridCells.Fixed(count = 3),
contentPadding = PaddingValues(8.dp)
) {
// items(movieListItems) { item ->
items(moviesList.value) { item ->
val poster = item?.let { i ->
"https://image.tmdb.org/t/p/original${i.posterPath}"
}
Image(
painter = rememberImagePainter(
data = poster,
builder = {
transformations(RoundedCornersTransformation(5f.dpToPx(context)))
placeholder(R.drawable.placeholder)
}
),
contentDescription = item?.title,
modifier = Modifier
.size(190.dp)
.padding(5.dp)
.clickable {
Toast.makeText(context, "${item?.title} clicked", Toast.LENGTH_SHORT).show()
}
)
}
}
}

View File

@@ -1,24 +1,19 @@
package com.owenlejeune.tvtime.ui.screens
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.owenlejeune.tvtime.api.tmdb.TvService
import com.owenlejeune.tvtime.ui.components.PosterGrid
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun TvTab() {
Column(
modifier = Modifier
.fillMaxSize()
.wrapContentSize(Alignment.Center)
) {
Text(
text = "TV Tab",
color = MaterialTheme.colorScheme.onBackground
)
PosterGrid { tvList ->
val service = TvService()
service.getPopularTv { isSuccessful, response ->
if (isSuccessful) {
tvList.value = response!!.tv
}
}
}
}