mirror of
https://github.com/owenlejeune/TVTime.git
synced 2025-11-23 04:00:53 -05:00
add tv page
This commit is contained in:
@@ -26,6 +26,10 @@ class TmdbClient: KoinComponent {
|
|||||||
return client.create(MoviesApi::class.java)
|
return client.create(MoviesApi::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createTvService(): TvApi {
|
||||||
|
return client.create(TvApi::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
private inner class TmdbInterceptor: Interceptor {
|
private inner class TmdbInterceptor: Interceptor {
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
val apiParam = QueryParam("api_key", BuildConfig.TMDB_ApiKey)
|
val apiParam = QueryParam("api_key", BuildConfig.TMDB_ApiKey)
|
||||||
|
|||||||
13
app/src/main/java/com/owenlejeune/tvtime/api/tmdb/TvApi.kt
Normal file
13
app/src/main/java/com/owenlejeune/tvtime/api/tmdb/TvApi.kt
Normal 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>
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.owenlejeune.tvtime.api.tmdb.model
|
||||||
|
|
||||||
|
abstract class MediaItem(
|
||||||
|
open val posterPath: String?,
|
||||||
|
@Transient open val title: String
|
||||||
|
)
|
||||||
@@ -2,7 +2,7 @@ package com.owenlejeune.tvtime.api.tmdb.model
|
|||||||
|
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
class PopularMovie(
|
data class PopularMovie(
|
||||||
@SerializedName("poster_path") val posterPath: String?,
|
@SerializedName("poster_path") override val posterPath: String?,
|
||||||
@SerializedName("title") val title: String
|
@SerializedName("title") override val title: String
|
||||||
)
|
): MediaItem(posterPath, title)
|
||||||
@@ -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)
|
||||||
@@ -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>
|
||||||
|
)
|
||||||
@@ -19,7 +19,7 @@ fun <T: Any> LazyGridScope.items(
|
|||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
fun <T: Any> LazyGridScope.items(
|
fun <T: Any> LazyGridScope.items(
|
||||||
items: List<T>,
|
items: List<T>,
|
||||||
itemContent: @Composable (value: T?) -> Unit
|
itemContent: @Composable (value: T) -> Unit
|
||||||
) {
|
) {
|
||||||
items(items.size) { index ->
|
items(items.size) { index ->
|
||||||
itemContent(items[index])
|
itemContent(items[index])
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,68 +1,22 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens
|
package com.owenlejeune.tvtime.ui.screens
|
||||||
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
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.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.MoviesService
|
||||||
import com.owenlejeune.tvtime.api.tmdb.model.PopularMovie
|
import com.owenlejeune.tvtime.ui.components.PosterGrid
|
||||||
import com.owenlejeune.tvtime.extensions.dpToPx
|
|
||||||
import com.owenlejeune.tvtime.extensions.items
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun MoviesTab() {
|
fun MoviesTab() {
|
||||||
val context = LocalContext.current
|
|
||||||
// val moviesViewModel = viewModel(PopularMovieViewModel::class.java)
|
// val moviesViewModel = viewModel(PopularMovieViewModel::class.java)
|
||||||
// val moviesList = moviesViewModel.moviePage
|
// val moviesList = moviesViewModel.moviePage
|
||||||
// val movieListItems: LazyPagingItems<PopularMovie> = moviesList.collectAsLazyPagingItems()
|
// val movieListItems: LazyPagingItems<PopularMovie> = moviesList.collectAsLazyPagingItems()
|
||||||
val moviesList = remember { mutableStateOf(emptyList<PopularMovie>()) }
|
PosterGrid { moviesList ->
|
||||||
val service = MoviesService()
|
val service = MoviesService()
|
||||||
service.getPopularMovies { isSuccessful, response ->
|
service.getPopularMovies { isSuccessful, response ->
|
||||||
if (isSuccessful) {
|
if (isSuccessful) {
|
||||||
moviesList.value = response!!.movies
|
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()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,19 @@
|
|||||||
package com.owenlejeune.tvtime.ui.screens
|
package com.owenlejeune.tvtime.ui.screens
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
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.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import com.owenlejeune.tvtime.api.tmdb.TvService
|
||||||
import androidx.compose.ui.Modifier
|
import com.owenlejeune.tvtime.ui.components.PosterGrid
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun TvTab() {
|
fun TvTab() {
|
||||||
Column(
|
PosterGrid { tvList ->
|
||||||
modifier = Modifier
|
val service = TvService()
|
||||||
.fillMaxSize()
|
service.getPopularTv { isSuccessful, response ->
|
||||||
.wrapContentSize(Alignment.Center)
|
if (isSuccessful) {
|
||||||
) {
|
tvList.value = response!!.tv
|
||||||
Text(
|
}
|
||||||
text = "TV Tab",
|
}
|
||||||
color = MaterialTheme.colorScheme.onBackground
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user