Pārlūkot izejas kodu

screens improvement

Milan Jurkulak 3 gadi atpakaļ
vecāks
revīzija
30a5d765a4

+ 5 - 0
app/src/main/kotlin/org/mjdev/tvapp/base/extensions/ComposeExt.kt

@@ -11,8 +11,10 @@
 package org.mjdev.tvapp.base.extensions
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalInspectionMode
+import kotlinx.coroutines.flow.Flow
 import org.mjdev.tvapp.BuildConfig
 
 @Suppress("MemberVisibilityCanBePrivate")
@@ -24,6 +26,9 @@ object ComposeExt {
     @Composable
     fun isEditMode() = LocalInspectionMode.current
 
+    @Composable
+    fun <T> Flow<T>?.collectAsState(): State<T>? = this?.collectAsState()
+
     /**
      * Helper function to return text from any object is given as input.
      * Mainly: Int -> is represented as resource text id String -> String null

+ 13 - 15
app/src/main/kotlin/org/mjdev/tvapp/base/extensions/HiltExt.kt

@@ -21,10 +21,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
 import androidx.navigation.NavBackStackEntry
 import androidx.savedstate.SavedStateRegistryOwner
 import org.mjdev.tvapp.base.extensions.ComposeExt.isEditMode
-import org.mjdev.tvapp.base.helpers.StateContextWrapper
 import org.mjdev.tvapp.base.viewmodel.BaseViewModel
-import kotlin.reflect.full.companionObjectInstance
-import kotlin.reflect.full.memberFunctions
 
 object HiltExt {
 
@@ -33,7 +30,7 @@ object HiltExt {
     inline fun <reified VM : BaseViewModel> appViewModel(
         viewModelStoreOwner: ViewModelStoreOwner? = null,
         key: String? = null
-    ): VM {
+    ): VM? {
         return if (isEditMode())
             createMockModel()
         else {
@@ -52,17 +49,18 @@ object HiltExt {
 
     // todo
     @Composable
-    inline fun <reified VM : BaseViewModel> createMockModel(): VM {
-        val context = StateContextWrapper(LocalContext.current)
-        return VM::class.memberFunctions.first { fn ->
-            fn.name == "mock"
-        }.call(VM::class.companionObjectInstance, context) as? VM
-            ?: throw (RuntimeException(
-                "ViewModel ${
-                    VM::class.simpleName
-                } does not contain MOCK companion function." +
-                    "Please define companion function fun MOCK(context:Context)in this view model."
-            ))
+    inline fun <reified VM : BaseViewModel> createMockModel(): VM? {
+        return null
+//        val context = StateContextWrapper(LocalContext.current)
+//        return VM::class.memberFunctions.first { fn ->
+//            fn.name == "mock"
+//        }.call(VM::class.companionObjectInstance, context) as? VM
+//            ?: throw (RuntimeException(
+//                "ViewModel ${
+//                    VM::class.simpleName
+//                } does not contain MOCK companion function." +
+//                    "Please define companion function fun MOCK(context:Context)in this view model."
+//            ))
     }
 
     @Composable

+ 48 - 0
app/src/main/kotlin/org/mjdev/tvapp/base/navigation/ScreenWithPages.kt

@@ -0,0 +1,48 @@
+package org.mjdev.tvapp.base.navigation
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.res.stringResource
+import androidx.navigation.NavBackStackEntry
+import androidx.navigation.NavHostController
+import org.mjdev.tvapp.R
+import org.mjdev.tvapp.base.page.Pager
+import org.mjdev.tvapp.base.page.PagerScope
+import org.mjdev.tvapp.base.page.PagerState
+import org.mjdev.tvapp.base.ui.components.complex.ScreenView
+
+open class ScreenWithPages : Screen() {
+
+    open val pages : @Composable PagerScope.(pagerState: PagerState) -> Unit = {}
+
+    @Composable
+    override fun Compose() = super.Compose()
+
+    @Composable
+    override fun Compose(
+        navController: NavHostController?,
+        backStackEntry: NavBackStackEntry?,
+        menuItems: List<MenuItem>,
+        args: Map<String, Any?>
+    ) {
+
+        val menuState = remember { mutableListOf<MenuItem>().apply { addAll(menuItems) } }
+
+        ScreenView(
+            navController = navController,
+            title = if (titleResId > -1) stringResource(titleResId) else R.string.app_name,
+            menuItems = menuState
+        ) { screenState ->
+
+            Pager(
+                navController=navController,
+                screenState = screenState,
+                menuItems = menuState,
+                startIndex = 0,
+                pages = pages
+            )
+
+        }
+
+    }
+}

+ 14 - 14
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/MainPage.kt

@@ -11,6 +11,7 @@ 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
@@ -40,9 +41,10 @@ import org.mjdev.tvapp.base.ui.components.complex.Header
 import org.mjdev.tvapp.ui.screens.DetailScreen
 import org.mjdev.tvapp.ui.screens.PlayerScreen
 import org.mjdev.tvapp.viewmodel.MainViewModel
+import org.mjdev.tvapp.base.extensions.ComposeExt.collectAsState
 
 @SuppressLint("ComposableNaming")
-class MainPage: Page() {
+class MainPage : Page() {
 
     override val title: Int = R.string.title_home
     override val icon: ImageVector = Icons.Default.Home
@@ -53,16 +55,14 @@ class MainPage: 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 categoryList = remember { viewModel?.categoryList }?.collectAsState()
+        val featuredMovieList = remember { viewModel?.featuredMovieList }?.collectAsState()
+        val messages = remember { viewModel?.messages }?.collectAsState()
+        val networkState = remember { viewModel?.networkInfo?.networkStatus }?.collectAsState()
 
         val onItemClick: (movie: Movie?) -> Unit = { movie ->
             if (movie == null) {
-                viewModel.postError("No media found.".asException())
+                viewModel?.postError("No media found.".asException())
             } else if (movie.hasVideoUri) {
                 navController?.open<PlayerScreen>(movie.id)
             } else {
@@ -70,7 +70,7 @@ class MainPage: Page() {
             }
         }
 
-        viewModel.handleError { error ->
+        viewModel?.handleError { error ->
             screenState?.error(error)
         }
 
@@ -86,12 +86,12 @@ class MainPage: Page() {
 
                 Header(
                     title = screenState?.titleState?.value,
-                    messagesCount = messages.value.size
+                    messagesCount = messages?.value?.size ?: 0
                 )
 
             }
 
-            if (networkState.value !is NetworkStatus.Connected) item {
+            if (networkState?.value !is NetworkStatus.Connected) item {
                 ErrorMessage(
                     error = stringResource(R.string.error_no_network).asException(),
                     backgroundColor = Color.Black,
@@ -100,7 +100,7 @@ class MainPage: Page() {
             }
 
 
-            if (categoryList.value.isNotEmpty()) item {
+            if (categoryList?.value?.isNotEmpty() == true) item {
 
                 Tabs(
                     items = categoryList.value.map { it.name }
@@ -108,7 +108,7 @@ class MainPage: Page() {
 
             }
 
-            if (featuredMovieList.value.isNotEmpty()) item {
+            if (featuredMovieList?.value?.isNotEmpty() == true) item {
 
                 BigCarousel(
                     modifier = Modifier.touchable(),
@@ -118,7 +118,7 @@ class MainPage: Page() {
 
             }
 
-            items(categoryList.value) { category ->
+            items(categoryList?.value ?: emptyList()) { category ->
 
                 Text(
                     modifier = Modifier

+ 9 - 41
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/MainScreen.kt

@@ -9,58 +9,26 @@
 package org.mjdev.tvapp.ui.screens
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.res.stringResource
-import androidx.navigation.NamedNavArgument
-import androidx.navigation.NavBackStackEntry
-import androidx.navigation.NavHostController
-import org.mjdev.tvapp.R
 import org.mjdev.tvapp.base.annotations.TvPreview
-import org.mjdev.tvapp.base.navigation.MenuItem
-import org.mjdev.tvapp.base.navigation.Screen
-import org.mjdev.tvapp.base.page.Pager
-import org.mjdev.tvapp.base.ui.components.complex.ScreenView
+import org.mjdev.tvapp.base.navigation.ScreenWithPages
+import org.mjdev.tvapp.base.page.PagerScope
+import org.mjdev.tvapp.base.page.PagerState
 import org.mjdev.tvapp.ui.pages.AboutPage
 import org.mjdev.tvapp.ui.pages.MainPage
 import org.mjdev.tvapp.ui.pages.SubscriptionPage
 
-class MainScreen : Screen() {
-
-    override val args = listOf<NamedNavArgument>()
+class MainScreen : ScreenWithPages() {
 
     @TvPreview
     @Composable
     override fun Compose() = super.Compose()
 
-    @Composable
-    override fun Compose(
-        navController: NavHostController?,
-        backStackEntry: NavBackStackEntry?,
-        menuItems: List<MenuItem>,
-        args: Map<String, Any?>
-    ) {
-
-        val menuState = remember { mutableListOf<MenuItem>().apply { addAll(menuItems) } }
-
-        ScreenView(
-            navController = navController,
-            title = if (titleResId > -1) stringResource(titleResId) else R.string.app_name,
-            menuItems = menuState
-        ) { screenState ->
+    override val pages: @Composable (PagerScope.(PagerState) -> Unit) = {
 
-            Pager(
-                navController,
-                screenState,
-                menuState
-            ) {
-
-                page(MainPage())
-                page(AboutPage())
-                page(SubscriptionPage())
-
-            }
-
-        }
+        page(MainPage())
+        page(AboutPage())
+        page(SubscriptionPage())
 
     }
+
 }