diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/AppNavHost.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/AppNavHost.kt index 742c89dcc..d5341f1e5 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/AppNavHost.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/AppNavHost.kt @@ -24,7 +24,7 @@ import com.m3u.features.playlist.navigation.playlistScreen import com.m3u.features.playlist.navigation.playlistTvScreen import com.m3u.features.stream.PlayerActivity import com.m3u.i18n.R.string -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.ui.Destination import com.m3u.ui.Destination.Root.Setting.SettingFragment import com.m3u.ui.LocalHelper @@ -44,7 +44,7 @@ fun AppNavHost( val context = LocalContext.current val pref = LocalPref.current - val tv = isTvDevice() + val tv = isTelevision() NavHost( navController = navController, startDestination = startDestination, diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/AppRootGraph.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/AppRootGraph.kt index 3963402c3..7d4046b14 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/AppRootGraph.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/AppRootGraph.kt @@ -7,15 +7,20 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.exclude import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material3.Icon -import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem @@ -25,8 +30,8 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -83,7 +88,8 @@ internal fun AppRootGraph( Text( text = title, maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(horizontal = spacing.medium) ) }, navigationIcon = { @@ -97,26 +103,23 @@ internal fun AppRootGraph( } }, actions = { - - CompositionLocalProvider( - androidx.tv.material3.LocalContentColor provides LocalContentColor.current - ) { - actions.forEach { action -> - IconButton( - icon = action.icon, - contentDescription = action.contentDescription, - onClick = action.onClick - ) - } + actions.forEach { action -> + IconButton( + icon = action.icon, + contentDescription = action.contentDescription, + onClick = action.onClick + ) } + Spacer(modifier = Modifier.width(spacing.medium)) }, modifier = Modifier.fillMaxWidth() ) } - val topBarWithContent = @Composable { + val topBarWithContent = @Composable { windowInsets: WindowInsets -> Scaffold( topBar = topBar, + contentWindowInsets = windowInsets, modifier = Modifier.fillMaxSize() ) { padding -> Background { @@ -139,7 +142,7 @@ internal fun AppRootGraph( Modifier .fillMaxWidth() .weight(1f) - ) { topBarWithContent() } + ) { topBarWithContent(WindowInsets.systemBars.exclude(WindowInsets.navigationBars)) } NavigationBar( containerColor = currentContainerColor, contentColor = currentContentColor, @@ -171,7 +174,9 @@ internal fun AppRootGraph( NavigationRail( containerColor = currentContainerColor, contentColor = currentContentColor, - modifier = Modifier.fillMaxHeight() + modifier = Modifier.fillMaxHeight(), + // keep header not null + header = {} ) { items { NavigationItemLayout( @@ -197,17 +202,17 @@ internal fun AppRootGraph( Modifier .fillMaxHeight() .weight(1f) - ) { topBarWithContent() } + ) { topBarWithContent(WindowInsets.systemBars) } } } } @Composable -private fun NavigationItemLayout( +private inline fun NavigationItemLayout( currentRootDestination: Destination.Root?, fob: Fob?, rootDestination: Destination.Root, - navigateToRoot: (Destination.Root) -> Unit, + crossinline navigateToRoot: (Destination.Root) -> Unit, block: @Composable ( selected: Boolean, onClick: () -> Unit, @@ -227,13 +232,15 @@ private fun NavigationItemLayout( contentDescription = null ) } - val label = @Composable { - Text( - text = stringResource( - if (usefob && fob != null) fob.iconTextId - else rootDestination.iconTextId + val label: @Composable () -> Unit = remember(usefob, fob) { + @Composable { + Text( + text = stringResource( + if (usefob && fob != null) fob.iconTextId + else rootDestination.iconTextId + ) ) - ) + } } val actualOnClick: () -> Unit = if (usefob) { { fob?.onClick?.invoke() } diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/RootGraph.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/RootGraph.kt index a636b1d3b..16f3513fc 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/RootGraph.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/RootGraph.kt @@ -27,7 +27,7 @@ import com.m3u.features.foryou.ForyouRoute import com.m3u.features.setting.SettingRoute import com.m3u.material.ktx.Edge import com.m3u.material.ktx.blurEdge -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.ui.Destination import com.m3u.ui.ResumeEvent import kotlinx.collections.immutable.ImmutableList @@ -104,7 +104,7 @@ private fun RootGraph( HorizontalPager( state = pagerState, - userScrollEnabled = !isTvDevice(), + userScrollEnabled = !isTelevision(), modifier = modifier .fillMaxSize() .blurEdge( diff --git a/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteGallery.kt b/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteGallery.kt index e6cc5269b..658faa656 100644 --- a/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteGallery.kt +++ b/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteGallery.kt @@ -14,7 +14,7 @@ import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid import androidx.tv.foundation.lazy.grid.items import com.m3u.core.architecture.pref.LocalPref import com.m3u.data.database.model.Stream -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.ktx.plus import com.m3u.material.model.LocalSpacing import com.m3u.ui.LocalHelper @@ -69,7 +69,7 @@ private fun FavouriteGalleryImpl( val spacing = LocalSpacing.current val pref = LocalPref.current val helper = LocalHelper.current - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { LazyVerticalStaggeredGrid( columns = StaggeredGridCells.Fixed(rowCount), @@ -143,7 +143,7 @@ private fun CompactFavouriteGalleryImpl( val pref = LocalPref.current val helper = LocalHelper.current - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { LazyVerticalStaggeredGrid( columns = StaggeredGridCells.Fixed(rowCount), diff --git a/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteItem.kt b/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteItem.kt index 675876cf6..fdd757d5f 100644 --- a/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteItem.kt +++ b/features/favorite/src/main/java/com/m3u/features/favorite/components/FavoriteItem.kt @@ -30,7 +30,7 @@ import com.m3u.data.database.model.Stream import com.m3u.i18n.R.string import com.m3u.material.components.Image import com.m3u.material.components.TextBadge -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import java.net.URI @@ -78,7 +78,7 @@ private fun FavoriteItemImpl( ) { val context = LocalContext.current val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() val scheme = remember(stream.url) { URI(stream.url).scheme ?: context.getString(string.feat_playlist_scheme_unknown) diff --git a/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistGallery.kt b/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistGallery.kt index 92ad34604..d6155eeb7 100644 --- a/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistGallery.kt +++ b/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistGallery.kt @@ -17,7 +17,7 @@ import com.m3u.core.architecture.pref.LocalPref import com.m3u.data.database.model.Playlist import com.m3u.features.foryou.model.PlaylistDetail import com.m3u.i18n.R.string -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.ktx.plus import com.m3u.material.model.LocalSpacing import kotlinx.collections.immutable.ImmutableList @@ -65,7 +65,7 @@ private fun PlaylistGalleryImpl( modifier: Modifier = Modifier ) { val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { LazyVerticalGrid( columns = GridCells.Fixed(rowCount), diff --git a/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistItem.kt b/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistItem.kt index b38e8d5f1..3073a2031 100644 --- a/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistItem.kt +++ b/features/foryou/src/main/java/com/m3u/features/foryou/components/PlaylistItem.kt @@ -27,7 +27,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.m3u.core.architecture.pref.LocalPref import com.m3u.material.components.OuterRow -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import androidx.tv.material3.Card as TvCard @@ -75,7 +75,7 @@ private fun PlaylistItemImpl( ) { val spacing = LocalSpacing.current val theme = MaterialTheme.colorScheme - val tv = isTvDevice() + val tv = isTelevision() val currentContentColor by animateColorAsState( targetValue = theme.onSurface, label = "playlist-item-content" diff --git a/features/playlist/src/main/java/com/m3u/features/playlist/PlaylistScreen.kt b/features/playlist/src/main/java/com/m3u/features/playlist/PlaylistScreen.kt index d71246271..f17827623 100644 --- a/features/playlist/src/main/java/com/m3u/features/playlist/PlaylistScreen.kt +++ b/features/playlist/src/main/java/com/m3u/features/playlist/PlaylistScreen.kt @@ -21,9 +21,13 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.KeyboardDoubleArrowUp import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -32,7 +36,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.google.accompanist.permissions.PermissionStatus import com.google.accompanist.permissions.rememberPermissionState import com.m3u.core.architecture.pref.LocalPref -import com.m3u.core.util.compose.observableStateOf import com.m3u.core.wrapper.Event import com.m3u.core.wrapper.Message import com.m3u.data.database.model.Stream @@ -41,13 +44,16 @@ import com.m3u.features.playlist.impl.TvPlaylistScreenImpl import com.m3u.i18n.R.string import com.m3u.material.components.Background import com.m3u.material.ktx.interceptVolumeEvent -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import com.m3u.ui.Destination import com.m3u.ui.Fob import com.m3u.ui.LocalHelper import com.m3u.ui.Sort import kotlinx.collections.immutable.ImmutableList +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach @Composable internal fun PlaylistRoute( @@ -73,7 +79,6 @@ internal fun PlaylistRoute( val message by viewModel.message.collectAsStateWithLifecycle() - // If you try to check or request the WRITE_EXTERNAL_STORAGE on Android 13+, // it will always return false. // So you'll have to skip the permission check/request completely on Android 13+. @@ -167,22 +172,34 @@ private fun PlaylistScreen( modifier: Modifier = Modifier ) { val helper = LocalHelper.current + val currentOnScrollUp by rememberUpdatedState(onScrollUp) val isAtTopState = remember { - observableStateOf(true) { newValue -> - helper.fob = if (newValue) null - else { - Fob( - icon = Icons.Rounded.KeyboardDoubleArrowUp, - rootDestination = Destination.Root.Foryou, - iconTextId = string.feat_playlist_scroll_up, - onClick = onScrollUp - ) + mutableStateOf(true) + } + + LaunchedEffect(Unit) { + snapshotFlow { isAtTopState.value } + .distinctUntilChanged() + .onEach { newValue -> + helper.fob = if (newValue) null + else { + Fob( + icon = Icons.Rounded.KeyboardDoubleArrowUp, + rootDestination = Destination.Root.Foryou, + iconTextId = string.feat_playlist_scroll_up, + onClick = currentOnScrollUp + ) + } } - } + .launchIn(this) + } + + DisposableEffect(Unit) { + onDispose { helper.fob = null } } - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { PlaylistScreenImpl( channels = channels, diff --git a/features/playlist/src/main/java/com/m3u/features/playlist/impl/PlaylistScreenImpl.kt b/features/playlist/src/main/java/com/m3u/features/playlist/impl/PlaylistScreenImpl.kt index 94c23af22..1680e9fb8 100644 --- a/features/playlist/src/main/java/com/m3u/features/playlist/impl/PlaylistScreenImpl.kt +++ b/features/playlist/src/main/java/com/m3u/features/playlist/impl/PlaylistScreenImpl.kt @@ -29,6 +29,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color @@ -61,6 +62,8 @@ import com.m3u.ui.Sort import com.m3u.ui.SortBottomSheet import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @Composable @@ -169,11 +172,13 @@ internal fun PlaylistScreenImpl( ) { PlaylistPager(channels) { streams -> val state = rememberLazyStaggeredGridState() - LaunchedEffect(state.isAtTop) { - isAtTopState.value = state.isAtTop + LaunchedEffect(Unit) { + snapshotFlow { state.isAtTop } + .onEach { isAtTopState.value = it } + .launchIn(this) } EventHandler(scrollUp) { - state.animateScrollToItem(0) + state.scrollToItem(0) } val orientation = configuration.orientation val actualRowCount = remember(orientation, rowCount) { diff --git a/features/setting/src/main/java/com/m3u/features/setting/fragments/AppearanceFragment.kt b/features/setting/src/main/java/com/m3u/features/setting/fragments/AppearanceFragment.kt index c3d13220c..11f732992 100644 --- a/features/setting/src/main/java/com/m3u/features/setting/fragments/AppearanceFragment.kt +++ b/features/setting/src/main/java/com/m3u/features/setting/fragments/AppearanceFragment.kt @@ -26,7 +26,7 @@ import com.m3u.material.components.ThemeAddSelection import com.m3u.material.components.ThemeSelection import com.m3u.material.ktx.asColorScheme import com.m3u.i18n.R.string -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import kotlinx.collections.immutable.ImmutableList @@ -50,7 +50,7 @@ internal fun AppearanceFragment( val pref = LocalPref.current val isDarkMode = pref.darkMode val useDynamicColors = pref.useDynamicColors - val tv = isTvDevice() + val tv = isTelevision() Background { Column( modifier diff --git a/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/OptionalPreferences.kt b/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/OptionalPreferences.kt index d8a40dabf..375c5e4fd 100644 --- a/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/OptionalPreferences.kt +++ b/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/OptionalPreferences.kt @@ -27,12 +27,12 @@ import com.m3u.core.util.basic.title import com.m3u.features.setting.components.CheckBoxSharedPreference import com.m3u.i18n.R.string import com.m3u.material.components.Preference -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision @Composable fun OptionalPreferences(modifier: Modifier = Modifier) { val pref = LocalPref.current - val tv = isTvDevice() + val tv = isTelevision() var expended by rememberSaveable { mutableStateOf(false) } Column(modifier) { diff --git a/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/PreferencesFragment.kt b/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/PreferencesFragment.kt index b6dca75b9..f1e251e83 100644 --- a/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/PreferencesFragment.kt +++ b/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/PreferencesFragment.kt @@ -9,7 +9,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.tv.foundation.lazy.list.TvLazyColumn -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import com.m3u.ui.Destination.Root.Setting.SettingFragment @@ -27,7 +27,7 @@ internal fun PreferencesFragment( modifier: Modifier = Modifier ) { val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { LazyColumn( modifier = modifier, diff --git a/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/RegularPreferences.kt b/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/RegularPreferences.kt index 9db78d6aa..93ea702e7 100644 --- a/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/RegularPreferences.kt +++ b/features/setting/src/main/java/com/m3u/features/setting/fragments/preferences/RegularPreferences.kt @@ -25,7 +25,7 @@ import com.m3u.features.setting.components.CheckBoxSharedPreference import com.m3u.i18n.R.string import com.m3u.material.components.Preference import com.m3u.material.components.TextPreference -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.ui.Destination import com.m3u.ui.Destination.Root.Setting.SettingFragment import kotlin.time.DurationUnit @@ -39,7 +39,7 @@ internal fun RegularPreferences( modifier: Modifier = Modifier ) { val pref = LocalPref.current - val tv = isTvDevice() + val tv = isTelevision() Column(modifier) { Preference( diff --git a/features/stream/src/main/java/com/m3u/features/stream/StreamScreen.kt b/features/stream/src/main/java/com/m3u/features/stream/StreamScreen.kt index c2d42999c..fcf84e5ca 100644 --- a/features/stream/src/main/java/com/m3u/features/stream/StreamScreen.kt +++ b/features/stream/src/main/java/com/m3u/features/stream/StreamScreen.kt @@ -35,7 +35,7 @@ import com.m3u.material.components.Background import com.m3u.material.components.mask.MaskInterceptor import com.m3u.material.components.mask.MaskState import com.m3u.material.components.mask.rememberMaskState -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.ui.LocalHelper import com.m3u.ui.OnPipModeChanged import kotlinx.coroutines.flow.launchIn @@ -225,7 +225,7 @@ private fun StreamScreen( val playlistTitle = playlist?.title ?: "--" val favourite = stream?.favourite ?: false - BackHandler(isTvDevice() && maskState.visible) { + BackHandler(isTelevision() && maskState.visible) { maskState.sleep() } diff --git a/features/stream/src/main/java/com/m3u/features/stream/components/PlayerMask.kt b/features/stream/src/main/java/com/m3u/features/stream/components/PlayerMask.kt index dea42a4bd..096826e27 100644 --- a/features/stream/src/main/java/com/m3u/features/stream/components/PlayerMask.kt +++ b/features/stream/src/main/java/com/m3u/features/stream/components/PlayerMask.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.LocalContentColor @@ -16,19 +17,20 @@ import androidx.compose.ui.graphics.Color import com.m3u.material.components.mask.Mask import com.m3u.material.components.mask.MaskPanel import com.m3u.material.components.mask.MaskState -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing @Composable internal fun PlayerMask( state: MaskState, + windowInsets: WindowInsets, header: @Composable RowScope.() -> Unit, body: @Composable RowScope.() -> Unit, footer: @Composable RowScope.() -> Unit, modifier: Modifier = Modifier, ) { val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() CompositionLocalProvider( LocalContentColor provides Color.White, androidx.tv.material3.LocalContentColor provides Color.White @@ -39,6 +41,7 @@ internal fun PlayerMask( ) Mask( state = state, + windowInsets = windowInsets, color = Color.Black.copy(alpha = 0.54f) ) { Row( @@ -59,8 +62,7 @@ internal fun PlayerMask( content = body ) Column( - modifier = Modifier - .align(Alignment.BottomCenter) + modifier = Modifier.align(Alignment.BottomCenter) ) { Row( modifier = Modifier.fillMaxWidth(), diff --git a/features/stream/src/main/java/com/m3u/features/stream/fragments/StreamFragment.kt b/features/stream/src/main/java/com/m3u/features/stream/fragments/StreamFragment.kt index 1943e8376..6fe8f0369 100644 --- a/features/stream/src/main/java/com/m3u/features/stream/fragments/StreamFragment.kt +++ b/features/stream/src/main/java/com/m3u/features/stream/fragments/StreamFragment.kt @@ -10,10 +10,8 @@ import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.shape.RoundedCornerShape @@ -64,7 +62,7 @@ import com.m3u.material.components.Image import com.m3u.material.components.mask.MaskButton import com.m3u.material.components.mask.MaskCircleButton import com.m3u.material.components.mask.MaskState -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import com.m3u.ui.LocalHelper import com.m3u.ui.Player @@ -98,7 +96,7 @@ internal fun StreamFragment( val theme = MaterialTheme.colorScheme val pref = LocalPref.current val helper = LocalHelper.current - val tv = isTvDevice() + val tv = isTelevision() // because they will be updated frequently, // they must be wrapped with rememberUpdatedState when using them. @@ -107,7 +105,7 @@ internal fun StreamFragment( Background( color = Color.Black, - contentColor = Color.White + contentColor = Color.White, ) { Box(modifier.animateContentSize()) { val state = rememberPlayerState( @@ -136,6 +134,7 @@ internal fun StreamFragment( val muted = currentVolume == 0f PlayerMask( state = maskState, + windowInsets = windowInsets, header = { MaskButton( state = maskState, @@ -341,7 +340,6 @@ internal fun StreamFragment( } ) ) - .padding(windowInsets.asPaddingValues()) ) } diff --git a/material/src/main/java/com/m3u/material/components/Backgrounds.kt b/material/src/main/java/com/m3u/material/components/Backgrounds.kt index e4fc54f63..02cd45fba 100644 --- a/material/src/main/java/com/m3u/material/components/Backgrounds.kt +++ b/material/src/main/java/com/m3u/material/components/Backgrounds.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.isSpecified import androidx.compose.ui.unit.dp import com.m3u.material.ktx.ifUnspecified -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision @Composable inline fun Background( @@ -27,7 +27,7 @@ inline fun Background( crossinline content: @Composable BoxScope.() -> Unit ) { val actualContentColor = contentColor.ifUnspecified { - if (!isTvDevice()) LocalContentColor.current + if (!isTelevision()) LocalContentColor.current else androidx.tv.material3.LocalContentColor.current } val currentColor by animateColorAsState( diff --git a/material/src/main/java/com/m3u/material/components/Badges.kt b/material/src/main/java/com/m3u/material/components/Badges.kt index 90af006c0..0ab3ae8ab 100644 --- a/material/src/main/java/com/m3u/material/components/Badges.kt +++ b/material/src/main/java/com/m3u/material/components/Badges.kt @@ -4,17 +4,12 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.tv.material3.surfaceColorAtElevation -import com.m3u.material.ktx.isTvDevice import com.m3u.material.model.LocalSpacing @Composable @@ -24,16 +19,9 @@ fun TextBadge( icon: (@Composable () -> Unit)? = null, ) { val spacing = LocalSpacing.current - val tv = isTvDevice() - val tvColorScheme = androidx.tv.material3.MaterialTheme.colorScheme Card( modifier = modifier, shape = RoundedCornerShape(spacing.small), - colors = CardDefaults.cardColors( - containerColor = if (tv) tvColorScheme.surfaceColorAtElevation(4.dp) - else Color.Unspecified, - contentColor = if (tv) tvColorScheme.onSurface else Color.Unspecified - ) ) { Row( verticalAlignment = Alignment.CenterVertically diff --git a/material/src/main/java/com/m3u/material/components/Buttons.kt b/material/src/main/java/com/m3u/material/components/Buttons.kt index 51b49938d..d8a4dac9f 100644 --- a/material/src/main/java/com/m3u/material/components/Buttons.kt +++ b/material/src/main/java/com/m3u/material/components/Buttons.kt @@ -27,11 +27,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.isUnspecified import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp -import com.m3u.material.ktx.ifUnspecified -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.TelevisionChain +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import androidx.tv.material3.Button as TvButton import androidx.tv.material3.OutlinedButton as TvOutlinedButton @@ -49,7 +50,7 @@ fun Button( onClick: () -> Unit ) { val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { Button( shape = RoundedCornerShape(8.dp), @@ -101,7 +102,7 @@ fun TextButton( ) { val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { TextButton( shape = RoundedCornerShape(8.dp), @@ -119,21 +120,23 @@ fun TextButton( ) } } else { - TvOutlinedButton( - onClick = onClick, - enabled = enabled, - modifier = Modifier - .padding(spacing.extraSmall) - .then(modifier), - colors = androidx.tv.material3.ButtonDefaults.colors( - containerColor = containerColor, - contentColor = contentColor, - disabledContentColor = disabledContentColor - ) - ) { - TvText( - text = text.uppercase() - ) + TelevisionChain { + TvOutlinedButton( + onClick = onClick, + enabled = enabled, + modifier = Modifier + .padding(spacing.extraSmall) + .then(modifier), + colors = androidx.tv.material3.ButtonDefaults.colors( + containerColor = containerColor, + contentColor = contentColor, + disabledContentColor = disabledContentColor + ) + ) { + TvText( + text = text.uppercase() + ) + } } } } @@ -147,13 +150,14 @@ fun IconButton( enabled: Boolean = true, tint: Color = Color.Unspecified ) { - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { IconButton( onClick = onClick, enabled = enabled, modifier = modifier, - colors = IconButtonDefaults.iconButtonColors( + colors = if (tint.isUnspecified) IconButtonDefaults.iconButtonColors() + else IconButtonDefaults.iconButtonColors( contentColor = tint ) ) { @@ -163,22 +167,23 @@ fun IconButton( ) } } else { - val colorScheme = androidx.tv.material3.MaterialTheme.colorScheme - val actualTint = tint.ifUnspecified { androidx.tv.material3.LocalContentColor.current } - androidx.tv.material3.IconButton( - onClick = onClick, - enabled = enabled, - modifier = modifier, - colors = androidx.tv.material3.IconButtonDefaults.colors( - contentColor = actualTint, - focusedContainerColor = colorScheme.onSurface.copy(0.38f), - focusedContentColor = actualTint - ) - ) { - androidx.tv.material3.Icon( - imageVector = icon, - contentDescription = contentDescription - ) + TelevisionChain { + androidx.tv.material3.IconButton( + onClick = onClick, + enabled = enabled, + modifier = modifier, + colors = if (tint.isUnspecified) androidx.tv.material3.IconButtonDefaults.colors() + else androidx.tv.material3.IconButtonDefaults.colors( + contentColor = tint, + focusedContentColor = tint, + pressedContentColor = tint + ) + ) { + androidx.tv.material3.Icon( + imageVector = icon, + contentDescription = contentDescription + ) + } } } } diff --git a/material/src/main/java/com/m3u/material/components/Preferences.kt b/material/src/main/java/com/m3u/material/components/Preferences.kt index fea207101..79affedc7 100644 --- a/material/src/main/java/com/m3u/material/components/Preferences.kt +++ b/material/src/main/java/com/m3u/material/components/Preferences.kt @@ -35,7 +35,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.TelevisionChain +import com.m3u.material.ktx.isTelevision import androidx.tv.material3.ListItem as TvListItem import androidx.tv.material3.ListItemDefaults as TvListItemDefaults @@ -50,9 +51,6 @@ fun Preference( icon: ImageVector? = null, trailing: @Composable (() -> Unit)? = null ) { - // val configuration = LocalConfiguration.current - // val type = configuration.uiMode and Configuration.UI_MODE_TYPE_MASK - val interactionSource = remember { MutableInteractionSource() } val focus by interactionSource.collectIsFocusedAsState() @@ -80,7 +78,7 @@ fun Preference( label = "preference-content-color", animationSpec = spring(stiffness = Spring.StiffnessMediumLow) ) - if (!isTvDevice()) { + if (!isTelevision()) { ListItem( headlineContent = { Text( @@ -129,49 +127,43 @@ fun Preference( .fillMaxWidth() ) } else { - TvListItem( - selected = focus, - interactionSource = interactionSource, - headlineContent = { - androidx.tv.material3.Text( - text = title, - style = MaterialTheme.typography.titleMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - }, - supportingContent = { - if (content != null) { + TelevisionChain { + TvListItem( + selected = focus, + interactionSource = interactionSource, + headlineContent = { androidx.tv.material3.Text( - text = content.capitalize(Locale.current), - style = MaterialTheme.typography.bodyMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier then if (focus) Modifier.basicMarquee() - else Modifier + text = title, + style = MaterialTheme.typography.titleMedium, ) - } - }, - trailingContent = trailing, - leadingContent = { - icon?.let { - androidx.tv.material3.Icon(imageVector = it, contentDescription = null) - } - }, - tonalElevation = LocalAbsoluteTonalElevation.current, - colors = TvListItemDefaults.colors( - containerColor = currentContainerColor, - contentColor = currentContentColor, - ), - scale = TvListItemDefaults.scale( - scale = 0.9f, - focusedScale = 1f - ), - onClick = onClick, - modifier = modifier - .semantics(mergeDescendants = true) {} - .fillMaxWidth() - ) + }, + supportingContent = { + if (content != null) { + androidx.tv.material3.Text( + text = content.capitalize(Locale.current), + style = MaterialTheme.typography.bodyMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + }, + trailingContent = trailing, + leadingContent = { + icon?.let { + androidx.tv.material3.Icon(imageVector = it, contentDescription = null) + } + }, + scale = TvListItemDefaults.scale( + scale = 0.9f, + focusedScale = 1f + ), + onClick = onClick, + modifier = modifier + .semantics(mergeDescendants = true) {} + .fillMaxWidth() + ) + } + } } } @@ -200,11 +192,19 @@ fun CheckBoxPreference( }, modifier = modifier, trailing = { - Checkbox( - enabled = enabled, - checked = checked, - onCheckedChange = null - ) + if (!isTelevision()) { + Checkbox( + enabled = enabled, + checked = checked, + onCheckedChange = null + ) + } else { + androidx.tv.material3.Checkbox( + enabled = enabled, + checked = checked, + onCheckedChange = null + ) + } }, icon = icon ) @@ -240,11 +240,19 @@ fun SwitchPreference( }, modifier = combined, trailing = { - Switch( - enabled = enabled, - checked = checked, - onCheckedChange = null - ) + if (!isTelevision()) { + Switch( + enabled = enabled, + checked = checked, + onCheckedChange = null + ) + } else { + androidx.tv.material3.Switch( + enabled = enabled, + checked = checked, + onCheckedChange = null + ) + } }, icon = icon ) @@ -269,11 +277,18 @@ fun IconPreference( elevation = elevation, modifier = modifier, trailing = { - Icon( - imageVector = imageVector, - contentDescription = null, - tint = LocalContentColor.current.copy(alpha = 0.65f) - ) + if (!isTelevision()) { + Icon( + imageVector = imageVector, + contentDescription = null, + tint = LocalContentColor.current.copy(alpha = 0.65f) + ) + } else { + androidx.tv.material3.Icon( + imageVector = imageVector, + contentDescription = null, + ) + } }, icon = icon ) @@ -300,14 +315,25 @@ fun TextPreference( }, modifier = modifier, trailing = { - Text( - text = trailing.uppercase(), - color = MaterialTheme.colorScheme.primary, - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Bold, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) + + if (!isTelevision()) { + Text( + text = trailing.uppercase(), + color = MaterialTheme.colorScheme.primary, + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } else { + androidx.tv.material3.Text( + text = trailing.uppercase(), + style = androidx.tv.material3.MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } }, icon = icon ) diff --git a/material/src/main/java/com/m3u/material/components/ThemeSelection.kt b/material/src/main/java/com/m3u/material/components/ThemeSelection.kt index 338c9733b..f4eb5fc51 100644 --- a/material/src/main/java/com/m3u/material/components/ThemeSelection.kt +++ b/material/src/main/java/com/m3u/material/components/ThemeSelection.kt @@ -14,8 +14,8 @@ import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Add @@ -47,7 +47,7 @@ import androidx.compose.ui.unit.sp import androidx.tv.material3.Card import com.m3u.material.ktx.InteractionType import com.m3u.material.ktx.interactionBorder -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import com.m3u.material.model.LocalSpacing import com.m3u.material.model.SugarColors @@ -64,7 +64,7 @@ fun ThemeSelection( modifier: Modifier = Modifier, ) { val spacing = LocalSpacing.current - val tv = isTvDevice() + val tv = isTelevision() val alpha by animateFloatAsState( targetValue = if (selected) 0f else 0.4f, @@ -299,10 +299,7 @@ private fun ColorPiece( ), modifier = Modifier .aspectRatio(1f) - .sizeIn( - minWidth = if (left) 48.dp else 32.dp, - minHeight = if (left) 48.dp else 32.dp, - ) + .requiredSize(if (left) 48.dp else 32.dp) .padding(spacing.extraSmall) ) { Box( diff --git a/material/src/main/java/com/m3u/material/components/mask/Mask.kt b/material/src/main/java/com/m3u/material/components/mask/Mask.kt index f39dbcfa5..551b6a725 100644 --- a/material/src/main/java/com/m3u/material/components/mask/Mask.kt +++ b/material/src/main/java/com/m3u/material/components/mask/Mask.kt @@ -4,6 +4,9 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember @@ -17,6 +20,7 @@ import com.m3u.material.components.OuterBox @Composable fun Mask( state: MaskState, + windowInsets: WindowInsets, modifier: Modifier = Modifier, color: Color = Color.Unspecified, contentColor: Color = Color.Unspecified, @@ -33,7 +37,9 @@ fun Mask( } Background(color = color, contentColor = contentColor) { OuterBox( - modifier = modifier.focusRequester(focusRequester), + modifier = modifier + .focusRequester(focusRequester) + .padding(windowInsets.asPaddingValues()), content = content ) } diff --git a/material/src/main/java/com/m3u/material/components/mask/MaskButton.kt b/material/src/main/java/com/m3u/material/components/mask/MaskButton.kt index 803fd3186..7cdc8f788 100644 --- a/material/src/main/java/com/m3u/material/components/mask/MaskButton.kt +++ b/material/src/main/java/com/m3u/material/components/mask/MaskButton.kt @@ -1,7 +1,6 @@ package com.m3u.material.components.mask import androidx.compose.animation.animateColorAsState -import androidx.compose.material3.LocalContentColor import androidx.compose.material3.PlainTooltip import androidx.compose.material3.Text import androidx.compose.material3.TooltipBox @@ -13,7 +12,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.m3u.material.components.IconButton -import com.m3u.material.ktx.ifUnspecified @Composable fun MaskButton( @@ -28,7 +26,7 @@ fun MaskButton( val tooltipState = rememberTooltipState() val currentTint by animateColorAsState( - targetValue = tint.ifUnspecified { LocalContentColor.current }, + targetValue = tint, label = "mask-button-tint" ) diff --git a/material/src/main/java/com/m3u/material/components/mask/MaskCircleButton.kt b/material/src/main/java/com/m3u/material/components/mask/MaskCircleButton.kt index dacd9397a..89a281598 100644 --- a/material/src/main/java/com/m3u/material/components/mask/MaskCircleButton.kt +++ b/material/src/main/java/com/m3u/material/components/mask/MaskCircleButton.kt @@ -3,15 +3,17 @@ package com.m3u.material.components.mask import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import androidx.tv.material3.ClickableSurfaceDefaults import com.m3u.material.ktx.ifUnspecified -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision @Composable fun MaskCircleButton( @@ -21,7 +23,7 @@ fun MaskCircleButton( modifier: Modifier = Modifier, tint: Color = Color.Unspecified ) { - val tv = isTvDevice() + val tv = isTelevision() if (!tv) { Surface( shape = CircleShape, @@ -30,8 +32,14 @@ fun MaskCircleButton( onClick() }, modifier = modifier, - color = Color.Unspecified + color = Color.Unspecified, + contentColor = tint.ifUnspecified { LocalContentColor.current } ) { + CompositionLocalProvider( + androidx.tv.material3.LocalContentColor provides LocalContentColor.current + ) { + + } Icon( imageVector = icon, contentDescription = null, @@ -47,14 +55,14 @@ fun MaskCircleButton( }, modifier = modifier, colors = ClickableSurfaceDefaults.colors( - containerColor = Color.Unspecified + containerColor = Color.Unspecified, + contentColor = tint.ifUnspecified { androidx.tv.material3.LocalContentColor.current } ) ) { androidx.tv.material3.Icon( imageVector = icon, contentDescription = null, - modifier = Modifier.size(96.dp), - tint = tint.ifUnspecified { androidx.tv.material3.LocalContentColor.current } + modifier = Modifier.size(96.dp) ) } } diff --git a/material/src/main/java/com/m3u/material/components/mask/MaskState.kt b/material/src/main/java/com/m3u/material/components/mask/MaskState.kt index 4628125a4..1ac7eb85b 100644 --- a/material/src/main/java/com/m3u/material/components/mask/MaskState.kt +++ b/material/src/main/java/com/m3u/material/components/mask/MaskState.kt @@ -10,7 +10,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import com.m3u.material.ktx.isTvDevice +import com.m3u.material.ktx.isTelevision import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -89,7 +89,7 @@ private class MaskStateCoroutineImpl( fun rememberMaskState( @IntRange(from = 1) minDuration: Long = MaskDefaults.MIN_DURATION_SECOND, coroutineScope: CoroutineScope = rememberCoroutineScope(), - isTvDevice: Boolean = isTvDevice() + isTvDevice: Boolean = isTelevision() ): MaskState { return remember(minDuration, coroutineScope) { MaskStateCoroutineImpl( diff --git a/material/src/main/java/com/m3u/material/ktx/Tv.kt b/material/src/main/java/com/m3u/material/ktx/Tv.kt index dd0e9189e..1c7bd9f2e 100644 --- a/material/src/main/java/com/m3u/material/ktx/Tv.kt +++ b/material/src/main/java/com/m3u/material/ktx/Tv.kt @@ -1,12 +1,48 @@ package com.m3u.material.ktx import android.content.res.Configuration +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalConfiguration +import com.m3u.material.model.asTvScheme +import com.m3u.material.model.asTvTypography @Composable -fun isTvDevice(): Boolean { +fun isTelevision(): Boolean { val configuration = LocalConfiguration.current val type = configuration.uiMode and Configuration.UI_MODE_TYPE_MASK return type == Configuration.UI_MODE_TYPE_TELEVISION +} + +@Composable +fun TelevisionChain(block: @Composable () -> Unit) { + if (!isTelevision()) { + block() + return + } + val scheme = MaterialTheme.colorScheme + val typography = MaterialTheme.typography + androidx.tv.material3.MaterialTheme( + colorScheme = remember(scheme) { scheme.asTvScheme() }, + typography = remember(typography) { typography.asTvTypography() } + ) { + block() + } +} + +@Composable +inline fun T.TelevisionChain(crossinline block: @Composable T.() -> Unit) { + if (!isTelevision()) { + block() + return + } + val scheme = MaterialTheme.colorScheme + val typography = MaterialTheme.typography + androidx.tv.material3.MaterialTheme( + colorScheme = remember(scheme) { scheme.asTvScheme() }, + typography = remember(typography) { typography.asTvTypography() } + ) { + block() + } } \ No newline at end of file diff --git a/material/src/main/java/com/m3u/material/model/Theme.kt b/material/src/main/java/com/m3u/material/model/Theme.kt index 8a36e3e05..6abe97b7f 100644 --- a/material/src/main/java/com/m3u/material/model/Theme.kt +++ b/material/src/main/java/com/m3u/material/model/Theme.kt @@ -12,9 +12,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import com.google.android.material.color.utilities.Scheme +import com.m3u.material.ktx.TelevisionChain import com.m3u.material.ktx.asColorScheme import androidx.tv.material3.ColorScheme as TvColorScheme -import androidx.tv.material3.MaterialTheme as TvMaterialTheme import androidx.tv.material3.Typography as TvTypography @Composable @@ -38,18 +38,15 @@ fun AppTheme( } MaterialTheme( colorScheme = colorScheme, - content = { - TvMaterialTheme( - colorScheme = remember(colorScheme) { colorScheme.asTvScheme() }, - typography = remember(typography) { typography.asTvTypography() }, - content = content - ) - }, typography = typography - ) + ) { + TelevisionChain { + content() + } + } } -private fun ColorScheme.asTvScheme(): TvColorScheme { +fun ColorScheme.asTvScheme(): TvColorScheme { return TvColorScheme( primary = primary, onPrimary = onPrimary, @@ -83,7 +80,7 @@ private fun ColorScheme.asTvScheme(): TvColorScheme { ) } -private fun Typography.asTvTypography(): TvTypography { +fun Typography.asTvTypography(): TvTypography { return TvTypography( displayLarge = displayLarge, displayMedium = displayMedium,