From 1dcad82c4bb1343c8766faf0d5d02af1c96660b2 Mon Sep 17 00:00:00 2001 From: Pramod Bharti Date: Thu, 12 Oct 2023 21:40:00 +0530 Subject: [PATCH] refactor --- .../com/pramodbharti/filmo/MainActivity.kt | 9 +- .../pramodbharti/filmo/dummydata/DummyData.kt | 66 +++++ .../filmo/ui/components/CarouselItem.kt | 95 +++++++ .../filmo/ui/components/CastItemsRow.kt | 65 +++++ .../home => components}/FilmoCarousel.kt | 4 +- .../filmo/ui/components/MediaItemsRow.kt | 52 ++++ .../pramodbharti/filmo/ui/components/Slots.kt | 28 ++ .../filmo/ui/components/TagItemsRow.kt | 45 +++ .../filmo/ui/models/FavoriteItems.kt | 5 + .../ui/models/{MovieItem.kt => MediaItem.kt} | 2 +- .../pramodbharti/filmo/ui/models/Movies.kt | 9 + .../pramodbharti/filmo/ui/models/TvShows.kt | 9 + .../pramodbharti/filmo/ui/screens/FilmoApp.kt | 23 ++ .../filmo/ui/screens/details/DetailsScreen.kt | 159 ++--------- .../filmo/ui/screens/home/HomeScreen.kt | 263 ------------------ .../filmo/ui/screens/home/MovieUiState.kt | 9 - .../filmo/ui/screens/movies/MoviesScreen.kt | 56 ++++ .../filmo/ui/screens/movies/MoviesUiState.kt | 9 + .../MoviesViewModel.kt} | 19 +- 19 files changed, 495 insertions(+), 432 deletions(-) create mode 100644 app/src/main/java/com/pramodbharti/filmo/dummydata/DummyData.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/components/CarouselItem.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/components/CastItemsRow.kt rename app/src/main/java/com/pramodbharti/filmo/ui/{screens/home => components}/FilmoCarousel.kt (97%) create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/components/MediaItemsRow.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/components/Slots.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/components/TagItemsRow.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/models/FavoriteItems.kt rename app/src/main/java/com/pramodbharti/filmo/ui/models/{MovieItem.kt => MediaItem.kt} (91%) create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/models/Movies.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/models/TvShows.kt delete mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeScreen.kt delete mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/screens/home/MovieUiState.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesScreen.kt create mode 100644 app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesUiState.kt rename app/src/main/java/com/pramodbharti/filmo/ui/screens/{home/HomeViewModel.kt => movies/MoviesViewModel.kt} (72%) diff --git a/app/src/main/java/com/pramodbharti/filmo/MainActivity.kt b/app/src/main/java/com/pramodbharti/filmo/MainActivity.kt index f0e73dd..c0eca5c 100644 --- a/app/src/main/java/com/pramodbharti/filmo/MainActivity.kt +++ b/app/src/main/java/com/pramodbharti/filmo/MainActivity.kt @@ -1,5 +1,6 @@ package com.pramodbharti.filmo +import FilmoApp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent @@ -7,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.pramodbharti.filmo.ui.theme.FilmoTheme class MainActivity : ComponentActivity() { @@ -15,11 +17,8 @@ class MainActivity : ComponentActivity() { setContent { FilmoTheme { // A surface container using the 'background' color from the theme - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.background - ) { - + Surface(tonalElevation = 5.dp) { + FilmoApp() } } } diff --git a/app/src/main/java/com/pramodbharti/filmo/dummydata/DummyData.kt b/app/src/main/java/com/pramodbharti/filmo/dummydata/DummyData.kt new file mode 100644 index 0000000..a6559bc --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/dummydata/DummyData.kt @@ -0,0 +1,66 @@ +package com.pramodbharti.filmo.dummydata + +import com.pramodbharti.filmo.R +import com.pramodbharti.filmo.ui.models.MediaItem +import com.pramodbharti.filmo.ui.screens.details.Cast + +val dummyMovies: List = listOf( + MediaItem( + 123, + "Testing one", + R.drawable.poster1, + R.drawable.back_drop1, + "" + ), MediaItem( + 133, + "Testing one", + R.drawable.poster2, + R.drawable.back_drop2, + "" + ), MediaItem( + 1230, + "Testing one", + R.drawable.poster1, + R.drawable.back_drop1, + "" + ), + MediaItem( + 123, + "Testing one", + R.drawable.poster1, + R.drawable.back_drop1, + "" + ), MediaItem( + 133, + "Testing one", + R.drawable.poster2, + R.drawable.back_drop2, + "" + ), MediaItem( + 1230, + "Testing one", + R.drawable.poster1, + R.drawable.back_drop1, + "" + ) +) + + +val dummyGenreList = listOf( + "Adventure", + "Action", + "Animation", + "Documentary", + "Fantasy", + "History", + "Science Fiction" +) + +val dummyCastData = listOf( + Cast("Pramod Bharti", R.drawable.dddd), + Cast("Konark Chakra", R.drawable.placeholder), + Cast("Unknown Profile", R.drawable.profile_picture), + Cast("Pramod Bharti", R.drawable.dddd), + Cast("Konark Chakra", R.drawable.placeholder), + Cast("Unknown Profile", R.drawable.profile_picture) +) \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/components/CarouselItem.kt b/app/src/main/java/com/pramodbharti/filmo/ui/components/CarouselItem.kt new file mode 100644 index 0000000..9d34669 --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/components/CarouselItem.kt @@ -0,0 +1,95 @@ +package com.pramodbharti.filmo.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.pramodbharti.filmo.dummydata.dummyMovies +import com.pramodbharti.filmo.ui.Constants +import com.pramodbharti.filmo.ui.models.MediaItem +import com.pramodbharti.filmo.ui.theme.FilmoTheme + +@Composable +fun CarouselItem(movieItem: MediaItem, modifier: Modifier = Modifier) { + Card( + modifier = modifier, + elevation = CardDefaults.cardElevation(defaultElevation = 8.dp), + shape = RectangleShape + ) { + Box { + AsyncImage( + model = ImageRequest.Builder(context = LocalContext.current) + .data("${Constants.IMAGE_URL_500}${movieItem.poster}") + .crossfade(true) + .build(), + contentDescription = movieItem.title, + contentScale = ContentScale.Crop, + placeholder = painterResource(id = movieItem.backdrop), + error = painterResource(id = movieItem.backdrop), + modifier = Modifier + .height(230.dp) + .fillMaxWidth() + ) + + Column( + modifier = Modifier + .align(Alignment.BottomStart) + .background( + brush = Brush.verticalGradient( + colorStops = arrayOf( + 0.0f to Color.Black.copy(alpha = 0.0f), + 0.6f to Color.Black.copy(alpha = 0.8f), + 1f to Color.Black.copy(alpha = 0.8f) + ) + ) + ) + .fillMaxWidth() + ) { + Text( + text = "John Wick 4", + style = TextStyle( + color = Color.White, + fontWeight = FontWeight.Bold + ), + modifier = Modifier.padding(start = 16.dp, top = 16.dp) + ) + Text( + text = "Crime, Thriller", + style = MaterialTheme.typography.bodySmall, + color = Color.Gray, + modifier = Modifier.padding(start = 16.dp, bottom = 16.dp) + ) + } + + } + } +} + +@Preview(showBackground = true) +@Composable +fun CarouselItemPReview() { + FilmoTheme { + CarouselItem(movieItem = dummyMovies[1]) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/components/CastItemsRow.kt b/app/src/main/java/com/pramodbharti/filmo/ui/components/CastItemsRow.kt new file mode 100644 index 0000000..1c55b85 --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/components/CastItemsRow.kt @@ -0,0 +1,65 @@ +package com.pramodbharti.filmo.ui.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +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.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.pramodbharti.filmo.ui.screens.details.Cast + +@Composable +fun CastItemsRow(casts: List, modifier: Modifier = Modifier) { + LazyRow( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp) + ) { + items(casts) { + CastItem(cast = it) + } + } +} + +@Composable +fun CastItem(cast: Cast, modifier: Modifier = Modifier) { + Column( + modifier = modifier.width(80.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + AsyncImage( + model = ImageRequest + .Builder(context = LocalContext.current) + .data(cast.photo) + .crossfade(true) + .build(), + placeholder = painterResource(id = cast.photo), + error = painterResource(id = cast.photo), + contentScale = ContentScale.Crop, + contentDescription = null, + modifier = Modifier + .clip(CircleShape) + .height(80.dp) + ) + Text( + text = cast.name, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/FilmoCarousel.kt b/app/src/main/java/com/pramodbharti/filmo/ui/components/FilmoCarousel.kt similarity index 97% rename from app/src/main/java/com/pramodbharti/filmo/ui/screens/home/FilmoCarousel.kt rename to app/src/main/java/com/pramodbharti/filmo/ui/components/FilmoCarousel.kt index 17acbc2..f9c00b7 100644 --- a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/FilmoCarousel.kt +++ b/app/src/main/java/com/pramodbharti/filmo/ui/components/FilmoCarousel.kt @@ -1,4 +1,4 @@ -package com.pramodbharti.filmo.ui.screens.home +package com.pramodbharti.filmo.ui.components import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background @@ -29,7 +29,7 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.pramodbharti.filmo.ui.components.carouselTransition +import com.pramodbharti.filmo.dummydata.dummyMovies import kotlinx.coroutines.delay import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/components/MediaItemsRow.kt b/app/src/main/java/com/pramodbharti/filmo/ui/components/MediaItemsRow.kt new file mode 100644 index 0000000..84e5182 --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/components/MediaItemsRow.kt @@ -0,0 +1,52 @@ +package com.pramodbharti.filmo.ui.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import coil.request.ImageRequest +import com.pramodbharti.filmo.ui.Constants +import com.pramodbharti.filmo.ui.models.MediaItem + +@Composable +fun MediaItemsPosterRow(movies: List, modifier: Modifier = Modifier) { + LazyRow( + modifier = modifier, + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + items(movies) { movie -> + MediaPoster(movieItem = movie) + } + } +} + +@Composable +fun MediaPoster(movieItem: MediaItem, modifier: Modifier = Modifier) { + Card( + modifier = modifier, + elevation = CardDefaults.cardElevation(defaultElevation = 8.dp) + ) { + AsyncImage( + model = ImageRequest.Builder(context = LocalContext.current) + .data("${Constants.IMAGE_URL_500}${movieItem.poster}") + .crossfade(true) + .build(), + contentDescription = movieItem.title, + contentScale = ContentScale.Crop, + placeholder = painterResource(id = movieItem.poster), + error = painterResource(id = movieItem.poster), + modifier = Modifier.size(150.dp, 230.dp) + ) + } +} diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/components/Slots.kt b/app/src/main/java/com/pramodbharti/filmo/ui/components/Slots.kt new file mode 100644 index 0000000..881fe2c --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/components/Slots.kt @@ -0,0 +1,28 @@ +package com.pramodbharti.filmo.ui.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.paddingFromBaseline +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun MediaSlots( + title: String, + modifier: Modifier = Modifier, + content: @Composable () -> Unit +) { + Column(modifier) { + Text( + text = title, + style = MaterialTheme.typography.titleMedium, + modifier = Modifier + .paddingFromBaseline(top = 32.dp) + .padding(horizontal = 16.dp) + ) + content() + } +} diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/components/TagItemsRow.kt b/app/src/main/java/com/pramodbharti/filmo/ui/components/TagItemsRow.kt new file mode 100644 index 0000000..884c183 --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/components/TagItemsRow.kt @@ -0,0 +1,45 @@ +package com.pramodbharti.filmo.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun TagItemsRow(tags: List, modifier: Modifier = Modifier) { + LazyRow( + horizontalArrangement = Arrangement.spacedBy(4.dp), + modifier = modifier, + contentPadding = PaddingValues( + start = 16.dp, + end = 16.dp, + bottom = 8.dp + ) + ) { + items(tags) { + TagItem(tagName = it) + } + } +} + +@Composable +fun TagItem(tagName: String, modifier: Modifier = Modifier) { + Text( + text = tagName, + style = MaterialTheme.typography.bodySmall, + color = Color.White, + fontSize = 10.sp, + modifier = modifier + .background(Color.DarkGray) + .padding(horizontal = 4.dp, vertical = 2.dp) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/models/FavoriteItems.kt b/app/src/main/java/com/pramodbharti/filmo/ui/models/FavoriteItems.kt new file mode 100644 index 0000000..359ec7c --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/models/FavoriteItems.kt @@ -0,0 +1,5 @@ +package com.pramodbharti.filmo.ui.models + +data class FavoriteItems( + val items: List +) diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/models/MovieItem.kt b/app/src/main/java/com/pramodbharti/filmo/ui/models/MediaItem.kt similarity index 91% rename from app/src/main/java/com/pramodbharti/filmo/ui/models/MovieItem.kt rename to app/src/main/java/com/pramodbharti/filmo/ui/models/MediaItem.kt index 657ba52..295d4b1 100644 --- a/app/src/main/java/com/pramodbharti/filmo/ui/models/MovieItem.kt +++ b/app/src/main/java/com/pramodbharti/filmo/ui/models/MediaItem.kt @@ -2,7 +2,7 @@ package com.pramodbharti.filmo.ui.models import androidx.annotation.DrawableRes -data class MovieItem( +data class MediaItem( val id: Int, val title: String, @DrawableRes diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/models/Movies.kt b/app/src/main/java/com/pramodbharti/filmo/ui/models/Movies.kt new file mode 100644 index 0000000..e31a74f --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/models/Movies.kt @@ -0,0 +1,9 @@ +package com.pramodbharti.filmo.ui.models + +data class Movies( + val trending: List, + val nowPlaying: List, + val popular: List, + val topRated: List, + val upcoming: List +) diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/models/TvShows.kt b/app/src/main/java/com/pramodbharti/filmo/ui/models/TvShows.kt new file mode 100644 index 0000000..af5b52d --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/models/TvShows.kt @@ -0,0 +1,9 @@ +package com.pramodbharti.filmo.ui.models + +data class TvShows( + val trending: List, + val airingToday: List, + val onTheAir: List, + val popular: List, + val topRated: List +) diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/FilmoApp.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/FilmoApp.kt index e69de29..fb8412f 100644 --- a/app/src/main/java/com/pramodbharti/filmo/ui/screens/FilmoApp.kt +++ b/app/src/main/java/com/pramodbharti/filmo/ui/screens/FilmoApp.kt @@ -0,0 +1,23 @@ +import android.content.res.Configuration.UI_MODE_NIGHT_NO +import android.content.res.Configuration.UI_MODE_NIGHT_YES +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.pramodbharti.filmo.dummydata.dummyMovies +import com.pramodbharti.filmo.ui.screens.movies.MoviesScreen + +@Composable +fun FilmoApp(modifier: Modifier = Modifier) { + MoviesScreen(dummyMovies) +} + +@Preview(name = "DarkMode", uiMode = UI_MODE_NIGHT_YES, showSystemUi = true) +@Preview(name = "LightMode", uiMode = UI_MODE_NIGHT_NO, showSystemUi = true) +@Composable +fun FilmoAppPreview() { + Surface(tonalElevation = 0.dp) { + FilmoApp() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/details/DetailsScreen.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/details/DetailsScreen.kt index b863401..1105305 100644 --- a/app/src/main/java/com/pramodbharti/filmo/ui/screens/details/DetailsScreen.kt +++ b/app/src/main/java/com/pramodbharti/filmo/ui/screens/details/DetailsScreen.kt @@ -1,18 +1,12 @@ package com.pramodbharti.filmo.ui.screens.details import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll @@ -23,43 +17,40 @@ 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.Brush import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import coil.request.ImageRequest import com.pramodbharti.filmo.R -import com.pramodbharti.filmo.ui.models.MovieItem -import com.pramodbharti.filmo.ui.screens.home.MoviePosterList -import com.pramodbharti.filmo.ui.screens.home.MoviesScreen -import com.pramodbharti.filmo.ui.screens.home.MoviesSection -import com.pramodbharti.filmo.ui.screens.home.dummyMovies +import com.pramodbharti.filmo.dummydata.dummyCastData +import com.pramodbharti.filmo.dummydata.dummyGenreList +import com.pramodbharti.filmo.dummydata.dummyMovies +import com.pramodbharti.filmo.ui.components.CastItemsRow +import com.pramodbharti.filmo.ui.components.MediaItemsPosterRow +import com.pramodbharti.filmo.ui.components.MediaSlots +import com.pramodbharti.filmo.ui.components.TagItemsRow +import com.pramodbharti.filmo.ui.models.MediaItem import com.pramodbharti.filmo.ui.theme.FilmoTheme @Composable -fun ItemDetailsScreen(movieItem: MovieItem, modifier: Modifier = Modifier) { +fun ItemDetailsScreen(movieItem: MediaItem, modifier: Modifier = Modifier) { Column(modifier = Modifier.verticalScroll(rememberScrollState())) { ItemDetails(movieItem = movieItem) - MoviesSection(title = "Cast") { - CastItemRow(casts = dummyCastData) + MediaSlots(title = "Cast") { + CastItemsRow(casts = dummyCastData) } - MoviesSection(title = "Similar") { - MoviePosterList(movies = dummyMovies) + MediaSlots(title = "Similar") { + MediaItemsPosterRow(movies = dummyMovies) } - MoviesSection(title = "Recommended for you") { - MoviePosterList(movies = dummyMovies) + MediaSlots(title = "Recommended for you") { + MediaItemsPosterRow(movies = dummyMovies) } } } @@ -73,7 +64,7 @@ fun ItemDetailsScreen() { } @Composable -fun ItemDetails(movieItem: MovieItem, modifier: Modifier = Modifier) { +fun ItemDetails(movieItem: MediaItem, modifier: Modifier = Modifier) { Box(modifier) { AsyncImage( model = ImageRequest @@ -97,7 +88,7 @@ fun ItemDetails(movieItem: MovieItem, modifier: Modifier = Modifier) { } @Composable -fun ItemDetailsSection(movieItem: MovieItem, modifier: Modifier = Modifier) { +fun ItemDetailsSection(movieItem: MediaItem, modifier: Modifier = Modifier) { Column( modifier = modifier.background( brush = Brush.verticalGradient( @@ -155,36 +146,6 @@ fun TitleAndFavorite(title: String, modifier: Modifier = Modifier) { } } -@Composable -fun TagItemsRow(tags: List, modifier: Modifier = Modifier) { - LazyRow( - horizontalArrangement = Arrangement.spacedBy(4.dp), - modifier = modifier, - contentPadding = PaddingValues( - start = 16.dp, - end = 16.dp, - bottom = 8.dp - ) - ) { - items(tags) { - TagItem(tagName = it) - } - } -} - -@Composable -fun TagItem(tagName: String, modifier: Modifier = Modifier) { - Text( - text = tagName, - style = MaterialTheme.typography.bodySmall, - color = Color.White, - fontSize = 10.sp, - modifier = modifier - .background(Color.DarkGray) - .padding(horizontal = 4.dp, vertical = 2.dp) - ) -} - @Composable fun AboutSection(modifier: Modifier = Modifier) { Text( @@ -200,98 +161,12 @@ fun AboutSection(modifier: Modifier = Modifier) { ) } -@Composable -fun CastItemRow(casts: List, modifier: Modifier = Modifier) { - LazyRow( - modifier = modifier, - horizontalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp) - ) { - items(casts) { - CastItem(cast = it) - } - } -} - -@Composable -fun CastItem(cast: Cast, modifier: Modifier = Modifier) { - Column( - modifier = modifier.width(80.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - AsyncImage( - model = ImageRequest - .Builder(context = LocalContext.current) - .data(cast.photo) - .crossfade(true) - .build(), - placeholder = painterResource(id = cast.photo), - error = painterResource(id = cast.photo), - contentScale = ContentScale.Crop, - contentDescription = null, - modifier = Modifier - .clip(CircleShape) - .height(80.dp) - ) - Text( - text = cast.name, - style = MaterialTheme.typography.bodyMedium, - textAlign = TextAlign.Center - ) - } -} - @Preview @Composable fun ItemDetailsPreview() { ItemDetails(movieItem = dummyMovies[0]) } -@Preview(showBackground = true) -@Composable -fun TitleAndFavoritePreview() { - TitleAndFavorite(title = dummyGenreList[0]) -} -@Preview(showBackground = true) -@Composable -fun TagItemsRowPreview() { - TagItemsRow(tags = dummyGenreList) -} - -@Preview(showBackground = true) -@Composable -fun AboutSectionPReview() { - AboutSection() -} - -@Preview(showBackground = true) -@Composable -fun CastItemRowPreview() { - CastItemRow(casts = dummyCastData) -} - -@Preview(showBackground = true) -@Composable -fun CastItemPreview() { - CastItem(cast = dummyCastData[0]) -} -val dummyGenreList = listOf( - "Adventure", - "Action", - "Animation", - "Documentary", - "Fantasy", - "History", - "Science Fiction" -) -val dummyCastData = listOf( - Cast("Pramod Bharti", R.drawable.dddd), - Cast("Konark Chakra", R.drawable.placeholder), - Cast("Unknown Profile", R.drawable.profile_picture), - Cast("Pramod Bharti", R.drawable.dddd), - Cast("Konark Chakra", R.drawable.placeholder), - Cast("Unknown Profile", R.drawable.profile_picture) -) \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeScreen.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeScreen.kt deleted file mode 100644 index 4098e3e..0000000 --- a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeScreen.kt +++ /dev/null @@ -1,263 +0,0 @@ -package com.pramodbharti.filmo.ui.screens.home - -import android.content.res.Configuration.UI_MODE_NIGHT_YES -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.paddingFromBaseline -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.RectangleShape -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage -import coil.request.ImageRequest -import com.pramodbharti.filmo.R -import com.pramodbharti.filmo.ui.Constants -import com.pramodbharti.filmo.ui.models.MovieItem -import com.pramodbharti.filmo.ui.theme.FilmoTheme - - -@Composable -fun CarouselItem(movieItem: MovieItem, modifier: Modifier = Modifier) { - Card( - modifier = modifier, - elevation = CardDefaults.cardElevation(defaultElevation = 8.dp), - shape = RectangleShape - ) { - Box { - AsyncImage( - model = ImageRequest.Builder(context = LocalContext.current) - .data("${Constants.IMAGE_URL_500}${movieItem.poster}") - .crossfade(true) - .build(), - contentDescription = movieItem.title, - contentScale = ContentScale.Crop, - placeholder = painterResource(id = movieItem.backdrop), - error = painterResource(id = movieItem.backdrop), - modifier = Modifier - .height(230.dp) - .fillMaxWidth() - ) - - Column( - modifier = Modifier - .align(Alignment.BottomStart) - .background( - brush = Brush.verticalGradient( - colorStops = arrayOf( - 0.0f to Color.Black.copy(alpha = 0.0f), - 0.6f to Color.Black.copy(alpha = 0.8f), - 1f to Color.Black.copy(alpha = 0.8f) - ) - ) - ) - .fillMaxWidth() - ) { - Text( - text = "John Wick 4", - style = TextStyle( - color = Color.White, - fontWeight = FontWeight.Bold - ), - modifier = Modifier.padding(start = 16.dp, top = 16.dp) - ) - Text( - text = "Crime, Thriller", - style = MaterialTheme.typography.bodySmall, - color = Color.Gray, - modifier = Modifier.padding(start = 16.dp, bottom = 16.dp) - ) - } - - } - } -} - - -@OptIn(ExperimentalFoundationApi::class) -@Composable -fun MoviesScreen(modifier: Modifier = Modifier) { - Column(modifier.verticalScroll(rememberScrollState())) { - FilmoCarousel(itemsCount = dummyMovies.size) { index, pagerState -> - CarouselItem( - movieItem = dummyMovies[index] - ) - } - MoviesSection(title = "Trending") { - MoviePosterList(movies = dummyMovies) - } - MoviesSection(title = "Popular") { - MoviePosterList(movies = dummyMovies) - } - MoviesSection(title = "Trending") { - MoviePosterList(movies = dummyMovies) - } - MoviesSection(title = "Popular") { - MoviePosterList(movies = dummyMovies) - } - } -} - -@Composable -fun MoviesSection( - title: String, - modifier: Modifier = Modifier, - content: @Composable () -> Unit -) { - Column(modifier) { - Text( - text = title, - style = MaterialTheme.typography.titleMedium, - modifier = Modifier - .paddingFromBaseline(top = 32.dp) - .padding(horizontal = 16.dp) - ) - content() - } -} - -@Composable -fun MoviePosterList(movies: List, modifier: Modifier = Modifier) { - LazyRow( - modifier = modifier, - contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - items(movies) { movie -> - MoviePoster(movieItem = movie) - } - } -} - -@Composable -fun MoviePoster(movieItem: MovieItem, modifier: Modifier = Modifier) { - Card( - modifier = modifier, - elevation = CardDefaults.cardElevation(defaultElevation = 8.dp) - ) { - AsyncImage( - model = ImageRequest.Builder(context = LocalContext.current) - .data("${Constants.IMAGE_URL_500}${movieItem.poster}") - .crossfade(true) - .build(), - contentDescription = movieItem.title, - contentScale = ContentScale.Crop, - placeholder = painterResource(id = movieItem.poster), - error = painterResource(id = movieItem.poster), - modifier = Modifier.size(150.dp, 230.dp) - ) - } -} - -@Preview(showBackground = true) -@Composable -fun CarouselItemPReview() { - FilmoTheme { - CarouselItem(movieItem = dummyMovies[1]) - } -} - -@Preview(showBackground = true, showSystemUi = true, uiMode = UI_MODE_NIGHT_YES) -@Composable -fun MoviesScreenPreview() { - FilmoTheme { - MoviesScreen() - } -} - -@Preview(showBackground = true) -@Composable -fun MovieSectionPreview() { - FilmoTheme { - MoviesSection(title = "Trending") { - MoviePosterList(movies = dummyMovies) - } - } -} - -@Preview(showBackground = true) -@Composable -fun MoviePosterListPreview() { - FilmoTheme { - MoviePosterList( - movies = dummyMovies - ) - } -} - -@Preview(showBackground = true) -@Composable -fun MoviePosterPreview() { - FilmoTheme { - MoviePoster( - movieItem = dummyMovies[0] - ) - } -} - -val dummyMovies: List = listOf( - MovieItem( - 123, - "Testing one", - R.drawable.poster1, - R.drawable.back_drop1, - "" - ), MovieItem( - 133, - "Testing one", - R.drawable.poster2, - R.drawable.back_drop2, - "" - ), MovieItem( - 1230, - "Testing one", - R.drawable.poster1, - R.drawable.back_drop1, - "" - ), - MovieItem( - 123, - "Testing one", - R.drawable.poster1, - R.drawable.back_drop1, - "" - ), MovieItem( - 133, - "Testing one", - R.drawable.poster2, - R.drawable.back_drop2, - "" - ), MovieItem( - 1230, - "Testing one", - R.drawable.poster1, - R.drawable.back_drop1, - "" - ) -) - - diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/MovieUiState.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/MovieUiState.kt deleted file mode 100644 index 6f2aff7..0000000 --- a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/MovieUiState.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.pramodbharti.filmo.ui.screens.home - -import com.pramodbharti.filmo.ui.models.MovieItem - -sealed interface MovieUiState { - data class Success(val movies: List): MovieUiState - object Error : MovieUiState - object Loading : MovieUiState -} \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesScreen.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesScreen.kt new file mode 100644 index 0000000..e2e251f --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesScreen.kt @@ -0,0 +1,56 @@ +package com.pramodbharti.filmo.ui.screens.movies + +import android.content.res.Configuration.UI_MODE_NIGHT_YES +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.pramodbharti.filmo.dummydata.dummyMovies +import com.pramodbharti.filmo.ui.components.CarouselItem +import com.pramodbharti.filmo.ui.components.FilmoCarousel +import com.pramodbharti.filmo.ui.components.MediaItemsPosterRow +import com.pramodbharti.filmo.ui.components.MediaSlots +import com.pramodbharti.filmo.ui.models.MediaItem +import com.pramodbharti.filmo.ui.theme.FilmoTheme + + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun MoviesScreen( + movies: List, + modifier: Modifier = Modifier +) { + Column(modifier.verticalScroll(rememberScrollState())) { + FilmoCarousel(itemsCount = movies.size) { index, pagerState -> + CarouselItem( + movieItem = movies[index] + ) + } + MediaSlots(title = "Trending") { + MediaItemsPosterRow(movies = dummyMovies) + } + MediaSlots(title = "Popular") { + MediaItemsPosterRow(movies = dummyMovies) + } + MediaSlots(title = "Trending") { + MediaItemsPosterRow(movies = dummyMovies) + } + MediaSlots(title = "Popular") { + MediaItemsPosterRow(movies = dummyMovies) + } + } +} + + +@Preview(showBackground = true, showSystemUi = true, uiMode = UI_MODE_NIGHT_YES) +@Composable +fun MoviesScreenPreview() { + FilmoTheme { + MoviesScreen(dummyMovies) + } +} + + diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesUiState.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesUiState.kt new file mode 100644 index 0000000..95d3395 --- /dev/null +++ b/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesUiState.kt @@ -0,0 +1,9 @@ +package com.pramodbharti.filmo.ui.screens.movies + +import com.pramodbharti.filmo.ui.models.MediaItem + +sealed interface MoviesUiState { + data class Success(val movies: List): MoviesUiState + object Error : MoviesUiState + object Loading : MoviesUiState +} \ No newline at end of file diff --git a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeViewModel.kt b/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesViewModel.kt similarity index 72% rename from app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeViewModel.kt rename to app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesViewModel.kt index 33c36c9..5eddeb9 100644 --- a/app/src/main/java/com/pramodbharti/filmo/ui/screens/home/HomeViewModel.kt +++ b/app/src/main/java/com/pramodbharti/filmo/ui/screens/movies/MoviesViewModel.kt @@ -1,4 +1,4 @@ -package com.pramodbharti.filmo.ui.screens.home +package com.pramodbharti.filmo.ui.screens.movies import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -12,14 +12,13 @@ import androidx.lifecycle.viewmodel.viewModelFactory import com.pramodbharti.filmo.FilmoApplication import com.pramodbharti.filmo.R import com.pramodbharti.filmo.data.network.models.MovieResponse -import com.pramodbharti.filmo.data.network.models.MoviesResponse import com.pramodbharti.filmo.data.repositories.MoviesRepository -import com.pramodbharti.filmo.ui.models.MovieItem +import com.pramodbharti.filmo.ui.models.MediaItem import kotlinx.coroutines.launch import java.io.IOException -class HomeViewModel(private val moviesRepository: MoviesRepository) : ViewModel() { - var movieUiState: MovieUiState by mutableStateOf(MovieUiState.Loading) +class MoviesViewModel(private val moviesRepository: MoviesRepository) : ViewModel() { + var movieUiState: MoviesUiState by mutableStateOf(MoviesUiState.Loading) private set init { @@ -30,9 +29,9 @@ class HomeViewModel(private val moviesRepository: MoviesRepository) : ViewModel( viewModelScope.launch { movieUiState = try { val movieList = moviesRepository.getDiscoverMovies() - MovieUiState.Success(movieList.results.map { it.toMovieItem() }) + MoviesUiState.Success(movieList.results.map { it.toMovieItem() }) } catch (e: IOException) { - MovieUiState.Error + MoviesUiState.Error } } } @@ -42,14 +41,14 @@ class HomeViewModel(private val moviesRepository: MoviesRepository) : ViewModel( initializer { val application = (this[APPLICATION_KEY] as FilmoApplication) val moviesRepository = application.container.moviesRepository - HomeViewModel(moviesRepository) + MoviesViewModel(moviesRepository) } } } - private fun MovieResponse.toMovieItem(): MovieItem = - MovieItem( + private fun MovieResponse.toMovieItem(): MediaItem = + MediaItem( id = id, title = title, poster = R.drawable.poster1,