|
|
@@ -1,5 +1,6 @@
|
|
|
package org.mjdev.tvapp.ui.pages
|
|
|
|
|
|
+import android.annotation.SuppressLint
|
|
|
import androidx.compose.foundation.background
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
|
import androidx.compose.foundation.layout.PaddingValues
|
|
|
@@ -7,15 +8,17 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
+import androidx.compose.material.icons.Icons
|
|
|
+import androidx.compose.material.icons.filled.Home
|
|
|
import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.collectAsState
|
|
|
import androidx.compose.runtime.remember
|
|
|
import androidx.compose.ui.Modifier
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
+import androidx.compose.ui.graphics.vector.ImageVector
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
import androidx.compose.ui.text.font.FontWeight
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
-import androidx.navigation.NavHostController
|
|
|
import androidx.tv.foundation.lazy.list.TvLazyRow
|
|
|
import androidx.tv.foundation.lazy.list.items
|
|
|
import androidx.tv.material3.Text
|
|
|
@@ -27,7 +30,6 @@ import org.mjdev.tvapp.base.extensions.StringExt.asException
|
|
|
import org.mjdev.tvapp.base.navigation.Screen.Companion.open
|
|
|
import org.mjdev.tvapp.base.network.NetworkStatus
|
|
|
import org.mjdev.tvapp.base.page.Page
|
|
|
-import org.mjdev.tvapp.base.state.ScreenState
|
|
|
import org.mjdev.tvapp.base.ui.components.complex.BigCarousel
|
|
|
import org.mjdev.tvapp.base.ui.components.complex.ScrollableTvLazyRow
|
|
|
import org.mjdev.tvapp.base.ui.components.complex.Tabs
|
|
|
@@ -39,114 +41,120 @@ import org.mjdev.tvapp.ui.screens.DetailScreen
|
|
|
import org.mjdev.tvapp.ui.screens.PlayerScreen
|
|
|
import org.mjdev.tvapp.viewmodel.MainViewModel
|
|
|
|
|
|
-@TvPreview
|
|
|
-@Composable
|
|
|
-fun MainPage(
|
|
|
- navController: NavHostController? = null,
|
|
|
- screenState: ScreenState? = null,
|
|
|
-) = Page {
|
|
|
-
|
|
|
- val viewModel = appViewModel<MainViewModel>()
|
|
|
-
|
|
|
- val categoryList = remember { viewModel.categoryList }.collectAsState()
|
|
|
- val featuredMovieList = remember { viewModel.featuredMovieList }.collectAsState()
|
|
|
- val messages = remember { viewModel.messages }.collectAsState()
|
|
|
- val networkState = remember {
|
|
|
- viewModel.networkInfo.networkStatus
|
|
|
- }.collectAsState(null)
|
|
|
-
|
|
|
- val onItemClick: (movie: Movie?) -> Unit = { movie ->
|
|
|
- if (movie == null) {
|
|
|
- viewModel.postError("No media found.".asException())
|
|
|
- } else if (movie.hasVideoUri) {
|
|
|
- navController?.open<PlayerScreen>(movie.id)
|
|
|
- } else {
|
|
|
- navController?.open<DetailScreen>(movie.id)
|
|
|
- }
|
|
|
- }
|
|
|
+@SuppressLint("ComposableNaming")
|
|
|
+class MainPage: Page() {
|
|
|
|
|
|
- viewModel.handleError { error ->
|
|
|
- screenState?.error(error)
|
|
|
- }
|
|
|
+ override val title: Int = R.string.app_name
|
|
|
+ override val icon: ImageVector = Icons.Default.Home
|
|
|
|
|
|
- ScrollableTvLazyRow(
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxSize()
|
|
|
- .background(Color.DarkGray),
|
|
|
- verticalArrangement = Arrangement.spacedBy(32.dp),
|
|
|
- contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
|
|
|
- ) {
|
|
|
+ @TvPreview
|
|
|
+ @Composable
|
|
|
+ override fun Content() {
|
|
|
|
|
|
- item {
|
|
|
+ val viewModel = appViewModel<MainViewModel>()
|
|
|
|
|
|
- Header(
|
|
|
- title = screenState?.titleState?.value,
|
|
|
- messagesCount = messages.value.size
|
|
|
- )
|
|
|
+ val categoryList = remember { viewModel.categoryList }.collectAsState()
|
|
|
+ val featuredMovieList = remember { viewModel.featuredMovieList }.collectAsState()
|
|
|
+ val messages = remember { viewModel.messages }.collectAsState()
|
|
|
+ val networkState = remember {
|
|
|
+ viewModel.networkInfo.networkStatus
|
|
|
+ }.collectAsState(null)
|
|
|
|
|
|
+ val onItemClick: (movie: Movie?) -> Unit = { movie ->
|
|
|
+ if (movie == null) {
|
|
|
+ viewModel.postError("No media found.".asException())
|
|
|
+ } else if (movie.hasVideoUri) {
|
|
|
+ navController?.open<PlayerScreen>(movie.id)
|
|
|
+ } else {
|
|
|
+ navController?.open<DetailScreen>(movie.id)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (networkState.value !is NetworkStatus.Connected) item {
|
|
|
- ErrorMessage(
|
|
|
- error = stringResource(R.string.error_no_network).asException(),
|
|
|
- backgroundColor = Color.Black,
|
|
|
- dismissible = false
|
|
|
- )
|
|
|
+ viewModel.handleError { error ->
|
|
|
+ screenState?.error(error)
|
|
|
}
|
|
|
|
|
|
+ ScrollableTvLazyRow(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxSize()
|
|
|
+ .background(Color.DarkGray),
|
|
|
+ verticalArrangement = Arrangement.spacedBy(32.dp),
|
|
|
+ contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
|
|
|
+ ) {
|
|
|
|
|
|
- if (categoryList.value.isNotEmpty()) item {
|
|
|
+ item {
|
|
|
|
|
|
- Tabs(
|
|
|
- items = categoryList.value.map { it.name }
|
|
|
- )
|
|
|
+ Header(
|
|
|
+ title = screenState?.titleState?.value,
|
|
|
+ messagesCount = messages.value.size
|
|
|
+ )
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- if (featuredMovieList.value.isNotEmpty()) item {
|
|
|
+ if (networkState.value !is NetworkStatus.Connected) item {
|
|
|
+ ErrorMessage(
|
|
|
+ error = stringResource(R.string.error_no_network).asException(),
|
|
|
+ backgroundColor = Color.Black,
|
|
|
+ dismissible = false
|
|
|
+ )
|
|
|
+ }
|
|
|
|
|
|
- BigCarousel(
|
|
|
- modifier = Modifier.touchable(),
|
|
|
- items = featuredMovieList.value,
|
|
|
- onItemClicked = onItemClick
|
|
|
- )
|
|
|
|
|
|
- }
|
|
|
+ if (categoryList.value.isNotEmpty()) item {
|
|
|
|
|
|
- items(categoryList.value) { category ->
|
|
|
-
|
|
|
- Text(
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(0.dp, 16.dp),
|
|
|
- text = category.name,
|
|
|
- color = Color.White,
|
|
|
- fontWeight = FontWeight.Bold
|
|
|
- )
|
|
|
-
|
|
|
- TvLazyRow(
|
|
|
- horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
|
- modifier = Modifier.height(200.dp),
|
|
|
- contentPadding = PaddingValues(
|
|
|
- start = 16.dp,
|
|
|
- top = 16.dp,
|
|
|
- bottom = 16.dp,
|
|
|
- end = 16.dp
|
|
|
+ Tabs(
|
|
|
+ items = categoryList.value.map { it.name }
|
|
|
)
|
|
|
- ) {
|
|
|
|
|
|
- items(category.movieList) { item ->
|
|
|
+ }
|
|
|
+
|
|
|
+ if (featuredMovieList.value.isNotEmpty()) item {
|
|
|
|
|
|
- MovieCard(
|
|
|
- movie = item,
|
|
|
- onClick = onItemClick
|
|
|
+ BigCarousel(
|
|
|
+ modifier = Modifier.touchable(),
|
|
|
+ items = featuredMovieList.value,
|
|
|
+ onItemClicked = onItemClick
|
|
|
+ )
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ items(categoryList.value) { category ->
|
|
|
+
|
|
|
+ Text(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .padding(0.dp, 16.dp),
|
|
|
+ text = category.name,
|
|
|
+ color = Color.White,
|
|
|
+ fontWeight = FontWeight.Bold
|
|
|
+ )
|
|
|
+
|
|
|
+ TvLazyRow(
|
|
|
+ horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
|
+ modifier = Modifier.height(200.dp),
|
|
|
+ contentPadding = PaddingValues(
|
|
|
+ start = 16.dp,
|
|
|
+ top = 16.dp,
|
|
|
+ bottom = 16.dp,
|
|
|
+ end = 16.dp
|
|
|
)
|
|
|
+ ) {
|
|
|
+
|
|
|
+ items(category.movieList) { item ->
|
|
|
+
|
|
|
+ MovieCard(
|
|
|
+ movie = item,
|
|
|
+ onClick = onItemClick
|
|
|
+ )
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|