Kaynağa Gözat

design improvement

Milan Jurkulak 3 yıl önce
ebeveyn
işleme
8d06871f59
87 değiştirilmiş dosya ile 480 ekleme ve 253 silme
  1. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/activity/IPTVActivity.kt
  2. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/activity/MainActivity.kt
  3. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/activity/WebActivity.kt
  4. 1 2
      app/src/main/kotlin/org/mjdev/tvapp/module/ProvideModule.kt
  5. 3 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/AboutPage.kt
  6. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/MainPage.kt
  7. 3 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/PluginsPage.kt
  8. 3 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/pages/SubscriptionPage.kt
  9. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/DetailScreen.kt
  10. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/IPTVScreen.kt
  11. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/LoadingScreen.kt
  12. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/MainScreen.kt
  13. 4 9
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/SplashScreen.kt
  14. 2 2
      app/src/main/kotlin/org/mjdev/tvapp/ui/screens/WebScreen.kt
  15. 1 0
      settings.gradle.kts
  16. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/activity/ComposableActivity.kt
  17. 48 0
      tvlib/src/main/kotlin/org/mjdev/tvlib/annotations/Preview.kt
  18. 0 24
      tvlib/src/main/kotlin/org/mjdev/tvlib/annotations/TvPreview.kt
  19. 10 0
      tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/GlobalExt.kt
  20. 35 9
      tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/ModifierExt.kt
  21. 11 0
      tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/StringExt.kt
  22. 37 37
      tvlib/src/main/kotlin/org/mjdev/tvlib/helpers/other/Observed.kt
  23. 6 3
      tvlib/src/main/kotlin/org/mjdev/tvlib/screen/Screen.kt
  24. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/screen/ScreenWithPages.kt
  25. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/button/Button.kt
  26. 6 3
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/Card.kt
  27. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/CardContent.kt
  28. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/ItemCard.kt
  29. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/PhotoCard.kt
  30. 6 4
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/PreviewCard.kt
  31. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/carousel/BigCarousel.kt
  32. 4 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/carousel/Carousel.kt
  33. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/carousel/CarouselCard.kt
  34. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/FocusableBox.kt
  35. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/FocusableCard.kt
  36. 9 6
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/VerticalScrollableBox.kt
  37. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/XmlLayout.kt
  38. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/gallery/Gallery.kt
  39. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/gallery/ItemInfo.kt
  40. 4 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/gridview/TvGridView.kt
  41. 5 3
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/icon/IconAny.kt
  42. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/CircleImage.kt
  43. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/FadingPhotoImage.kt
  44. 4 3
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/ImageAny.kt
  45. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/ImageBackground.kt
  46. 4 3
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/PhotoImage.kt
  47. 9 3
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/immersivelist/ImmersiveList.kt
  48. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/media/MediaPlayerContainer.kt
  49. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/media/PlayerControlView.kt
  50. 3 4
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/DrawerSheet.kt
  51. 6 4
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/ModalNavigationDrawer.kt
  52. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavDrawerContent.kt
  53. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavHostEx.kt
  54. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/Navigation.kt
  55. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavigationDrawer.kt
  56. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavigationRow.kt
  57. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/SettingsDrawer.kt
  58. 1 1
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/SettingsDrawerContent.kt
  59. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/Page.kt
  60. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/SearchPage.kt
  61. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/SettingsPage.kt
  62. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/TvPager.kt
  63. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/screen/EmptyScreen.kt
  64. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/screen/ScreenView.kt
  65. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/AutoHideEmptyText.kt
  66. 5 4
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/CircleText.kt
  67. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/TextAny.kt
  68. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/TextWithShadow.kt
  69. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/AppsRow.kt
  70. 4 4
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/BrowseView.kt
  71. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/CategoryRow.kt
  72. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Clock.kt
  73. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/CursorRow.kt
  74. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/ErrorMessage.kt
  75. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Header.kt
  76. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Loading.kt
  77. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/LocalAudioRow.kt
  78. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/LocalPhotosRow.kt
  79. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/LocalVideoRow.kt
  80. 5 1
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/NetworkErrorMessage.kt
  81. 16 4
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/ScrollableTvLazyColumn.kt
  82. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/TVRow.kt
  83. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Tabs.kt
  84. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Title.kt
  85. 2 2
      tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/UserPic.kt
  86. 54 0
      tvlib/src/main/kotlin/org/mjdev/tvlib/webclient/cache/NetUtils.kt
  87. 61 0
      tvlib/src/main/kotlin/org/mjdev/tvlib/webclient/cache/TimeUtils.kt

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/activity/IPTVActivity.kt

@@ -14,11 +14,11 @@ import dagger.hilt.android.AndroidEntryPoint
 import org.mjdev.tvapp.data.local.Movie
 import org.mjdev.tvapp.ui.screens.DetailScreen
 import org.mjdev.tvlib.activity.ComposableActivity
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.screen
 import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvapp.ui.screens.IPTVScreen
 import org.mjdev.tvapp.ui.screens.LoadingScreen
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.NavControllerExt.openAsTop
 import org.mjdev.tvlib.interfaces.ItemAudio
 import org.mjdev.tvlib.interfaces.ItemPhoto
@@ -28,7 +28,7 @@ import org.mjdev.tvlib.navigation.NavHostControllerEx
 @AndroidEntryPoint
 class IPTVActivity : ComposableActivity() {
 
-    @TvPreview
+    @Previews
     @Composable
     override fun Compose() = super.Compose()
 

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/activity/MainActivity.kt

@@ -11,16 +11,16 @@ package org.mjdev.tvapp.activity
 import androidx.compose.runtime.Composable
 import dagger.hilt.android.AndroidEntryPoint
 import org.mjdev.tvlib.activity.ComposableActivity
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.screen
 import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvapp.ui.screens.MainScreen
 import org.mjdev.tvapp.ui.screens.SplashScreen
+import org.mjdev.tvlib.annotations.Previews
 
 @AndroidEntryPoint
 class MainActivity : ComposableActivity() {
 
-    @TvPreview
+    @Previews
     @Composable
     override fun Compose() = super.Compose()
 

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/activity/WebActivity.kt

@@ -13,10 +13,10 @@ import android.net.Uri
 import androidx.compose.runtime.Composable
 import dagger.hilt.android.AndroidEntryPoint
 import org.mjdev.tvlib.activity.ComposableActivity
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.NavGraphBuilderExt.screen
 import org.mjdev.tvlib.navigation.NavGraphBuilderEx
 import org.mjdev.tvapp.ui.screens.WebScreen
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.NavControllerExt.openAsTop
 import org.mjdev.tvlib.extensions.StringExt.parseUri
 import org.mjdev.tvlib.navigation.NavHostControllerEx
@@ -24,7 +24,7 @@ import org.mjdev.tvlib.navigation.NavHostControllerEx
 @AndroidEntryPoint
 class WebActivity : ComposableActivity() {
 
-    @TvPreview
+    @Previews
     @Composable
     override fun Compose() = super.Compose()
 

+ 1 - 2
app/src/main/kotlin/org/mjdev/tvapp/module/ProvideModule.kt

@@ -39,7 +39,6 @@ import javax.inject.Singleton
 @InstallIn(SingletonComponent::class)
 class ProvideModule {
 
-    private val isDebug = BuildConfig.DEBUG
     private val baseUrl = BuildConfig.IPTV_API_URL
 
     @Singleton
@@ -94,7 +93,7 @@ class ProvideModule {
         httpLoggingInterceptor: HttpLoggingInterceptor
     ): OkHttpClient = OkHttpClient.Builder().apply {
         addNetworkInterceptor(cacheInterceptor)
-        if (isDebug) {
+        if (BuildConfig.DEBUG) {
             addInterceptor(httpLoggingInterceptor)
         }
     }.build()

+ 3 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/AboutPage.kt

@@ -26,7 +26,7 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import org.mjdev.tvapp.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
 import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.card.CardContent
@@ -39,7 +39,7 @@ class AboutPage : Page() {
     override val icon: ImageVector = Icons.Default.Info
 
     @OptIn(ExperimentalTvMaterial3Api::class)
-    @TvPreview
+    @Previews
     @Composable
     override fun Content() {
         Box(
@@ -52,6 +52,7 @@ class AboutPage : Page() {
                 onClick = {},
                 onLongClick = {},
                 shape = CardDefaults.shape(),
+                aspectRatio = null,
                 colors = CardDefaults.colors(
                     containerColor = Color(0xff242424)
                 ),

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

@@ -26,7 +26,6 @@ import org.mjdev.tvapp.activity.IPTVActivity
 import org.mjdev.tvapp.activity.IPTVActivity.Companion.IPTV_DATA
 import org.mjdev.tvapp.data.local.User
 import org.mjdev.tvapp.helpers.AuthManager.Companion.rememberAuthManager
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.HiltExt.appViewModel
 import org.mjdev.tvlib.interfaces.ItemWithId
 import org.mjdev.tvlib.ui.components.page.Page
@@ -36,6 +35,7 @@ import org.mjdev.tvlib.ui.components.tv.LocalAudioRow
 import org.mjdev.tvlib.ui.components.tv.LocalPhotosRow
 import org.mjdev.tvlib.ui.components.tv.LocalVideoRow
 import org.mjdev.tvapp.viewmodel.MainViewModel
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.interfaces.ItemPhoto
 import org.mjdev.tvlib.interfaces.ItemWithBackground
 import org.mjdev.tvlib.interfaces.ItemWithImage
@@ -48,7 +48,7 @@ class MainPage : Page() {
     override val title: Int = R.string.title_home
     override val icon: ImageVector = Icons.Default.Home
 
-    @TvPreview
+    @Previews
     @Composable
     override fun Content() {
         val viewModel: MainViewModel = appViewModel { context ->

+ 3 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/PluginsPage.kt

@@ -25,7 +25,7 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import org.mjdev.tvapp.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.CardContent
 import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.text.TextAny
@@ -37,7 +37,7 @@ class PluginsPage : Page() {
     override val icon: ImageVector = Icons.Default.SettingsInputComponent
 
     @OptIn(ExperimentalTvMaterial3Api::class)
-    @TvPreview
+    @Previews
     @Composable
     override fun Content() {
         Box(
@@ -50,6 +50,7 @@ class PluginsPage : Page() {
                 onLongClick = {},
                 modifier = Modifier.fillMaxSize(),
                 shape = CardDefaults.shape(),
+                aspectRatio = null,
                 colors = CardDefaults.colors(
                     containerColor = Color(0xff242424)
                 ),

+ 3 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/pages/SubscriptionPage.kt

@@ -25,7 +25,7 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import org.mjdev.tvapp.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.Card
 import org.mjdev.tvlib.ui.components.page.Page
 import org.mjdev.tvlib.ui.components.card.CardContent
@@ -37,7 +37,7 @@ class SubscriptionPage : Page() {
     override val icon: ImageVector = Icons.Default.ShoppingCart
 
     @OptIn(ExperimentalTvMaterial3Api::class)
-    @TvPreview
+    @Previews
     @Composable
     override fun Content() {
         Box(
@@ -50,6 +50,7 @@ class SubscriptionPage : Page() {
                 onLongClick = {},
                 modifier = Modifier.fillMaxSize(),
                 shape = CardDefaults.shape(),
+                aspectRatio = null,
                 colors = CardDefaults.colors(
                     containerColor = Color(0xff242424)
                 ),

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/DetailScreen.kt

@@ -20,7 +20,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.navigation.navArgument
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.viewmodel.DetailViewModel
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.HiltExt.appViewModel
 import org.mjdev.tvlib.extensions.ListExt.indexOf
 import org.mjdev.tvlib.extensions.MediaItemExt.uri
@@ -45,7 +45,7 @@ class DetailScreen : Screen() {
         }
     )
 
-    @TvPreview
+    @Previews
     @Composable
     override fun ComposeScreen() {
 

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/IPTVScreen.kt

@@ -22,7 +22,7 @@ import androidx.media3.common.MediaItem
 import androidx.navigation.navArgument
 import org.mjdev.tvapp.R
 import org.mjdev.tvapp.viewmodel.IPTVViewModel
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.HiltExt.appViewModel
 import org.mjdev.tvlib.navigation.AnyType
 import org.mjdev.tvlib.screen.Screen
@@ -48,7 +48,7 @@ class IPTVScreen : Screen() {
         }
     )
 
-    @TvPreview
+    @Previews
     @Composable
     override fun ComposeScreen() {
 

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/LoadingScreen.kt

@@ -23,7 +23,7 @@ import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.sp
 import org.mjdev.tvapp.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.screen.Screen
 import org.mjdev.tvlib.ui.components.text.TextAny
 
@@ -34,7 +34,7 @@ class LoadingScreen : Screen() {
     override val immersive: Boolean = true
     override val showOnce: Boolean = true
 
-    @TvPreview
+    @Previews
     @Composable
     override fun ComposeScreen() {
         Box(

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

@@ -17,7 +17,7 @@ import org.mjdev.tvapp.ui.pages.AboutPage
 import org.mjdev.tvapp.ui.pages.MainPage
 import org.mjdev.tvapp.ui.pages.PluginsPage
 import org.mjdev.tvapp.ui.pages.SubscriptionPage
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.screen.ScreenWithPages
 import org.mjdev.tvlib.ui.components.page.PagerScope
 import org.mjdev.tvlib.ui.components.page.SearchPage
@@ -29,7 +29,7 @@ class MainScreen : ScreenWithPages() {
     override val menuIcon: ImageVector = Icons.Default.Home
     override val immersive: Boolean = false
 
-    @TvPreview
+    @Previews
     @Composable
     override fun Compose() = super.Compose()
 

+ 4 - 9
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/SplashScreen.kt

@@ -33,7 +33,7 @@ import com.airbnb.lottie.compose.rememberLottieComposition
 import com.google.accompanist.permissions.ExperimentalPermissionsApi
 import kotlinx.coroutines.delay
 import org.mjdev.tvapp.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.NavControllerExt.openAsTop
 import org.mjdev.tvlib.permission.rememberPermissionManager
@@ -48,7 +48,7 @@ class SplashScreen : Screen() {
     override val immersive: Boolean = true
 
     @OptIn(ExperimentalPermissionsApi::class)
-    @TvPreview
+    @Previews
     @Composable
     override fun ComposeScreen() {
 
@@ -66,7 +66,7 @@ class SplashScreen : Screen() {
             contentAlignment = Alignment.Center
         ) {
             LottieAnimation(
-                modifier = Modifier.padding(120.dp) ,
+                modifier = Modifier.padding(120.dp),
                 composition = composition.value,
                 progress = {
                     progress.value
@@ -76,12 +76,7 @@ class SplashScreen : Screen() {
         Box(
             modifier = Modifier
                 .fillMaxSize()
-                .padding(
-                    0.dp,
-                    0.dp,
-                    0.dp,
-                    4.dp
-                ),
+                .padding(0.dp, 0.dp, 0.dp, 4.dp),
             contentAlignment = Alignment.BottomCenter
         ) {
             TextAny(

+ 2 - 2
app/src/main/kotlin/org/mjdev/tvapp/ui/screens/WebScreen.kt

@@ -21,7 +21,7 @@ import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.navigation.navArgument
 import org.mjdev.tvapp.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.navigation.AnyType
 import org.mjdev.tvlib.screen.Screen
 import org.mjdev.tvlib.ui.components.web.WebView
@@ -42,7 +42,7 @@ class WebScreen : Screen() {
         }
     )
 
-    @TvPreview
+    @Previews
     @Composable
     override fun ComposeScreen() {
 

+ 1 - 0
settings.gradle.kts

@@ -18,6 +18,7 @@ pluginManagement {
         jcenter()
         maven(url = "https://plugins.gradle.org/m2/")
         maven(url = "https://mvn.dailymotion.com/repository/releases/")
+        maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
     }
 }
 

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/activity/ComposableActivity.kt

@@ -32,7 +32,7 @@ import androidx.tv.material3.NonInteractiveSurfaceDefaults
 import androidx.tv.material3.Surface
 import com.github.anrwatchdog.ANRWatchDog
 import org.mjdev.tvlib.BuildConfig
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ContextExt.isATv
 import org.mjdev.tvlib.extensions.ModifierExt.detectSwipe
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
@@ -72,7 +72,7 @@ open class ComposableActivity : ComponentActivity() {
             }
     }
 
-    @TvPreview
+    @Previews
     @OptIn(ExperimentalTvMaterial3Api::class)
     @Composable
     @CallSuper

+ 48 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/annotations/Preview.kt

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) Milan Jurkulák 2023.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package org.mjdev.tvlib.annotations
+
+import androidx.compose.ui.tooling.preview.Devices
+import androidx.compose.ui.tooling.preview.Preview
+
+//@Preview(
+//    uiMode = UI_MODE_TYPE_TELEVISION,
+//    showBackground = true,
+//    device = Devices.TV_720p,
+//    showSystemUi = false,
+//    backgroundColor = 0xFF444444,
+//    wallpaper = GREEN_DOMINATED_EXAMPLE
+//)
+//annotation class TvPreview
+
+@Preview(
+    name = "Landscape",
+    group = "device",
+    device = Devices.AUTOMOTIVE_1024p,
+    showBackground = true,
+    backgroundColor = 0xFF444444,
+    widthDp = 800,
+    heightDp = 480
+)
+annotation class PreviewLandscape
+
+@Preview(
+    name = "Portrait",
+    group = "device",
+    showBackground = true,
+    device = Devices.PIXEL_7,
+    backgroundColor = 0xFF444444,
+    widthDp = 480,
+    heightDp = 800
+)
+annotation class PreviewPortrait
+
+@PreviewPortrait
+@PreviewLandscape
+annotation class Previews

+ 0 - 24
tvlib/src/main/kotlin/org/mjdev/tvlib/annotations/TvPreview.kt

@@ -1,24 +0,0 @@
-/*
- * Copyright (c) Milan Jurkulák 2023.
- *  Contact:
- *  e: mimoccc@gmail.com
- *  e: mj@mjdev.org
- *  w: https://mjdev.org
- */
-
-package org.mjdev.tvlib.annotations
-
-import android.content.res.Configuration.UI_MODE_TYPE_TELEVISION
-import androidx.compose.ui.tooling.preview.Devices
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.tooling.preview.Wallpapers.GREEN_DOMINATED_EXAMPLE
-
-@Preview(
-    uiMode = UI_MODE_TYPE_TELEVISION,
-    showBackground = true,
-    device = Devices.TV_720p,
-    showSystemUi = false,
-    backgroundColor = 0xFF444444,
-    wallpaper = GREEN_DOMINATED_EXAMPLE
-)
-annotation class TvPreview

+ 10 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/GlobalExt.kt

@@ -17,6 +17,8 @@ import com.skydoves.sandwich.onException
 import com.skydoves.sandwich.toFlow
 import kotlinx.coroutines.flow.Flow
 import timber.log.Timber
+import java.net.MalformedURLException
+import java.net.URL
 
 @Suppress("unused")
 object GlobalExt {
@@ -59,4 +61,12 @@ object GlobalExt {
         Result.failure(e)
     }
 
+    @Suppress("SENSELESS_COMPARISON")
+    val String.isUrl:Boolean
+        get() = try {
+            URL(this) != null
+        } catch (e: MalformedURLException) {
+            false
+        }
+
 }

+ 35 - 9
tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/ModifierExt.kt

@@ -6,6 +6,8 @@
  *  w: https://mjdev.org
  */
 
+@file:Suppress("unused")
+
 package org.mjdev.tvlib.extensions
 
 import android.annotation.SuppressLint
@@ -15,6 +17,7 @@ import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.relocation.BringIntoViewResponder
 import androidx.compose.foundation.relocation.bringIntoViewResponder
+import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.MutableIntState
 import androidx.compose.runtime.MutableState
@@ -44,6 +47,8 @@ import androidx.compose.ui.platform.debugInspectorInfo
 import androidx.compose.ui.unit.dp
 import kotlinx.coroutines.delay
 import org.mjdev.tvlib.BuildConfig
+import org.mjdev.tvlib.extensions.ComposeExt.isLandscapeMode
+import org.mjdev.tvlib.extensions.ComposeExt.isPortraitMode
 import timber.log.Timber
 import java.lang.Float.min
 import kotlin.math.abs
@@ -51,15 +56,32 @@ import kotlin.math.abs
 @Suppress("MemberVisibilityCanBePrivate")
 object ModifierExt {
 
-    // used to debug library
-    val isDebug: Boolean = BuildConfig.DEBUG
-
-    // used to debug composable in library
-    val isComposeDebug: Boolean = BuildConfig.IS_COMPOSE_DEBUG
-
+    @Composable
     fun Modifier.conditional(
         condition: Boolean,
-        other: Modifier.() -> Modifier
+        other: @Composable Modifier.() -> Modifier
+    ): Modifier {
+        return when (condition) {
+            true -> this.then(other.invoke(this))
+            else -> this
+        }
+    }
+
+    @Composable
+    fun Modifier.onlyPortrait(
+        condition: Boolean = isPortraitMode(),
+        other: @Composable Modifier.() -> Modifier
+    ): Modifier {
+        return when (condition) {
+            true -> this.then(other.invoke(this))
+            else -> this
+        }
+    }
+
+    @Composable
+    fun Modifier.onlyLandscape(
+        condition: Boolean = isLandscapeMode(),
+        other: @Composable Modifier.() -> Modifier
     ): Modifier {
         return when (condition) {
             true -> this.then(other.invoke(this))
@@ -67,9 +89,10 @@ object ModifierExt {
         }
     }
 
+    @Composable
     fun Modifier.tvAspectRatio(
         ratio: Float?,
-        matchHeightConstraintsFirst: Boolean = false
+        matchHeightConstraintsFirst: Boolean = isLandscapeMode()
     ): Modifier = conditional(ratio != null) {
         aspectRatio(
             ratio!!,
@@ -104,8 +127,11 @@ object ModifierExt {
         )
     }
 
+    @Composable
     @Stable
-    fun Modifier.recomposeHighlighter(): Modifier = conditional(
+    fun Modifier.recomposeHighlighter(
+        isComposeDebug: Boolean = BuildConfig.DEBUG
+    ): Modifier = conditional(
         isComposeDebug
     ) {
         this.then(recomposeModifier)

+ 11 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/extensions/StringExt.kt

@@ -10,10 +10,21 @@ package org.mjdev.tvlib.extensions
 
 import android.net.Uri
 
+@Suppress("unused")
 object StringExt {
 
     fun String.asException() = Exception(this)
 
     fun String.parseUri(): Uri = Uri.parse(this)
 
+    fun List<String>.removeEmptyLines(): List<String> =
+        filter { line -> line.isNotEmpty() }
+
+    fun List<String>.removeComments(
+        vararg startTagChars: Char
+    ): List<String> =
+        filter { line -> (!startTagChars.contains(line[0])) }
+
+    fun List<String>.trimLines() = map { line -> line.trim() }
+
 }

+ 37 - 37
tvlib/src/main/kotlin/org/mjdev/tvlib/helpers/other/Observed.kt

@@ -1,37 +1,37 @@
-/*
- *  Copyright (c) Milan Jurkulák 2023.
- *  Contact:
- *  e: mimoccc@gmail.com
- *  e: mj@mjdev.org
- *  w: https://mjdev.org
- */
-
-@file:Suppress("unused")
-
-package org.mjdev.tvlib.helpers.other
-
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-
-open class Observed<T>(
-    initial: T
-) : MutableState<T> {
-
-    private var _value by mutableStateOf(initial)
-
-    override var value: T = initial
-        get() = _value
-        set(value) {
-            _value = value
-            field = value
-        }
-
-    override fun component1(): T = value
-
-    override fun component2(): (T) -> Unit = { v ->
-        value = v
-    }
-
-}
+///*
+// *  Copyright (c) Milan Jurkulák 2023.
+// *  Contact:
+// *  e: mimoccc@gmail.com
+// *  e: mj@mjdev.org
+// *  w: https://mjdev.org
+// */
+//
+//@file:Suppress("unused")
+//
+//package org.mjdev.tvlib.helpers.other
+//
+//import androidx.compose.runtime.MutableState
+//import androidx.compose.runtime.getValue
+//import androidx.compose.runtime.mutableStateOf
+//import androidx.compose.runtime.setValue
+//
+//open class Observed<T>(
+//    initial: T
+//) : MutableState<T> {
+//
+//    private var _value by mutableStateOf(initial)
+//
+//    override var value: T = initial
+//        get() = _value
+//        set(value) {
+//            _value = value
+//            field = value
+//        }
+//
+//    override fun component1(): T = value
+//
+//    override fun component2(): (T) -> Unit = { v ->
+//        value = v
+//    }
+//
+//}

+ 6 - 3
tvlib/src/main/kotlin/org/mjdev/tvlib/screen/Screen.kt

@@ -33,7 +33,8 @@ import androidx.navigation.NamedNavArgument
 import androidx.navigation.NavBackStackEntry
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Text
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.extensions.ModifierExt.onlyPortrait
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
 import org.mjdev.tvlib.navigation.MenuItem
 import org.mjdev.tvlib.navigation.NavHostControllerEx
@@ -72,7 +73,7 @@ open class Screen {
     var backStackEntry: NavBackStackEntry? = null
     var args: Map<String, Any?> = emptyMap()
 
-    @TvPreview
+    @Previews
     @Composable
     @CallSuper
     open fun Compose() {
@@ -97,7 +98,9 @@ open class Screen {
         Box(
             modifier = Modifier
                 .fillMaxSize()
-                .navigationBarsPadding()
+                .onlyPortrait {
+                    navigationBarsPadding()
+                }
                 .statusBarsPadding()
         ) {
             ComposeScreen()

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/screen/ScreenWithPages.kt

@@ -9,7 +9,7 @@
 package org.mjdev.tvlib.screen
 
 import androidx.compose.runtime.Composable
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
 import org.mjdev.tvlib.ui.components.page.Page.Companion.EMPTY_PAGE
 import org.mjdev.tvlib.ui.components.page.PagerScope
@@ -23,7 +23,7 @@ open class ScreenWithPages : Screen() {
         page(EMPTY_PAGE)
     }
 
-    @TvPreview
+    @Previews
     @Composable
     override fun ComposeScreen() {
         val navController = navController ?: rememberNavControllerEx()

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/button/Button.kt

@@ -22,7 +22,6 @@ import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
@@ -33,6 +32,7 @@ import androidx.tv.material3.ButtonGlow
 import androidx.tv.material3.ButtonScale
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Glow
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusState
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.text.TextAny
@@ -41,7 +41,7 @@ import org.mjdev.tvlib.ui.components.text.TextAny
 @Suppress("UNUSED_PARAMETER")
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun Button(
     text: Any? = "test",

+ 6 - 3
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/Card.kt

@@ -23,7 +23,6 @@ import androidx.compose.ui.composed
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
 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 androidx.tv.material3.Border
@@ -35,12 +34,14 @@ import androidx.tv.material3.CardScale
 import androidx.tv.material3.CardShape
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Glow
+import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.extensions.ModifierExt.conditional
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.ModifierExt.tvAspectRatio
 
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun Card(
     modifier: Modifier = Modifier,
@@ -64,7 +65,9 @@ fun Card(
     modifier = modifier
         .recomposeHighlighter()
         .widthIn(max = 320.dp)
-        .tvAspectRatio(aspectRatio)
+        .conditional(aspectRatio != null) {
+            tvAspectRatio(aspectRatio)
+        }
         .clickable {
             onClick()
         },

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/CardContent.kt

@@ -13,15 +13,15 @@ import androidx.compose.foundation.layout.Column
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.MaterialTheme
 import androidx.tv.material3.ProvideTextStyle
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.text.AutoHideEmptyText
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun CardContent(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/ItemCard.kt

@@ -18,7 +18,6 @@ import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardBorder
@@ -28,6 +27,7 @@ import androidx.tv.material3.CardGlow
 import androidx.tv.material3.CardScale
 import androidx.tv.material3.CardShape
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
@@ -40,7 +40,7 @@ import org.mjdev.tvlib.ui.components.image.ImageAny
 
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun ItemCard(
     item: Any? = null,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/PhotoCard.kt

@@ -19,12 +19,12 @@ import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardDefaults
 import androidx.tv.material3.CardScale
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.extensions.ComposeExt.isFocused
@@ -37,7 +37,7 @@ import org.mjdev.tvlib.ui.components.image.PhotoImage
 
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun PhotoCard(
     item: Any? = null,

+ 6 - 4
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/card/PreviewCard.kt

@@ -26,7 +26,6 @@ import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalLifecycleOwner
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.AndroidView
 import androidx.lifecycle.Lifecycle
@@ -50,6 +49,7 @@ import coil.compose.AsyncImage
 import coil.compose.rememberAsyncImagePainter
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.ModifierExt.tvAspectRatio
 
@@ -57,7 +57,7 @@ import org.mjdev.tvlib.extensions.ModifierExt.tvAspectRatio
 @OptIn(ExperimentalTvMaterial3Api::class)
 @Suppress("unused")
 @UnstableApi
-@Preview
+@Previews
 @Composable
 fun PreviewCard(
     modifier: Modifier = Modifier,
@@ -134,7 +134,9 @@ fun PreviewCard(
                 lifecycle.removeObserver(observer)
             }
         }
-        Crossfade(targetState = hasFocus, animationSpec = tween(durationMillis = 700)) { focused ->
+        Crossfade(targetState = hasFocus, animationSpec = tween(durationMillis = 700),
+            label = ""
+        ) { focused ->
             if (focused) {
                 Box {
                     AndroidView(
@@ -172,7 +174,7 @@ fun PreviewCard(
     }
 }
 
-@Preview
+@Previews
 @Composable
 fun PreviewThumbnail(
     thumbnail: String? = "",

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/carousel/BigCarousel.kt

@@ -20,10 +20,10 @@ import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.LocalConfiguration
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardScale
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusState
 import org.mjdev.tvlib.extensions.ModifierExt.detectSwipe
@@ -32,7 +32,7 @@ import org.mjdev.tvlib.ui.components.card.FocusHelper
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @SuppressLint("AutoboxingStateValueProperty")
-@Preview
+@Previews
 @Composable
 fun BigCarousel(
     modifier: Modifier = Modifier,

+ 4 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/carousel/Carousel.kt

@@ -35,6 +35,7 @@ import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isFocused
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
 import org.mjdev.tvlib.extensions.ModifierExt.bringIntoViewIfChildrenAreFocused
@@ -47,9 +48,10 @@ import org.mjdev.tvlib.ui.components.carousel.ModifierExt.handleKeyEvents
 @OptIn(ExperimentalComposeUiApi::class)
 @SuppressLint("ServiceCast")
 @Suppress("IllegalExperimentalApiUsage")
+@Previews
 @Composable
 fun Carousel(
-    itemCount: Int,
+    itemCount: Int=0,
     modifier: Modifier = Modifier,
     carouselState: CarouselState = remember { CarouselState() },
     autoScrollDurationMillis: Long = CarouselDefaults.TimeToDisplayItemMillis,
@@ -66,7 +68,7 @@ fun Carousel(
     },
     isAutoScrollActive: MutableState<Boolean> = remember { mutableStateOf(false) },
     focusState: MutableState<FocusState?> = remember { mutableStateOf(null) },
-    content: @Composable AnimatedContentScope.(index: Int) -> Unit
+    content: @Composable AnimatedContentScope.(index: Int) -> Unit = {}
 ) {
 
     CarouselStateUpdater(carouselState, itemCount)

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/carousel/CarouselCard.kt

@@ -17,10 +17,10 @@ import androidx.compose.runtime.MutableState
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardScale
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusState
 import org.mjdev.tvlib.extensions.ModifierExt.conditional
@@ -34,7 +34,7 @@ import org.mjdev.tvlib.ui.components.image.ImageAny
 
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun CarouselCard(
     item: Any? = null,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/FocusableBox.kt

@@ -19,13 +19,13 @@ import androidx.compose.ui.focus.FocusState
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
 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 androidx.tv.material3.Border
 import androidx.tv.material3.ClickableSurfaceDefaults
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Surface
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isFocused
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusState
@@ -34,7 +34,7 @@ import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.ModifierExt.requestFocusOnTouch
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun FocusableBox(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/FocusableCard.kt

@@ -26,7 +26,6 @@ import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.CardBorder
@@ -38,6 +37,7 @@ import androidx.tv.material3.CardShape
 import androidx.tv.material3.CompactCard
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.MaterialTheme
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ComposeExt.isFocused
@@ -60,7 +60,7 @@ import org.mjdev.tvlib.ui.components.text.TextAny
 
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun FocusableCard(
     item: Any? = null,

+ 9 - 6
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/VerticalScrollableBox.kt

@@ -20,36 +20,39 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
+import org.mjdev.tvlib.extensions.ComposeExt.isLandscapeMode
 import org.mjdev.tvlib.extensions.ModifierExt.conditional
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.ModifierExt.tvAspectRatio
 
 @SuppressLint("AutoboxingStateValueProperty")
-@Preview
+@Previews
 @Composable
 fun VerticalScrollableBox(
     modifier: Modifier = Modifier,
     contentAlignment: Alignment = Alignment.TopStart,
-    propagateMinConstraints: Boolean = false,
+    propagateMinConstraints: Boolean = isLandscapeMode(),
     state: TvLazyListState? = null,
     content: @Composable BoxScope.() -> Unit = {}
 ) {
     val isEdit = isEditMode()
     val scrollDelta = remember { mutableFloatStateOf(0f) }
     Box(
-        modifier = modifier.recomposeHighlighter()
+        modifier = modifier
             .conditional(isEdit) {
-                tvAspectRatio(16f / 9f).defaultMinSize(80.dp)
+                defaultMinSize(80.dp)
+                    .tvAspectRatio(16f / 9f).defaultMinSize(80.dp)
             }
             .pointerInput(Unit) {
                 detectDragGestures { _, dragAmount ->
                     scrollDelta.value = dragAmount.y
                 }
-            },
+            }
+            .recomposeHighlighter(),
         contentAlignment = contentAlignment,
         propagateMinConstraints = propagateMinConstraints,
     ) {

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/complex/XmlLayout.kt

@@ -18,10 +18,10 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.viewinterop.AndroidView
 import androidx.core.view.allViews
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 
 @SuppressLint("PrivateResource")
-@TvPreview
+@Previews
 @Composable
 fun XmlLayout(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/gallery/Gallery.kt

@@ -55,7 +55,7 @@ import androidx.tv.foundation.lazy.list.itemsIndexed
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import kotlinx.coroutines.delay
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
 import org.mjdev.tvlib.extensions.GlobalExt.toggle
 import org.mjdev.tvlib.extensions.ModifierExt.detectSwipe
@@ -70,7 +70,7 @@ import org.mjdev.tvlib.ui.components.tv.TVRow
 import timber.log.Timber
 
 @OptIn(ExperimentalTvMaterial3Api::class, ExperimentalAnimationApi::class)
-@TvPreview
+@Previews
 @Composable
 fun Gallery(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/gallery/ItemInfo.kt

@@ -29,7 +29,7 @@ import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ColorExt.invert
 import org.mjdev.tvlib.helpers.media.MetadataRetriever
 import org.mjdev.tvlib.helpers.media.MetadataRetriever.Companion.rememberMetaDataRetriever
@@ -38,7 +38,7 @@ import org.mjdev.tvlib.interfaces.ItemWithTitle
 import org.mjdev.tvlib.ui.components.text.AutoHideEmptyText
 import org.mjdev.tvlib.ui.components.image.ImageBackground
 
-@TvPreview
+@Previews
 @Composable
 fun ItemInfo(
     src: Any? = null,

+ 4 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/gridview/TvGridView.kt

@@ -23,17 +23,19 @@ import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
 import androidx.tv.foundation.lazy.grid.items
 import androidx.tv.foundation.lazy.grid.rememberTvLazyGridState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt
 import org.mjdev.tvlib.extensions.ComposeExt.isPortraitMode
 import org.mjdev.tvlib.ui.components.card.PhotoCard
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun TvGridView(
     modifier: Modifier = Modifier,
     items: List<Any?> = listOf(
+        Unit, Unit, Unit,
+        Unit, Unit, Unit,
         Unit, Unit, Unit,
         Unit, Unit, Unit,
         Unit, Unit, Unit,

+ 5 - 3
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/icon/IconAny.kt

@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.BoxWithConstraints
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Menu
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.ColorFilter
@@ -24,18 +25,18 @@ import androidx.compose.ui.graphics.ImageBitmap
 import androidx.compose.ui.graphics.asImageBitmap
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Icon
 import androidx.tv.material3.LocalContentColor
 import coil.compose.AsyncImage
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.DrawableExt.asImageBitmap
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import java.net.URL
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @SuppressLint("ModifierParameter")
-@Preview
+@Previews
 @Composable
 fun IconAny(
     modifier: Modifier = Modifier,
@@ -43,7 +44,8 @@ fun IconAny(
     contentDescription: String? = null,
     tint: Color = LocalContentColor.current
 ) = BoxWithConstraints(
-    modifier = modifier
+    modifier = modifier,
+    contentAlignment = Alignment.Center
 ) {
 
     val width = constraints.minWidth

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/CircleImage.kt

@@ -22,14 +22,14 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 
 @SuppressLint("ModifierParameter")
-@Preview
+@Previews
 @Composable
 fun CircleImage(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/FadingPhotoImage.kt

@@ -27,9 +27,9 @@ import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import kotlinx.coroutines.delay
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 
-@TvPreview
+@Previews
 @Composable
 fun FadingPhotoImage(
     modifier: Modifier = Modifier,

+ 4 - 3
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/ImageAny.kt

@@ -28,18 +28,18 @@ import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.skydoves.landscapist.ImageOptions
 import com.skydoves.landscapist.coil.CoilImage
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.rememberImageLoader
 import org.mjdev.tvlib.extensions.DrawableExt.asImageBitmap
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import java.net.URL
 
 @SuppressLint("ModifierParameter")
-@Preview
+@Previews
 @Composable
 fun ImageAny(
     modifier: Modifier = Modifier,
@@ -50,7 +50,8 @@ fun ImageAny(
     alpha: Float = DefaultAlpha,
     colorFilter: ColorFilter? = null,
 ) = BoxWithConstraints(
-    modifier = modifier
+    modifier = modifier,
+    contentAlignment = Alignment.Center
 ) {
 
     val imageLoader = rememberImageLoader()

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/ImageBackground.kt

@@ -25,7 +25,7 @@ import androidx.compose.ui.platform.LocalContext
 import androidx.core.graphics.drawable.toBitmap
 import coil.request.CachePolicy
 import coil.request.ImageRequest
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.BitmapExt.majorColor
 import org.mjdev.tvlib.extensions.ComposeExt.rememberImageLoader
 import org.mjdev.tvlib.extensions.ModifierExt.conditional
@@ -33,7 +33,7 @@ import org.mjdev.tvlib.interfaces.ItemPhoto
 import org.mjdev.tvlib.interfaces.ItemWithBackground
 import org.mjdev.tvlib.interfaces.ItemWithImage
 
-@TvPreview
+@Previews
 @Composable
 fun ImageBackground(
     modifier: Modifier = Modifier,

+ 4 - 3
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/image/PhotoImage.kt

@@ -27,7 +27,6 @@ import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.asAndroidBitmap
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toDrawable
@@ -35,6 +34,7 @@ import com.skydoves.landscapist.ImageOptions
 import com.skydoves.landscapist.coil.CoilImage
 import com.skydoves.landscapist.coil.CoilImageState
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.BitmapExt.majorColor
 import org.mjdev.tvlib.extensions.ColorExt.contrastAndBrightness
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
@@ -45,7 +45,7 @@ import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import timber.log.Timber
 
 @SuppressLint("ModifierParameter")
-@Preview
+@Previews
 @Composable
 fun PhotoImage(
     src: Any? = null,
@@ -90,9 +90,10 @@ fun PhotoImage(
             src
         },
         modifier = modifier
+            .defaultMinSize(80.dp)
             .recomposeHighlighter()
             .conditional(isEdit) {
-                aspectRatio(16f / 9f).defaultMinSize(80.dp)
+                aspectRatio(16f / 9f)
             }
             .border(
                 BorderStroke(borderSize, borderColor),

+ 9 - 3
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/immersivelist/ImmersiveList.kt

@@ -8,6 +8,7 @@
 
 package org.mjdev.tvlib.ui.components.immersivelist
 
+import android.annotation.SuppressLint
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableIntState
@@ -22,19 +23,24 @@ import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.onFocusChanged
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.bringIntoViewIfChildrenAreFocused
 
+@Previews
+@SuppressLint("ModifierParameter")
 @Suppress("IllegalExperimentalApiUsage")
 @OptIn(ExperimentalComposeUiApi::class)
 @ExperimentalTvMaterial3Api
 @Composable
 fun ImmersiveList(
-    background: @Composable ImmersiveListBackgroundScope.(index: Int, listHasFocus: Boolean) -> Unit,
-    modifier: Modifier = Modifier,
+    background: @Composable ImmersiveListBackgroundScope.(
+        index: Int, listHasFocus: Boolean
+    ) -> Unit = { idx, focus -> },
+     modifier: Modifier = Modifier,
     listAlignment: Alignment = Alignment.BottomEnd,
     currentItemIndex: MutableIntState = remember { mutableIntStateOf(0) },
     listHasFocus: MutableState<Boolean> = remember { mutableStateOf(false) },
-    list: @Composable ImmersiveListScope.() -> Unit,
+    list: @Composable ImmersiveListScope.() -> Unit = {},
 ) {
     Box(
         modifier.bringIntoViewIfChildrenAreFocused()

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/media/MediaPlayerContainer.kt

@@ -16,12 +16,12 @@ import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.ui.Modifier
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.media.MediaPlayerState.Companion.rememberMediaPlayerState
 
 @SuppressLint("UnsafeOptInUsageError")
-@TvPreview
+@Previews
 @Composable
 fun MediaPlayerContainer(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/media/PlayerControlView.kt

@@ -10,11 +10,11 @@ package org.mjdev.tvlib.ui.components.media
 
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.media.MediaPlayerState.Companion.rememberMediaPlayerState
 
 // todo new ui
-@TvPreview
+@Previews
 @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
 @Composable
 fun PlayerControlView(

+ 3 - 4
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/DrawerSheet.kt

@@ -9,7 +9,6 @@
 package org.mjdev.tvlib.ui.components.navigation
 
 import androidx.compose.animation.animateContentSize
-import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.focusGroup
 import androidx.compose.foundation.layout.Box
@@ -30,12 +29,12 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.material3.DrawerState
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
 
 @Suppress("IllegalExperimentalApiUsage")
-@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalFoundationApi::class)
-@TvPreview
+@OptIn(ExperimentalTvMaterial3Api::class)
+@Previews
 @Composable
 fun DrawerSheet(
     modifier: Modifier = Modifier,

+ 6 - 4
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/ModalNavigationDrawer.kt

@@ -32,11 +32,11 @@ import androidx.tv.material3.DrawerState
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.rememberDrawerState
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 
 @ExperimentalTvMaterial3Api
-@TvPreview
+@Previews
 @Composable
 fun ModalNavigationDrawer(
     modifier: Modifier = Modifier,
@@ -89,14 +89,16 @@ fun ModalNavigationDrawer(
         )
         Box(
             modifier = when (contentAlignment) {
-                Alignment.TopStart -> Modifier.padding(
+                Alignment.TopStart -> Modifier
+                    .padding(
                     closedDrawerWidth.value ?: closeDrawerWidth,
                     0.dp,
                     0.dp,
                     0.dp
                 )
 
-                Alignment.TopEnd -> Modifier.padding(
+                Alignment.TopEnd -> Modifier
+                    .padding(
                     0.dp,
                     0.dp,
                     closedDrawerWidth.value ?: closeDrawerWidth,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavDrawerContent.kt

@@ -24,9 +24,9 @@ import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isClosed
 import org.mjdev.tvlib.extensions.ComposeExt.isPortraitMode
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
@@ -37,7 +37,7 @@ import org.mjdev.tvlib.navigation.NavHostControllerEx
 
 @SuppressLint("AutoboxingStateValueProperty")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun NavDrawerContent(
     backgroundColor: Color = Color.DarkGray,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavHostEx.kt

@@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.ContentScale
 import androidx.navigation.NavBackStackEntry
 import androidx.navigation.compose.NavHost
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.NavExt.createGraph
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
@@ -33,7 +33,7 @@ import org.mjdev.tvlib.ui.components.image.FadingPhotoImage
 import org.mjdev.tvlib.ui.components.screen.EmptyScreen
 import org.mjdev.tvlib.ui.components.screen.ScreenView
 
-@TvPreview
+@Previews
 @Composable
 fun NavHostEx(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/Navigation.kt

@@ -18,7 +18,7 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ComposeExt.isPortraitMode
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
@@ -29,7 +29,7 @@ import org.mjdev.tvlib.ui.components.page.Page
 
 @SuppressLint("AutoboxingStateValueProperty")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun Navigation(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavigationDrawer.kt

@@ -22,11 +22,11 @@ import androidx.tv.material3.DrawerState
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.rememberDrawerState
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 
 @ExperimentalTvMaterial3Api
-@TvPreview
+@Previews
 @Composable
 fun NavigationDrawer(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/NavigationRow.kt

@@ -39,7 +39,7 @@ import androidx.tv.material3.DrawerState
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.rememberDrawerState
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ComposeExt.isFocused
 import org.mjdev.tvlib.extensions.ComposeExt.isLandscapeMode
@@ -56,7 +56,7 @@ import org.mjdev.tvlib.ui.components.text.TextAny
 import timber.log.Timber
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun NavigationRow(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/SettingsDrawer.kt

@@ -17,11 +17,11 @@ import androidx.tv.material3.DrawerState
 import androidx.tv.material3.DrawerValue
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.rememberDrawerState
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun SettingsDrawer(
     modifier: Modifier = Modifier,

+ 1 - 1
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/navigation/SettingsDrawerContent.kt

@@ -30,7 +30,7 @@ fun SettingsDrawerContent(
     modifier: Modifier = Modifier
 ) {
     Column(
-        modifier = Modifier
+        modifier = modifier
             .recomposeHighlighter()
             .fillMaxHeight()
             .conditional(isEditMode()) {

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/Page.kt

@@ -21,7 +21,7 @@ import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.sp
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusRequester
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.ModifierExt.requestFocusOnTouch
@@ -37,7 +37,7 @@ open class Page {
     open val icon: Any? = null
 
     @SuppressLint("ComposableNaming")
-    @TvPreview
+    @Previews
     @Composable
     @CallSuper
     fun content() {

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/SearchPage.kt

@@ -13,7 +13,7 @@ import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Search
 import androidx.compose.runtime.Composable
 import org.mjdev.tvlib.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 
 open class SearchPage : Page() {
 
@@ -21,7 +21,7 @@ open class SearchPage : Page() {
     override val icon: Any? = Icons.Default.Search
 
     @SuppressLint("ComposableNaming")
-    @TvPreview
+    @Previews
     @Composable
     override fun Content() = super.Content()
 

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/SettingsPage.kt

@@ -13,7 +13,7 @@ import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Settings
 import androidx.compose.runtime.Composable
 import org.mjdev.tvlib.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 
 open class SettingsPage : Page() {
 
@@ -21,7 +21,7 @@ open class SettingsPage : Page() {
     override val icon: Any? = Icons.Default.Settings
 
     @SuppressLint("ComposableNaming")
-    @TvPreview
+    @Previews
     @Composable
     override fun Content() = super.Content()
 

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/page/TvPager.kt

@@ -30,7 +30,7 @@ import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import kotlinx.coroutines.launch
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
 import org.mjdev.tvlib.navigation.MenuItemClickListener
@@ -39,7 +39,7 @@ import org.mjdev.tvlib.navigation.NavHostControllerEx
 import org.mjdev.tvlib.ui.components.page.Page.Companion.EMPTY_PAGE
 
 @SuppressLint("AutoboxingStateValueProperty", "UnusedContentLambdaTargetStateParameter")
-@TvPreview
+@Previews
 @Composable
 fun TvPager(
     navController: NavHostControllerEx = rememberNavControllerEx(),

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/screen/EmptyScreen.kt

@@ -9,14 +9,14 @@
 package org.mjdev.tvlib.ui.components.screen
 
 import androidx.compose.runtime.Composable
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.screen.Screen
 
 internal class EmptyScreen : Screen() {
 
     override val route: String = ROUTE_NONE
 
-    @TvPreview
+    @Previews
     @Composable
     override fun Compose() = super.Compose()
 

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/screen/ScreenView.kt

@@ -13,7 +13,7 @@ import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.NavExt.rememberNavControllerEx
 import org.mjdev.tvlib.navigation.NavHostControllerEx
@@ -21,7 +21,7 @@ import org.mjdev.tvlib.ui.components.navigation.Navigation
 import org.mjdev.tvlib.ui.components.page.Page
 
 @Suppress("TrailingComma", "unused")
-@TvPreview
+@Previews
 @Composable
 fun ScreenView(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/AutoHideEmptyText.kt

@@ -20,16 +20,16 @@ import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextDecoration
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.TextUnit
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.LocalTextStyle
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.textFrom
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @SuppressLint("ModifierParameter")
-@Preview
+@Previews
 @Composable
 fun AutoHideEmptyText(
     text: Any? = "test",

+ 5 - 4
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/CircleText.kt

@@ -23,19 +23,20 @@ import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
 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.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.MaterialTheme
+import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.extensions.ComposeExt.isPortraitMode
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.extensions.ModifierExt.tvAspectRatio
 
 @SuppressLint("ModifierParameter")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun CircleText(
     modifier: Modifier = Modifier,
@@ -47,12 +48,12 @@ fun CircleText(
     textSize: TextUnit = 20.sp,
     contentPadding: Dp = 0.dp,
 ) {
-
+    val isPortrait = isPortraitMode()
     Box(
         modifier = modifier.recomposeHighlighter()
             .size(textSize.value.dp * 2)
             .padding(contentPadding)
-            .tvAspectRatio(1f)
+            .tvAspectRatio(1f, !isPortrait)
             .clip(CircleShape)
             .background(backGroundColor, CircleShape)
             .border(

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/TextAny.kt

@@ -20,17 +20,17 @@ import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextDecoration
 import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.TextUnit
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.LocalTextStyle
 import androidx.tv.material3.Text
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.textFrom
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @SuppressLint("ModifierParameter")
-@Preview
+@Previews
 @Composable
 fun TextAny(
     text: Any? = "test",

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/text/TextWithShadow.kt

@@ -15,17 +15,17 @@ import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shadow
 import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.MaterialTheme
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun TextWithShadow(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/AppsRow.kt

@@ -22,15 +22,15 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.helpers.apps.App
 import org.mjdev.tvlib.helpers.apps.rememberAppsManager
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.card.ItemCard
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun AppsRow(
     title: Any? = R.string.title_apps,

+ 4 - 4
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/BrowseView.kt

@@ -19,14 +19,14 @@ import androidx.compose.runtime.State
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.interfaces.ItemWithTitle
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.carousel.BigCarousel
 
-@TvPreview
+@Previews
 @Composable
 fun BrowseView(
     modifier: Modifier = Modifier,
@@ -60,8 +60,8 @@ fun BrowseView(
     val isEdit = isEditMode()
     ScrollableTvLazyColumn(
         modifier = modifier
-            .recomposeHighlighter()
-            .fillMaxSize(),
+            .fillMaxSize()
+            .recomposeHighlighter(),
         verticalArrangement = verticalArrangement,
         contentPadding = contentPadding
     ) {

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/CategoryRow.kt

@@ -26,12 +26,12 @@ import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.card.PhotoCard
@@ -39,7 +39,7 @@ import org.mjdev.tvlib.ui.components.text.TextAny
 
 @SuppressLint("AutoboxingStateValueProperty")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun CategoryRow(
     title: Any? = "category",

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Clock.kt

@@ -24,7 +24,6 @@ import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.platform.LocalContext
 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.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
@@ -32,6 +31,7 @@ import androidx.compose.ui.unit.sp
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.channelFlow
 import kotlinx.coroutines.launch
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ContextExt.dateAsString
 import org.mjdev.tvlib.extensions.ContextExt.timeAsString
@@ -40,7 +40,7 @@ import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.complex.FocusableBox
 import org.mjdev.tvlib.ui.components.text.TextAny
 
-@Preview
+@Previews
 @Composable
 fun Clock(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/CursorRow.kt

@@ -36,7 +36,7 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.extensions.CursorExt.getData
 import org.mjdev.tvlib.extensions.CursorExt.isNotEmpty
@@ -48,7 +48,7 @@ import org.mjdev.tvlib.ui.components.text.TextAny
 @Suppress("DEPRECATION")
 @SuppressLint("AutoboxingStateValueProperty")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun CursorRow(
     title: Any? = null,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/ErrorMessage.kt

@@ -28,7 +28,6 @@ import androidx.compose.ui.graphics.takeOrElse
 import androidx.compose.ui.res.stringResource
 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.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
@@ -39,10 +38,11 @@ import androidx.tv.material3.LocalTextStyle
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.button.Button
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.text.TextAny
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun ErrorMessage(
     error: Throwable? = null,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Header.kt

@@ -30,15 +30,15 @@ import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isPortraitMode
 import org.mjdev.tvlib.ui.components.badge.Badge
 import org.mjdev.tvlib.ui.components.complex.FocusableBox
 
-@TvPreview
+@Previews
 @Composable
 fun Header(
     title: Any? = R.string.app_name,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Loading.kt

@@ -22,12 +22,12 @@ import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.sp
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.MaterialTheme
-import org.mjdev.tvlib.annotations.TvPreview
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.text.TextAny
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun Loading(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/LocalAudioRow.kt

@@ -20,13 +20,13 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import org.mjdev.tvlib.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.helpers.cursor.AudioItem
 import org.mjdev.tvlib.helpers.cursor.CachingCursor.Companion.rememberCursor
 
 @Suppress("DEPRECATION")
-@TvPreview
+@Previews
 @Composable
 fun LocalAudioRow(
     title: Any? = R.string.title_audio_local,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/LocalPhotosRow.kt

@@ -20,13 +20,13 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import org.mjdev.tvlib.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.helpers.cursor.CachingCursor.Companion.rememberCursor
 import org.mjdev.tvlib.helpers.cursor.PhotoItem
 
 @Suppress("DEPRECATION")
-@TvPreview
+@Previews
 @Composable
 fun LocalPhotosRow(
     title: Any? = R.string.title_photo_local,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/LocalVideoRow.kt

@@ -20,13 +20,13 @@ import androidx.compose.ui.unit.dp
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
 import org.mjdev.tvlib.R
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.computeCardWidth
 import org.mjdev.tvlib.helpers.cursor.CachingCursor.Companion.rememberCursor
 import org.mjdev.tvlib.helpers.cursor.VideoItem
 
 @Suppress("DEPRECATION")
-@TvPreview
+@Previews
 @Composable
 fun LocalVideoRow(
     title: Any? = R.string.title_video_local,

+ 5 - 1
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/NetworkErrorMessage.kt

@@ -13,12 +13,15 @@ import androidx.compose.runtime.State
 import androidx.compose.runtime.collectAsState
 import androidx.compose.ui.graphics.Color
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.asException
+import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.network.NetworkConnectivityService
 import org.mjdev.tvlib.network.NetworkConnectivityService.Companion.rememberNetworkService
 import org.mjdev.tvlib.network.NetworkStatus
 import org.mjdev.tvlib.network.isNotConnected
 
+@Previews
 @Composable
 fun NetworkErrorMessage(
     message: Any? = R.string.error_no_network,
@@ -28,7 +31,8 @@ fun NetworkErrorMessage(
     networkState: State<NetworkStatus?> = networkService.networkStatus
         .collectAsState(NetworkStatus.Connected(null)),
 ) {
-    if (networkState.isNotConnected) {
+    val isEdit = isEditMode()
+    if (isEdit || networkState.isNotConnected) {
         ErrorMessage(
             error = message.asException(),
             backgroundColor = backgroundColor,

+ 16 - 4
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/ScrollableTvLazyColumn.kt

@@ -10,6 +10,7 @@ package org.mjdev.tvlib.ui.components.tv
 
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -19,11 +20,13 @@ import androidx.tv.foundation.lazy.list.TvLazyColumn
 import androidx.tv.foundation.lazy.list.TvLazyListScope
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
+import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
+import org.mjdev.tvlib.extensions.ModifierExt.conditional
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.ui.components.complex.VerticalScrollableBox
 
-@TvPreview
+@Previews
 @Composable
 fun ScrollableTvLazyColumn(
     modifier: Modifier = Modifier,
@@ -37,12 +40,21 @@ fun ScrollableTvLazyColumn(
     state: TvLazyListState = rememberTvLazyListState(),
     content: TvLazyListScope.() -> Unit = {}
 ) {
+    val isEdit = isEditMode()
     VerticalScrollableBox(
-        modifier = modifier.recomposeHighlighter(),
+        modifier = modifier
+            .conditional(isEdit) {
+                fillMaxSize()
+            }
+            .recomposeHighlighter(),
         state = state
     ) {
         TvLazyColumn(
-            modifier = modifier.recomposeHighlighter(),
+            modifier = modifier
+                .conditional(isEdit) {
+                    fillMaxSize()
+                }
+                .recomposeHighlighter(),
             state = state,
             contentPadding = contentPadding,
             reverseLayout = reverseLayout,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/TVRow.kt

@@ -21,10 +21,10 @@ import androidx.tv.foundation.lazy.list.TvLazyListScope
 import androidx.tv.foundation.lazy.list.TvLazyListState
 import androidx.tv.foundation.lazy.list.TvLazyRow
 import androidx.tv.foundation.lazy.list.rememberTvLazyListState
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 
-@TvPreview
+@Previews
 @Composable
 fun TVRow(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Tabs.kt

@@ -29,7 +29,7 @@ import androidx.tv.material3.Tab
 import androidx.tv.material3.TabDefaults
 import androidx.tv.material3.TabRow
 import androidx.tv.material3.TabRowDefaults
-import org.mjdev.tvlib.annotations.TvPreview
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.extensions.ComposeExt.isFocused
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusState
 import org.mjdev.tvlib.extensions.ComposeExt.rememberMutableInteractionSource
@@ -40,7 +40,7 @@ import org.mjdev.tvlib.ui.components.text.TextAny
 
 @SuppressLint("AutoboxingStateValueProperty")
 @OptIn(ExperimentalTvMaterial3Api::class)
-@TvPreview
+@Previews
 @Composable
 fun Tabs(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/Title.kt

@@ -21,7 +21,6 @@ import androidx.compose.ui.draw.scale
 import androidx.compose.ui.draw.shadow
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
@@ -31,11 +30,12 @@ import org.mjdev.tvlib.extensions.ComposeExt.isFocused
 import org.mjdev.tvlib.extensions.ComposeExt.rememberFocusState
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.complex.FocusableBox
 import org.mjdev.tvlib.ui.components.image.CircleImage
 import org.mjdev.tvlib.ui.components.text.TextWithShadow
 
-@Preview
+@Previews
 @Composable
 fun Title(
     modifier: Modifier = Modifier,

+ 2 - 2
tvlib/src/main/kotlin/org/mjdev/tvlib/ui/components/tv/UserPic.kt

@@ -15,7 +15,6 @@ import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 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 androidx.tv.material3.ExperimentalTvMaterial3Api
@@ -24,11 +23,12 @@ import org.mjdev.tvlib.extensions.ComposeExt.isEditMode
 import org.mjdev.tvlib.extensions.ModifierExt.conditional
 import org.mjdev.tvlib.extensions.ModifierExt.recomposeHighlighter
 import org.mjdev.tvlib.R
+import org.mjdev.tvlib.annotations.Previews
 import org.mjdev.tvlib.ui.components.complex.FocusableBox
 import org.mjdev.tvlib.ui.components.image.CircleImage
 
 @OptIn(ExperimentalTvMaterial3Api::class)
-@Preview
+@Previews
 @Composable
 fun UserPic(
     modifier: Modifier = Modifier,

+ 54 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/webclient/cache/NetUtils.kt

@@ -0,0 +1,54 @@
+package org.mjdev.tvlib.webclient.cache
+
+import android.app.Activity
+import android.content.Context
+import android.net.ConnectivityManager
+import android.text.TextUtils
+import timber.log.Timber
+import java.net.URL
+import java.util.*
+
+object NetUtils {
+
+    @Suppress("Deprecation")
+    fun isConnected(context: Context): Boolean {
+        val cm = context.applicationContext
+            .getSystemService(Activity.CONNECTIVITY_SERVICE) as ConnectivityManager
+        return cm.activeNetworkInfo.let { info ->
+            info != null && info.isConnected
+        }
+    }
+
+    fun getOriginUrl(referer: String?): String? {
+        var ou = referer
+        if (TextUtils.isEmpty(ou)) return ""
+        try {
+            val url = URL(ou)
+            val port = url.port
+            ou = url.protocol + "://" + url.host + if (port == -1) "" else ":$port"
+        } catch (e: Exception) {
+          Timber.e(e)
+        }
+        return ou
+    }
+
+    fun multimapToSingle(maps: Map<String, List<String>?>): Map<String, String> {
+        val sb = StringBuilder()
+        val map: MutableMap<String, String> = HashMap()
+        for ((key, values) in maps) {
+            sb.delete(0, sb.length)
+            if (!values.isNullOrEmpty()) {
+                for (v in values) {
+                    sb.append(v)
+                    sb.append(";")
+                }
+            }
+            if (sb.isNotEmpty()) {
+                sb.deleteCharAt(sb.length - 1)
+            }
+            map[key] = sb.toString()
+        }
+        return map
+    }
+
+}

+ 61 - 0
tvlib/src/main/kotlin/org/mjdev/tvlib/webclient/cache/TimeUtils.kt

@@ -0,0 +1,61 @@
+package org.mjdev.tvlib.webclient.cache
+
+import android.annotation.SuppressLint
+import timber.log.Timber
+import java.text.ParseException
+import java.text.SimpleDateFormat
+import java.util.*
+
+@Suppress("unused")
+object TimeUtils {
+
+    private const val DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"
+
+    fun formatGMT(time: String): Date? {
+        if (time.indexOf("GMT") < 0) {
+            try {
+                val tt = java.lang.Long.valueOf(time)
+                return Date(tt * 1000)
+            } catch (e: Exception) {
+                Timber.e(e)
+            }
+            return null
+        }
+        try {
+            return SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US)
+                .parse(time.trim { it <= ' ' })
+        } catch (e: ParseException) {
+            Timber.e(e)
+        }
+        return null
+    }
+
+    fun compare(d1: Date?, d2: Date?): Boolean {
+        return if (d1 == null || d2 == null) false
+        else d1.time - d2.time > 0
+    }
+
+    @SuppressLint("SimpleDateFormat")
+    fun getStardTime(time: String?): Date? {
+        return time?.let {
+            try {
+                SimpleDateFormat(DATE_FORMAT).parse(it)
+            } catch (e: ParseException) {
+                Timber.e(e)
+                null
+            }
+        }
+    }
+
+    fun getStardTime(time: Long): Date? {
+        try {
+            return Date(time * 1000)
+        } catch (e: Exception) {
+            Timber.e(e)
+        }
+        return null
+    }
+
+    val currentTime: String @SuppressLint("SimpleDateFormat")
+    get() = SimpleDateFormat(DATE_FORMAT).format(Date())
+}