diff --git a/androidApp/src/main/baseline-prof.txt b/androidApp/src/main/baseline-prof.txt index e0448b4b2..0beb64a47 100644 --- a/androidApp/src/main/baseline-prof.txt +++ b/androidApp/src/main/baseline-prof.txt @@ -2665,13 +2665,13 @@ HSPLcom/m3u/data/database/M3UDatabase_Impl;->s()Ldd/y; PLcom/m3u/data/database/M3UDatabase_Impl;->s()Ldd/y; HSPLcom/m3u/data/database/M3UDatabase_Impl;->t()Ldd/b0; PLcom/m3u/data/database/M3UDatabase_Impl;->t()Ldd/b0; -Lcom/m3u/data/leanback/model/Leanback; -HSPLcom/m3u/data/leanback/model/Leanback;->()V -PLcom/m3u/data/leanback/model/Leanback;->()V -HSPLcom/m3u/data/leanback/model/Leanback;->(Ljava/lang/String;IZLjava/lang/String;Z)V -PLcom/m3u/data/leanback/model/Leanback;->(Ljava/lang/String;IZLjava/lang/String;Z)V -HSPLcom/m3u/data/leanback/model/Leanback;->(Ljava/lang/String;IZLjava/lang/String;ZLkotlin/jvm/internal/f;)V -PLcom/m3u/data/leanback/model/Leanback;->(Ljava/lang/String;IZLjava/lang/String;ZLkotlin/jvm/internal/f;)V +Lcom/m3u/data/tv/model/Tv; +HSPLcom/m3u/data/tv/model/Tv;->()V +PLcom/m3u/data/tv/model/Tv;->()V +HSPLcom/m3u/data/tv/model/Tv;->(Ljava/lang/String;IZLjava/lang/String;Z)V +PLcom/m3u/data/tv/model/Tv;->(Ljava/lang/String;IZLjava/lang/String;Z)V +HSPLcom/m3u/data/tv/model/Tv;->(Ljava/lang/String;IZLjava/lang/String;ZLkotlin/jvm/internal/f;)V +PLcom/m3u/data/tv/model/Tv;->(Ljava/lang/String;IZLjava/lang/String;ZLkotlin/jvm/internal/f;)V Lcom/m3u/feature/playlist/TvPlaylistActivity; Ld/a; HSPLd/a;->()V diff --git a/androidApp/src/main/java/com/m3u/androidApp/AppPublisher.kt b/androidApp/src/main/java/com/m3u/androidApp/AppPublisher.kt index 2dc8a21b0..b0824dee2 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/AppPublisher.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/AppPublisher.kt @@ -4,7 +4,7 @@ import android.app.Application import android.os.Build import com.m3u.core.architecture.Abi import com.m3u.core.architecture.Publisher -import com.m3u.core.util.context.leanback +import com.m3u.core.util.context.tv import javax.inject.Inject class AppPublisher @Inject constructor(private val application: Application) : Publisher { @@ -16,6 +16,6 @@ class AppPublisher @Inject constructor(private val application: Application) : P override val lite: Boolean = BuildConfig.FLAVOR.contains("liteCodec", true) override val model: String = Build.MODEL override val abi: Abi = Abi.of(Build.SUPPORTED_ABIS[0]) - override val leanback: Boolean - get() = application.resources.configuration.leanback + override val tv: Boolean + get() = application.resources.configuration.tv } \ No newline at end of file diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/App.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/App.kt index 3c5cf51dd..80869c3c0 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/App.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/App.kt @@ -33,9 +33,9 @@ import androidx.navigation.navOptions import com.m3u.androidApp.ui.sheet.RemoteControlSheet import com.m3u.androidApp.ui.sheet.RemoteControlSheetValue import com.m3u.core.architecture.preferences.hiltPreferences -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection import com.m3u.material.components.Icon -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import com.m3u.ui.Destination import com.m3u.ui.FontFamilies @@ -65,8 +65,8 @@ fun App( onBackPressedDispatcher.onBackPressed() } - // for leanbacks - val broadcastCodeOnLeanback by viewModel.broadcastCodeOnLeanback.collectAsStateWithLifecycle() + // for tvs + val broadcastCodeOnTv by viewModel.broadcastCodeOnTv.collectAsStateWithLifecycle() // for smartphones val remoteControlSheetValue by viewModel.remoteControlSheetValue.collectAsStateWithLifecycle() @@ -74,9 +74,9 @@ fun App( AppImpl( navController = navController, onBackPressed = onBackPressed.takeUnless { shouldDispatchBackStack }, - checkLeanbackCodeOnSmartphone = viewModel::checkLeanbackCodeOnSmartphone, - forgetLeanbackCodeOnSmartphone = viewModel::forgetLeanbackCodeOnSmartphone, - broadcastCodeOnLeanback = broadcastCodeOnLeanback, + checkTvCodeOnSmartphone = viewModel::checkTvCodeOnSmartphone, + forgetTvCodeOnSmartphone = viewModel::forgetTvCodeOnSmartphone, + broadcastCodeOnTv = broadcastCodeOnTv, isRemoteControlSheetVisible = viewModel.isConnectSheetVisible, remoteControlSheetValue = remoteControlSheetValue, onRemoteDirection = viewModel::onRemoteDirection, @@ -95,12 +95,12 @@ private fun AppImpl( navController: NavHostController, isRemoteControlSheetVisible: Boolean, remoteControlSheetValue: RemoteControlSheetValue, - broadcastCodeOnLeanback: String?, + broadcastCodeOnTv: String?, onBackPressed: (() -> Unit)?, openRemoteControlSheet: () -> Unit, onCode: (String) -> Unit, - checkLeanbackCodeOnSmartphone: () -> Unit, - forgetLeanbackCodeOnSmartphone: () -> Unit, + checkTvCodeOnSmartphone: () -> Unit, + forgetTvCodeOnSmartphone: () -> Unit, onRemoteDirection: (RemoteDirection) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier @@ -108,7 +108,7 @@ private fun AppImpl( val spacing = LocalSpacing.current val preferences = hiltPreferences() - val leanback = leanback() + val tv = tv() val entry by navController.currentBackStackEntryAsState() @@ -147,7 +147,7 @@ private fun AppImpl( ) { SnackHost(Modifier.weight(1f)) AnimatedVisibility( - visible = !leanback && preferences.remoteControl, + visible = !tv && preferences.remoteControl, enter = scaleIn(initialScale = 0.65f) + fadeIn(), exit = scaleOut(targetScale = 0.65f) + fadeOut(), ) { @@ -172,15 +172,15 @@ private fun AppImpl( value = remoteControlSheetValue, visible = isRemoteControlSheetVisible, onCode = onCode, - checkLeanbackCodeOnSmartphone = checkLeanbackCodeOnSmartphone, - forgetLeanbackCodeOnSmartphone = forgetLeanbackCodeOnSmartphone, + checkTvCodeOnSmartphone = checkTvCodeOnSmartphone, + forgetTvCodeOnSmartphone = forgetTvCodeOnSmartphone, onRemoteDirection = onRemoteDirection, onDismissRequest = onDismissRequest ) Crossfade( - targetState = broadcastCodeOnLeanback, - label = "broadcast-code-on-leanback", + targetState = broadcastCodeOnTv, + label = "broadcast-code-on-tv", modifier = Modifier .padding(spacing.medium) .align(Alignment.BottomEnd) 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 d9438d69a..52c6d518d 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/AppNavHost.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/AppNavHost.kt @@ -20,7 +20,7 @@ import com.m3u.feature.playlist.navigation.navigateToPlaylist import com.m3u.feature.playlist.navigation.playlistScreen import com.m3u.feature.playlist.navigation.playlistTvScreen import com.m3u.feature.channel.PlayerActivity -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.ui.Destination import com.m3u.ui.Events import com.m3u.ui.SettingDestination @@ -36,7 +36,7 @@ fun AppNavHost( val context = LocalContext.current val preferences = hiltPreferences() - val leanback = leanback() + val tv = tv() NavHost( navController = navController, @@ -48,7 +48,7 @@ fun AppNavHost( rootGraph( contentPadding = contentPadding, navigateToPlaylist = { playlist -> - navController.navigateToPlaylist(playlist.url, leanback) + navController.navigateToPlaylist(playlist.url, tv) }, navigateToChannel = { if (preferences.zappingMode && PlayerActivity.isInPipMode) return@rootGraph diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/AppViewModel.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/AppViewModel.kt index bdb32aff3..c7bc73663 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/AppViewModel.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/AppViewModel.kt @@ -12,10 +12,10 @@ import com.m3u.core.architecture.Publisher import com.m3u.core.architecture.dispatcher.Dispatcher import com.m3u.core.architecture.dispatcher.M3uDispatchers.IO import com.m3u.core.architecture.preferences.Preferences -import com.m3u.data.api.LeanbackApiDelegate -import com.m3u.data.leanback.model.RemoteDirection -import com.m3u.data.repository.leanback.ConnectionToLeanbackValue -import com.m3u.data.repository.leanback.LeanbackRepository +import com.m3u.data.api.TvApiDelegate +import com.m3u.data.tv.model.RemoteDirection +import com.m3u.data.repository.tv.ConnectionToTvValue +import com.m3u.data.repository.tv.TvRepository import com.m3u.data.repository.playlist.PlaylistRepository import com.m3u.data.repository.programme.ProgrammeRepository import com.m3u.data.service.Messager @@ -42,8 +42,8 @@ class AppViewModel @Inject constructor( messager: Messager, private val playlistRepository: PlaylistRepository, private val programmeRepository: ProgrammeRepository, - private val leanbackRepository: LeanbackRepository, - private val leanbackApi: LeanbackApiDelegate, + private val tvRepository: TvRepository, + private val tvApi: TvApiDelegate, private val workManager: WorkManager, private val preferences: Preferences, private val publisher: Publisher, @@ -53,8 +53,8 @@ class AppViewModel @Inject constructor( refreshProgrammes() } - val broadcastCodeOnLeanback: StateFlow = leanbackRepository - .broadcastCodeOnLeanback + val broadcastCodeOnTv: StateFlow = tvRepository + .broadcastCodeOnTv .map { code -> code?.let { convertToPaddedString(it) } } .stateIn( scope = viewModelScope, @@ -62,52 +62,52 @@ class AppViewModel @Inject constructor( initialValue = null ) - private val leanbackCodeOnSmartphone = MutableSharedFlow() + private val tvCodeOnSmartphone = MutableSharedFlow() - private val connectionToLeanbackValue: StateFlow = - leanbackCodeOnSmartphone.flatMapLatest { code -> - if (code.isNotEmpty()) leanbackRepository.connectToLeanback(code.toInt()) + private val connectionToTvValue: StateFlow = + tvCodeOnSmartphone.flatMapLatest { code -> + if (code.isNotEmpty()) tvRepository.connectToTv(code.toInt()) else { - leanbackRepository.disconnectToLeanback() - flowOf(ConnectionToLeanbackValue.Idle()) + tvRepository.disconnectToTv() + flowOf(ConnectionToTvValue.Idle()) } } .flowOn(ioDispatcher) .stateIn( scope = viewModelScope, - initialValue = ConnectionToLeanbackValue.Idle(), + initialValue = ConnectionToTvValue.Idle(), started = SharingStarted.WhileSubscribed(5_000) ) internal val remoteControlSheetValue: StateFlow = combine( - leanbackRepository.connected, + tvRepository.connected, snapshotFlow { code }, - connectionToLeanbackValue - ) { leanback, code, connection -> + connectionToTvValue + ) { tvInfo, code, connection -> when { - leanback == null -> { + tvInfo == null -> { RemoteControlSheetValue.Prepare( code = code, searchingOrConnecting = with(connection) { - this is ConnectionToLeanbackValue.Searching || - this is ConnectionToLeanbackValue.Connecting + this is ConnectionToTvValue.Searching || + this is ConnectionToTvValue.Connecting } ) } - leanback.version != publisher.versionCode -> { + tvInfo.version != publisher.versionCode -> { this.code = "" -// val query = UpdateKey(leanback.version, leanback.abi) +// val query = UpdateKey(tvInfo.version, tvInfo.abi) // val state = states[query] ?: UpdateState.Idle // RemoteControlSheetValue.Update( -// leanback = leanback, +// tvInfo = tvInfo, // state = state // ) RemoteControlSheetValue.Prepare( code = code, searchingOrConnecting = with(connection) { - this is ConnectionToLeanbackValue.Searching || - this is ConnectionToLeanbackValue.Connecting + this is ConnectionToTvValue.Searching || + this is ConnectionToTvValue.Connecting } ) } @@ -115,7 +115,7 @@ class AppViewModel @Inject constructor( else -> { this.code = "" RemoteControlSheetValue.DPad( - leanback = leanback, + tvInfo = tvInfo, ) } } @@ -126,31 +126,31 @@ class AppViewModel @Inject constructor( started = SharingStarted.WhileSubscribed(5_000L) ) - private var checkLeanbackCodeOnSmartphoneJob: Job? = null + private var checkTvCodeOnSmartphoneJob: Job? = null - internal fun checkLeanbackCodeOnSmartphone() { + internal fun checkTvCodeOnSmartphone() { viewModelScope.launch { - leanbackCodeOnSmartphone.emit(code) + tvCodeOnSmartphone.emit(code) } - checkLeanbackCodeOnSmartphoneJob?.cancel() - checkLeanbackCodeOnSmartphoneJob = snapshotFlow { preferences.remoteControl } + checkTvCodeOnSmartphoneJob?.cancel() + checkTvCodeOnSmartphoneJob = snapshotFlow { preferences.remoteControl } .onEach { remoteControl -> if (!remoteControl) { - forgetLeanbackCodeOnSmartphone() + forgetTvCodeOnSmartphone() } } .launchIn(viewModelScope) } - internal fun forgetLeanbackCodeOnSmartphone() { + internal fun forgetTvCodeOnSmartphone() { viewModelScope.launch { - leanbackCodeOnSmartphone.emit("") + tvCodeOnSmartphone.emit("") } } internal fun onRemoteDirection(remoteDirection: RemoteDirection) { viewModelScope.launch { - leanbackApi.remoteDirection(remoteDirection.value) + tvApi.remoteDirection(remoteDirection.value) } } diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/Scaffold.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/Scaffold.kt index bef7d959f..b2e785e3f 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/Scaffold.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/Scaffold.kt @@ -40,14 +40,14 @@ import androidx.compose.ui.unit.offset import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMaxOfOrNull -import com.m3u.androidApp.ui.internal.LeanbackScaffoldImpl +import com.m3u.androidApp.ui.internal.TvScaffoldImpl import com.m3u.androidApp.ui.internal.SmartphoneScaffoldImpl import com.m3u.androidApp.ui.internal.TabletScaffoldImpl import com.m3u.material.components.Background import com.m3u.material.components.Icon import com.m3u.material.components.IconButton import com.m3u.material.effects.currentBackStackEntry -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalHazeState import com.m3u.material.model.LocalSpacing import com.m3u.ui.Destination @@ -73,15 +73,15 @@ internal fun Scaffold( content: @Composable BoxScope.(PaddingValues) -> Unit ) { val useRailNav = LocalHelper.current.useRailNav - val leanback = leanback() + val tv = tv() val hazeState = remember { HazeState() } CompositionLocalProvider(LocalHazeState provides hazeState) { Background { when { - leanback -> { - LeanbackScaffoldImpl( + tv -> { + TvScaffoldImpl( rootDestination = rootDestination, navigateToRoot = navigateToRootDestination, onBackPressed = onBackPressed, @@ -132,7 +132,7 @@ internal fun MainContent( onBackPressed: (() -> Unit)?, content: @Composable BoxScope.(PaddingValues) -> Unit ) { - val leanback = leanback() + val tv = tv() val spacing = LocalSpacing.current val hazeState = LocalHazeState.current @@ -144,7 +144,7 @@ internal fun MainContent( Scaffold( topBar = { - if (!leanback) { + if (!tv) { TopAppBar( colors = TopAppBarDefaults.topAppBarColors(Color.Transparent), windowInsets = windowInsets, @@ -238,11 +238,11 @@ internal fun NavigationItemLayout( ) { val hapticFeedback = LocalHapticFeedback.current - val leanback = leanback() + val tv = tv() val usefob = fob?.rootDestination == currentRootDestination val selected = usefob || currentRootDestination == rootDestination val icon = @Composable { - if (!leanback) { + if (!tv) { Icon( imageVector = when { fob != null && usefob -> fob.icon @@ -264,7 +264,7 @@ internal fun NavigationItemLayout( } val label: @Composable () -> Unit = remember(usefob, fob) { @Composable { - if (!leanback) { + if (!tv) { Text( text = stringResource( if (usefob && fob != null) fob.iconTextId @@ -293,7 +293,7 @@ internal fun NavigationItemLayout( } internal enum class ScaffoldContent { Navigation, MainContent } -internal enum class ScaffoldRole { SmartPhone, Tablet, Leanback } +internal enum class ScaffoldRole { SmartPhone, Tablet, Tv } @Composable internal fun ScaffoldLayout( diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/StarBackground.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/StarBackground.kt index 917a7c820..b6091d841 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/StarBackground.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/StarBackground.kt @@ -32,7 +32,7 @@ import androidx.graphics.shapes.RoundedPolygon import androidx.graphics.shapes.star import androidx.graphics.shapes.toPath import com.m3u.core.architecture.preferences.hiltPreferences -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv data class StarSpec( val numVertices: Int, @@ -88,11 +88,11 @@ fun StarBackground( modifier: Modifier = Modifier, colors: StarColors = StarColors.defaults(), ) { - val leanback = leanback() + val tv = tv() val preferences = hiltPreferences() val specs = remember(colors) { createStarSpecs(colors) } AnimatedVisibility( - visible = !leanback && preferences.colorfulBackground, + visible = !tv && preferences.colorfulBackground, enter = fadeIn() + scaleIn(initialScale = 2.3f), exit = fadeOut() + scaleOut(targetScale = 2.3f), modifier = modifier diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/internal/TelevisionScaffoldImpl.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/internal/TelevisionScaffoldImpl.kt index 631f6a771..8ee28fd5a 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/internal/TelevisionScaffoldImpl.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/internal/TelevisionScaffoldImpl.kt @@ -37,7 +37,7 @@ import androidx.tv.material3.MaterialTheme as TvMaterialTheme @Composable @InternalComposeApi -fun LeanbackScaffoldImpl( +fun TvScaffoldImpl( rootDestination: Destination.Root?, navigateToRoot: (Destination.Root) -> Unit, onBackPressed: (() -> Unit)?, @@ -48,7 +48,7 @@ fun LeanbackScaffoldImpl( val fob = Metadata.fob val navigation = @Composable { - LeanbackNavigation { + TvNavigation { Items { currentRootDestination -> NavigationItemLayout( rootDestination = rootDestination, @@ -112,7 +112,7 @@ fun LeanbackScaffoldImpl( Background(modifier) { ScaffoldLayout( - role = ScaffoldRole.Leanback, + role = ScaffoldRole.Tv, navigation = navigation, mainContent = mainContent ) @@ -120,7 +120,7 @@ fun LeanbackScaffoldImpl( } @Composable -private fun LeanbackNavigation( +private fun TvNavigation( modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit ) { diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/DPadContent.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/DPadContent.kt index d21584d08..20d8eefb4 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/DPadContent.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/DPadContent.kt @@ -16,17 +16,17 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.m3u.data.service.collectMessageAsState -import com.m3u.data.leanback.model.RemoteDirection -import com.m3u.data.leanback.model.Leanback +import com.m3u.data.tv.model.RemoteDirection +import com.m3u.data.tv.model.TvInfo import com.m3u.material.model.LocalSpacing import com.m3u.ui.FontFamilies @Composable @InternalComposeApi internal fun DPadContent( - leanback: Leanback, + tvInfo: TvInfo, onRemoteDirection: (RemoteDirection) -> Unit, - forgetLeanbackCodeOnSmartphone: () -> Unit, + forgetTvCodeOnSmartphone: () -> Unit, modifier: Modifier = Modifier ) { val spacing = LocalSpacing.current @@ -37,7 +37,7 @@ internal fun DPadContent( verticalArrangement = Arrangement.spacedBy(spacing.medium) ) { Text( - text = leanback.model, + text = tvInfo.model, textAlign = TextAlign.Center, style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold, @@ -59,7 +59,7 @@ internal fun DPadContent( ) TextButton( - onClick = forgetLeanbackCodeOnSmartphone, + onClick = forgetTvCodeOnSmartphone, modifier = Modifier.padding(top = 4.dp) ) { Text("DISCONNECT") diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/PrepareContent.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/PrepareContent.kt index 70153744a..4328f517c 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/PrepareContent.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/PrepareContent.kt @@ -37,7 +37,7 @@ import com.m3u.i18n.R internal fun PrepareContent( code: String, searchingOrConnecting: Boolean, - checkLeanbackCodeOnSmartphone: () -> Unit, + checkTvCodeOnSmartphone: () -> Unit, onCode: (String) -> Unit, modifier: Modifier = Modifier ) { @@ -88,7 +88,7 @@ internal fun PrepareContent( TextButton( enabled = !searchingOrConnecting && code.length == 6, - onClick = checkLeanbackCodeOnSmartphone, + onClick = checkTvCodeOnSmartphone, modifier = Modifier.padding(top = 4.dp) ) { Text( diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteControlSheet.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteControlSheet.kt index b90649677..767fb7f1b 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteControlSheet.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteControlSheet.kt @@ -8,8 +8,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.InternalComposeApi import androidx.compose.ui.Modifier -import com.m3u.data.leanback.model.Leanback -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.TvInfo +import com.m3u.data.tv.model.RemoteDirection @Immutable sealed class RemoteControlSheetValue { @@ -24,7 +24,7 @@ sealed class RemoteControlSheetValue { @Immutable data class DPad( - val leanback: Leanback, + val tvInfo: TvInfo, ) : RemoteControlSheetValue() } @@ -35,8 +35,8 @@ internal fun RemoteControlSheet( value: RemoteControlSheetValue, visible: Boolean, onCode: (String) -> Unit, - checkLeanbackCodeOnSmartphone: () -> Unit, - forgetLeanbackCodeOnSmartphone: () -> Unit, + checkTvCodeOnSmartphone: () -> Unit, + forgetTvCodeOnSmartphone: () -> Unit, onRemoteDirection: (RemoteDirection) -> Unit, onDismissRequest: () -> Unit, modifier: Modifier = Modifier @@ -66,16 +66,16 @@ internal fun RemoteControlSheet( PrepareContent( code = value.code, searchingOrConnecting = value.searchingOrConnecting, - checkLeanbackCodeOnSmartphone = checkLeanbackCodeOnSmartphone, + checkTvCodeOnSmartphone = checkTvCodeOnSmartphone, onCode = onCode ) } is RemoteControlSheetValue.DPad -> { DPadContent( - leanback = value.leanback, + tvInfo = value.tvInfo, onRemoteDirection = onRemoteDirection, - forgetLeanbackCodeOnSmartphone = forgetLeanbackCodeOnSmartphone, + forgetTvCodeOnSmartphone = forgetTvCodeOnSmartphone, ) } diff --git a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteDirectionController.kt b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteDirectionController.kt index 03d18fa31..b2044bed8 100644 --- a/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteDirectionController.kt +++ b/androidApp/src/main/java/com/m3u/androidApp/ui/sheet/RemoteDirectionController.kt @@ -43,7 +43,7 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.unit.dp -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/core/src/main/java/com/m3u/core/architecture/Publisher.kt b/core/src/main/java/com/m3u/core/architecture/Publisher.kt index c931265cf..a81d3a4ee 100644 --- a/core/src/main/java/com/m3u/core/architecture/Publisher.kt +++ b/core/src/main/java/com/m3u/core/architecture/Publisher.kt @@ -12,7 +12,7 @@ interface Publisher { val lite: Boolean val model: String val abi: Abi - val leanback: Boolean + val tv: Boolean } @JvmInline diff --git a/core/src/main/java/com/m3u/core/architecture/logger/Profiles.kt b/core/src/main/java/com/m3u/core/architecture/logger/Profiles.kt index 450d2597f..262e5e3d3 100644 --- a/core/src/main/java/com/m3u/core/architecture/logger/Profiles.kt +++ b/core/src/main/java/com/m3u/core/architecture/logger/Profiles.kt @@ -13,7 +13,7 @@ object Profiles { val REPOS_PLAYLIST = Profile("repos-playlist") val REPOS_CHANNEL = Profile("repos-channel") val REPOS_PROGRAMME = Profile("repos-programme") - val REPOS_LEANBACK = Profile("repos-leanback") + val REPOS_LEANBACK = Profile("repos-tv") val REPOS_MEDIA = Profile("repos-media") val REPOS_OTHER = Profile("repos-other") diff --git a/core/src/main/java/com/m3u/core/architecture/preferences/Preferences.kt b/core/src/main/java/com/m3u/core/architecture/preferences/Preferences.kt index 32e08fa3d..f11c96a1b 100644 --- a/core/src/main/java/com/m3u/core/architecture/preferences/Preferences.kt +++ b/core/src/main/java/com/m3u/core/architecture/preferences/Preferences.kt @@ -112,6 +112,8 @@ class Preferences @Inject constructor( sharedPreferences.booleanAsState(DEFAULT_RANDOMLY_IN_FAVOURITE, RANDOMLY_IN_FAVOURITE) var colorfulBackground by sharedPreferences.booleanAsState(DEFAULT_COLORFUL_BACKGROUND, COLORFUL_BACKGROUND) + var compactDimension by + sharedPreferences.booleanAsState(DEFAULT_COMPACT_DIMENSION, COMPACT_DIMENSION) companion object { @@ -156,6 +158,7 @@ class Preferences @Inject constructor( const val DEFAULT_12_H_CLOCK_MODE = false const val DEFAULT_COLORFUL_BACKGROUND = false + const val DEFAULT_COMPACT_DIMENSION = false const val PLAYLIST_STRATEGY = "playlist-strategy" const val ROW_COUNT = "rowCount" @@ -190,5 +193,6 @@ class Preferences @Inject constructor( const val RANDOMLY_IN_FAVOURITE = "randomly-in-favourite" const val COLORFUL_BACKGROUND = "colorful-background" + const val COMPACT_DIMENSION = "compact-dimension" } } diff --git a/core/src/main/java/com/m3u/core/util/context/Configuration.kt b/core/src/main/java/com/m3u/core/util/context/Configuration.kt index 29e4845b1..a7757237f 100644 --- a/core/src/main/java/com/m3u/core/util/context/Configuration.kt +++ b/core/src/main/java/com/m3u/core/util/context/Configuration.kt @@ -8,7 +8,7 @@ val Configuration.isPortraitMode: Boolean val Configuration.isDarkMode: Boolean get() = uiMode == Configuration.UI_MODE_NIGHT_YES -val Configuration.leanback: Boolean +val Configuration.tv: Boolean get() { val type = uiMode and Configuration.UI_MODE_TYPE_MASK return type == Configuration.UI_MODE_TYPE_TELEVISION diff --git a/data/src/main/java/com/m3u/data/api/LeanbackApi.kt b/data/src/main/java/com/m3u/data/api/LeanbackApi.kt index be5dc9ac8..8c654d9b5 100644 --- a/data/src/main/java/com/m3u/data/api/LeanbackApi.kt +++ b/data/src/main/java/com/m3u/data/api/LeanbackApi.kt @@ -4,8 +4,8 @@ import com.m3u.core.architecture.Publisher import com.m3u.core.architecture.logger.Logger import com.m3u.core.architecture.logger.execute import com.m3u.data.database.model.DataSource -import com.m3u.data.leanback.http.endpoint.DefRep -import com.m3u.data.leanback.model.Leanback +import com.m3u.data.tv.http.endpoint.DefRep +import com.m3u.data.tv.model.TvInfo import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking @@ -26,9 +26,9 @@ import retrofit2.http.Query import javax.inject.Inject import javax.inject.Singleton -interface LeanbackApi { +interface TvApi { @GET("/say_hello") - suspend fun sayHello(): Leanback? + suspend fun sayHello(): TvInfo? @POST("/playlists/subscribe") suspend fun subscribe( @@ -46,13 +46,13 @@ interface LeanbackApi { } @Singleton -class LeanbackApiDelegate @Inject constructor( +class TvApiDelegate @Inject constructor( private val builder: Retrofit.Builder, @OkhttpClient(true) private val okHttpClient: OkHttpClient, @Logger.MessageImpl private val logger: Logger, private val publisher: Publisher, -): LeanbackApi { - fun prepare(host: String, port: Int): Flow = callbackFlow { +): TvApi { + fun prepare(host: String, port: Int): Flow = callbackFlow { val json = Json { ignoreUnknownKeys = true } @@ -79,7 +79,7 @@ class LeanbackApiDelegate @Inject constructor( val listener = object : WebSocketListener() { override fun onMessage(webSocket: WebSocket, text: String) { try { - val info = json.decodeFromString(text) ?: return + val info = json.decodeFromString(text) ?: return trySendBlocking(info) } catch (e: IllegalStateException) { logger.log(e.message.orEmpty()) @@ -104,7 +104,7 @@ class LeanbackApiDelegate @Inject constructor( api = null } - override suspend fun sayHello(): Leanback? = logger.execute { + override suspend fun sayHello(): TvInfo? = logger.execute { requireApi().sayHello() } @@ -124,11 +124,11 @@ class LeanbackApiDelegate @Inject constructor( requireApi().remoteDirection(remoteDirectionValue) } - private var api: LeanbackApi? = null - private fun requireApi(): LeanbackApi = - checkNotNull(api) { "You haven't connected leanback" } + private var api: TvApi? = null + private fun requireApi(): TvApi = + checkNotNull(api) { "You haven't connected tv" } - private fun checkCompatibleInfoOrThrow(info: Leanback): Leanback { + private fun checkCompatibleInfoOrThrow(info: TvInfo): TvInfo { check(info.version == publisher.versionCode) { "The software version is incompatible, Please make sure the version is consistent" } diff --git a/data/src/main/java/com/m3u/data/repository/RepositoryModule.kt b/data/src/main/java/com/m3u/data/repository/RepositoryModule.kt index daca158ef..5567d8ed4 100644 --- a/data/src/main/java/com/m3u/data/repository/RepositoryModule.kt +++ b/data/src/main/java/com/m3u/data/repository/RepositoryModule.kt @@ -6,14 +6,14 @@ import com.m3u.data.repository.media.MediaRepository import com.m3u.data.repository.playlist.PlaylistRepository import com.m3u.data.repository.programme.ProgrammeRepository import com.m3u.data.repository.channel.ChannelRepository -import com.m3u.data.repository.leanback.LeanbackRepository +import com.m3u.data.repository.tv.TvRepository import com.m3u.data.repository.media.MediaRepositoryImpl import com.m3u.data.repository.playlist.PlaylistRepositoryImpl import com.m3u.data.repository.programme.ProgrammeRepositoryImpl import com.m3u.data.repository.channel.ChannelRepositoryImpl import com.m3u.data.repository.other.OtherRepository import com.m3u.data.repository.other.OtherRepositoryImpl -import com.m3u.data.repository.leanback.LeanbackRepositoryImpl +import com.m3u.data.repository.tv.TvRepositoryImpl import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -49,9 +49,9 @@ internal interface RepositoryModule { @Binds @Singleton - fun bindLeanbackRepository( - repository: LeanbackRepositoryImpl - ): LeanbackRepository + fun bindTvRepository( + repository: TvRepositoryImpl + ): TvRepository @Binds @Singleton diff --git a/data/src/main/java/com/m3u/data/repository/leanback/LeanbackRepository.kt b/data/src/main/java/com/m3u/data/repository/leanback/LeanbackRepository.kt deleted file mode 100644 index 0f5f5aa66..000000000 --- a/data/src/main/java/com/m3u/data/repository/leanback/LeanbackRepository.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.m3u.data.repository.leanback - -import com.m3u.data.leanback.model.Leanback -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.StateFlow -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -abstract class LeanbackRepository { - abstract val broadcastCodeOnLeanback: StateFlow - - protected abstract fun broadcastOnLeanback() - protected abstract fun closeBroadcastOnLeanback() - - abstract val connected: StateFlow - - abstract fun connectToLeanback( - broadcastCode: Int, - timeout: Duration = 8.seconds - ): Flow - - abstract suspend fun disconnectToLeanback() -} - -sealed interface ConnectionToLeanbackValue { - data class Idle(val reason: String? = null) : ConnectionToLeanbackValue - data object Searching : ConnectionToLeanbackValue - data object Connecting : ConnectionToLeanbackValue - data object Timeout : ConnectionToLeanbackValue - data class Completed(val host: String, val port: Int) : ConnectionToLeanbackValue -} diff --git a/data/src/main/java/com/m3u/data/repository/tv/TvRepository.kt b/data/src/main/java/com/m3u/data/repository/tv/TvRepository.kt new file mode 100644 index 000000000..79c24a97c --- /dev/null +++ b/data/src/main/java/com/m3u/data/repository/tv/TvRepository.kt @@ -0,0 +1,31 @@ +package com.m3u.data.repository.tv + +import com.m3u.data.tv.model.TvInfo +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds + +abstract class TvRepository { + abstract val broadcastCodeOnTv: StateFlow + + protected abstract fun broadcastOnTv() + protected abstract fun closeBroadcastOnTv() + + abstract val connected: StateFlow + + abstract fun connectToTv( + broadcastCode: Int, + timeout: Duration = 8.seconds + ): Flow + + abstract suspend fun disconnectToTv() +} + +sealed interface ConnectionToTvValue { + data class Idle(val reason: String? = null) : ConnectionToTvValue + data object Searching : ConnectionToTvValue + data object Connecting : ConnectionToTvValue + data object Timeout : ConnectionToTvValue + data class Completed(val host: String, val port: Int) : ConnectionToTvValue +} diff --git a/data/src/main/java/com/m3u/data/repository/leanback/LeanbackRepositoryImpl.kt b/data/src/main/java/com/m3u/data/repository/tv/TvRepositoryImpl.kt similarity index 70% rename from data/src/main/java/com/m3u/data/repository/leanback/LeanbackRepositoryImpl.kt rename to data/src/main/java/com/m3u/data/repository/tv/TvRepositoryImpl.kt index b25fc6d30..753a4a948 100644 --- a/data/src/main/java/com/m3u/data/repository/leanback/LeanbackRepositoryImpl.kt +++ b/data/src/main/java/com/m3u/data/repository/tv/TvRepositoryImpl.kt @@ -1,4 +1,4 @@ -package com.m3u.data.repository.leanback +package com.m3u.data.repository.tv import android.net.nsd.NsdServiceInfo import androidx.compose.runtime.snapshotFlow @@ -12,11 +12,11 @@ import com.m3u.core.architecture.preferences.Preferences import com.m3u.core.util.coroutine.timeout import com.m3u.core.wrapper.Resource import com.m3u.core.wrapper.asResource -import com.m3u.data.api.LeanbackApiDelegate -import com.m3u.data.leanback.Utils -import com.m3u.data.leanback.http.HttpServer -import com.m3u.data.leanback.model.Leanback -import com.m3u.data.leanback.nsd.NsdDeviceManager +import com.m3u.data.api.TvApiDelegate +import com.m3u.data.tv.Utils +import com.m3u.data.tv.http.HttpServer +import com.m3u.data.tv.model.TvInfo +import com.m3u.data.tv.nsd.NsdDeviceManager import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -39,41 +39,41 @@ import kotlinx.coroutines.launch import javax.inject.Inject import kotlin.time.Duration -class LeanbackRepositoryImpl @Inject constructor( +class TvRepositoryImpl @Inject constructor( private val nsdDeviceManager: NsdDeviceManager, private val httpServer: HttpServer, - private val leanbackApi: LeanbackApiDelegate, + private val tvApi: TvApiDelegate, logger: Logger, preferences: Preferences, publisher: Publisher, @Dispatcher(IO) ioDispatcher: CoroutineDispatcher -) : LeanbackRepository() { +) : TvRepository() { private val logger = logger.install(Profiles.REPOS_LEANBACK) - private val leanback = publisher.leanback + private val tv = publisher.tv private val coroutineScope = CoroutineScope(ioDispatcher) init { snapshotFlow { preferences.remoteControl } .onEach { remoteControl -> when { - !remoteControl -> closeBroadcastOnLeanback() - leanback -> broadcastOnLeanback() - else -> closeBroadcastOnLeanback() + !remoteControl -> closeBroadcastOnTv() + tv -> broadcastOnTv() + else -> closeBroadcastOnTv() } } .launchIn(coroutineScope) } - private val _broadcastCodeOnLeanback = MutableStateFlow(null) - override val broadcastCodeOnLeanback = _broadcastCodeOnLeanback.asStateFlow() + private val _broadcastCodeOnTv = MutableStateFlow(null) + override val broadcastCodeOnTv = _broadcastCodeOnTv.asStateFlow() - private var broadcastOnLeanbackJob: Job? = null + private var broadcastOnTvJob: Job? = null - override fun broadcastOnLeanback() { + override fun broadcastOnTv() { val serverPort = Utils.findPort() - closeBroadcastOnLeanback() + closeBroadcastOnTv() httpServer.start(serverPort) - broadcastOnLeanbackJob = coroutineScope.launch { + broadcastOnTvJob = coroutineScope.launch { while (isActive) { val nsdPort = Utils.findPort() val pin = Utils.createPin() @@ -94,39 +94,39 @@ class LeanbackRepositoryImpl @Inject constructor( logger.log("start-server: opening...") } .onCompletion { - _broadcastCodeOnLeanback.value = null + _broadcastCodeOnTv.value = null logger.log("start-server: nsd completed") } .onEach { registered -> logger.log("start-server: registered: $registered") - _broadcastCodeOnLeanback.value = if (registered != null) pin else null + _broadcastCodeOnTv.value = if (registered != null) pin else null } .collect() } } } - override fun closeBroadcastOnLeanback() { + override fun closeBroadcastOnTv() { httpServer.stop() - broadcastOnLeanbackJob?.cancel() - broadcastOnLeanbackJob = null + broadcastOnTvJob?.cancel() + broadcastOnTvJob = null } - private val _connected = MutableStateFlow(null) - override val connected: StateFlow = _connected.asStateFlow() + private val _connected = MutableStateFlow(null) + override val connected: StateFlow = _connected.asStateFlow() - private var connectToLeanbackJob: Job? = null + private var connectToTvJob: Job? = null - override fun connectToLeanback( + override fun connectToTv( broadcastCode: Int, timeout: Duration - ): Flow = channelFlow { + ): Flow = channelFlow { val completed = nsdDeviceManager .search() - .onStart { trySendBlocking(ConnectionToLeanbackValue.Searching) } + .onStart { trySendBlocking(ConnectionToTvValue.Searching) } .timeout(timeout) { logger.log("pair: timeout") - trySendBlocking(ConnectionToLeanbackValue.Timeout) + trySendBlocking(ConnectionToTvValue.Timeout) } .mapNotNull { all -> logger.log("pair: all devices: $all") @@ -141,14 +141,14 @@ class LeanbackRepositoryImpl @Inject constructor( .getAttribute(NsdDeviceManager.META_DATA_HOST) ?: return@mapNotNull null - ConnectionToLeanbackValue.Completed(host, port) + ConnectionToTvValue.Completed(host, port) } .firstOrNull() if (completed != null) { - trySendBlocking(ConnectionToLeanbackValue.Connecting) - connectToLeanbackJob?.cancel() - connectToLeanbackJob = leanbackApi + trySendBlocking(ConnectionToTvValue.Connecting) + connectToTvJob?.cancel() + connectToTvJob = tvApi .prepare(completed.host, completed.port) .asResource() .onEach { resource -> @@ -166,20 +166,20 @@ class LeanbackRepositoryImpl @Inject constructor( is Resource.Failure -> { logger.log("pair: catch an error, ${resource.message}") _connected.value = null - trySendBlocking(ConnectionToLeanbackValue.Idle(resource.message)) + trySendBlocking(ConnectionToTvValue.Idle(resource.message)) } } } .launchIn(coroutineScope) } awaitClose { - trySendBlocking(ConnectionToLeanbackValue.Idle()) + trySendBlocking(ConnectionToTvValue.Idle()) } } - override suspend fun disconnectToLeanback() { - connectToLeanbackJob?.cancel() - connectToLeanbackJob = null + override suspend fun disconnectToTv() { + connectToTvJob?.cancel() + connectToTvJob = null _connected.value = null } diff --git a/data/src/main/java/com/m3u/data/service/DPadReactionService.kt b/data/src/main/java/com/m3u/data/service/DPadReactionService.kt index d6316d5fe..4a4707a1c 100644 --- a/data/src/main/java/com/m3u/data/service/DPadReactionService.kt +++ b/data/src/main/java/com/m3u/data/service/DPadReactionService.kt @@ -1,7 +1,7 @@ package com.m3u.data.service import androidx.compose.runtime.Immutable -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection import kotlinx.coroutines.flow.SharedFlow @Immutable diff --git a/data/src/main/java/com/m3u/data/service/ServicesModule.kt b/data/src/main/java/com/m3u/data/service/ServicesModule.kt index eeb60a9f2..9a4d22f85 100644 --- a/data/src/main/java/com/m3u/data/service/ServicesModule.kt +++ b/data/src/main/java/com/m3u/data/service/ServicesModule.kt @@ -22,10 +22,10 @@ import com.m3u.data.service.internal.MessagerImpl import com.m3u.data.service.internal.PlayerManagerImpl import com.m3u.data.service.internal.DPadReactionServiceImpl import com.m3u.data.service.internal.FileProviderImpl -import com.m3u.data.leanback.http.HttpServer -import com.m3u.data.leanback.http.HttpServerImpl -import com.m3u.data.leanback.nsd.NsdDeviceManager -import com.m3u.data.leanback.nsd.NsdDeviceManagerImpl +import com.m3u.data.tv.http.HttpServer +import com.m3u.data.tv.http.HttpServerImpl +import com.m3u.data.tv.nsd.NsdDeviceManager +import com.m3u.data.tv.nsd.NsdDeviceManagerImpl import dagger.Binds import dagger.Module import dagger.Provides diff --git a/data/src/main/java/com/m3u/data/service/internal/DPadReactionServiceImpl.kt b/data/src/main/java/com/m3u/data/service/internal/DPadReactionServiceImpl.kt index 37ecda4c6..aad90267b 100644 --- a/data/src/main/java/com/m3u/data/service/internal/DPadReactionServiceImpl.kt +++ b/data/src/main/java/com/m3u/data/service/internal/DPadReactionServiceImpl.kt @@ -3,7 +3,7 @@ package com.m3u.data.service.internal import androidx.compose.runtime.Immutable import com.m3u.core.architecture.dispatcher.Dispatcher import com.m3u.core.architecture.dispatcher.M3uDispatchers.Main -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection import com.m3u.data.service.DPadReactionService import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableSharedFlow diff --git a/data/src/main/java/com/m3u/data/leanback/Utils.kt b/data/src/main/java/com/m3u/data/tv/Utils.kt similarity index 97% rename from data/src/main/java/com/m3u/data/leanback/Utils.kt rename to data/src/main/java/com/m3u/data/tv/Utils.kt index 068c5c125..1b62496c9 100644 --- a/data/src/main/java/com/m3u/data/leanback/Utils.kt +++ b/data/src/main/java/com/m3u/data/tv/Utils.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback +package com.m3u.data.tv import java.net.InetAddress import java.net.NetworkInterface diff --git a/data/src/main/java/com/m3u/data/leanback/http/HttpServer.kt b/data/src/main/java/com/m3u/data/tv/http/HttpServer.kt similarity index 65% rename from data/src/main/java/com/m3u/data/leanback/http/HttpServer.kt rename to data/src/main/java/com/m3u/data/tv/http/HttpServer.kt index 63105f0e0..377b48ec5 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/HttpServer.kt +++ b/data/src/main/java/com/m3u/data/tv/http/HttpServer.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.http +package com.m3u.data.tv.http interface HttpServer { fun start(port: Int) diff --git a/data/src/main/java/com/m3u/data/leanback/http/HttpServerImpl.kt b/data/src/main/java/com/m3u/data/tv/http/HttpServerImpl.kt similarity index 91% rename from data/src/main/java/com/m3u/data/leanback/http/HttpServerImpl.kt rename to data/src/main/java/com/m3u/data/tv/http/HttpServerImpl.kt index 975e76eef..96e74f40a 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/HttpServerImpl.kt +++ b/data/src/main/java/com/m3u/data/tv/http/HttpServerImpl.kt @@ -1,8 +1,8 @@ -package com.m3u.data.leanback.http +package com.m3u.data.tv.http -import com.m3u.data.leanback.http.endpoint.Remotes -import com.m3u.data.leanback.http.endpoint.Playlists -import com.m3u.data.leanback.http.endpoint.SayHellos +import com.m3u.data.tv.http.endpoint.Remotes +import com.m3u.data.tv.http.endpoint.Playlists +import com.m3u.data.tv.http.endpoint.SayHellos import io.ktor.serialization.kotlinx.KotlinxWebsocketSerializationConverter import io.ktor.serialization.kotlinx.json.json import io.ktor.server.application.Application diff --git a/data/src/main/java/com/m3u/data/leanback/http/endpoint/DefRep.kt b/data/src/main/java/com/m3u/data/tv/http/endpoint/DefRep.kt similarity index 79% rename from data/src/main/java/com/m3u/data/leanback/http/endpoint/DefRep.kt rename to data/src/main/java/com/m3u/data/tv/http/endpoint/DefRep.kt index 031fe5641..13ce3d967 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/endpoint/DefRep.kt +++ b/data/src/main/java/com/m3u/data/tv/http/endpoint/DefRep.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.http.endpoint +package com.m3u.data.tv.http.endpoint import androidx.annotation.Keep import kotlinx.serialization.Serializable diff --git a/data/src/main/java/com/m3u/data/leanback/http/endpoint/Endpoint.kt b/data/src/main/java/com/m3u/data/tv/http/endpoint/Endpoint.kt similarity index 68% rename from data/src/main/java/com/m3u/data/leanback/http/endpoint/Endpoint.kt rename to data/src/main/java/com/m3u/data/tv/http/endpoint/Endpoint.kt index b08d5dbd0..0bc6e82d2 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/endpoint/Endpoint.kt +++ b/data/src/main/java/com/m3u/data/tv/http/endpoint/Endpoint.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.http.endpoint +package com.m3u.data.tv.http.endpoint import io.ktor.server.routing.Route diff --git a/data/src/main/java/com/m3u/data/leanback/http/endpoint/Playlists.kt b/data/src/main/java/com/m3u/data/tv/http/endpoint/Playlists.kt similarity index 98% rename from data/src/main/java/com/m3u/data/leanback/http/endpoint/Playlists.kt rename to data/src/main/java/com/m3u/data/tv/http/endpoint/Playlists.kt index e82af8537..654e5e72d 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/endpoint/Playlists.kt +++ b/data/src/main/java/com/m3u/data/tv/http/endpoint/Playlists.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.http.endpoint +package com.m3u.data.tv.http.endpoint import android.content.Context import androidx.work.WorkManager diff --git a/data/src/main/java/com/m3u/data/leanback/http/endpoint/Remotes.kt b/data/src/main/java/com/m3u/data/tv/http/endpoint/Remotes.kt similarity index 93% rename from data/src/main/java/com/m3u/data/leanback/http/endpoint/Remotes.kt rename to data/src/main/java/com/m3u/data/tv/http/endpoint/Remotes.kt index e23bd36ea..55475432c 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/endpoint/Remotes.kt +++ b/data/src/main/java/com/m3u/data/tv/http/endpoint/Remotes.kt @@ -1,9 +1,9 @@ -package com.m3u.data.leanback.http.endpoint +package com.m3u.data.tv.http.endpoint import com.m3u.core.architecture.logger.Logger import com.m3u.core.architecture.logger.sandBox import com.m3u.data.service.DPadReactionService -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection import io.ktor.server.response.respond import io.ktor.server.routing.Route import io.ktor.server.routing.post diff --git a/data/src/main/java/com/m3u/data/leanback/http/endpoint/SayHellos.kt b/data/src/main/java/com/m3u/data/tv/http/endpoint/SayHellos.kt similarity index 96% rename from data/src/main/java/com/m3u/data/leanback/http/endpoint/SayHellos.kt rename to data/src/main/java/com/m3u/data/tv/http/endpoint/SayHellos.kt index cfffcd820..0544b2459 100644 --- a/data/src/main/java/com/m3u/data/leanback/http/endpoint/SayHellos.kt +++ b/data/src/main/java/com/m3u/data/tv/http/endpoint/SayHellos.kt @@ -1,11 +1,11 @@ -package com.m3u.data.leanback.http.endpoint +package com.m3u.data.tv.http.endpoint import com.m3u.core.architecture.Publisher import com.m3u.core.architecture.logger.Logger import com.m3u.core.architecture.logger.sandBox import com.m3u.core.wrapper.Message import com.m3u.data.repository.media.MediaRepository -import com.m3u.data.leanback.model.Leanback +import com.m3u.data.tv.model.TvInfo import io.ktor.server.request.receiveChannel import io.ktor.server.response.respond import io.ktor.server.routing.Route @@ -27,7 +27,7 @@ data class SayHellos @Inject constructor( private val mediaRepository: MediaRepository ) : Endpoint { private val info = with(publisher) { - Leanback( + TvInfo( model = model, version = versionCode, snapshot = snapshot, diff --git a/data/src/main/java/com/m3u/data/leanback/model/RemoteDirection.kt b/data/src/main/java/com/m3u/data/tv/model/RemoteDirection.kt similarity index 96% rename from data/src/main/java/com/m3u/data/leanback/model/RemoteDirection.kt rename to data/src/main/java/com/m3u/data/tv/model/RemoteDirection.kt index 72cc2588e..1177b32fc 100644 --- a/data/src/main/java/com/m3u/data/leanback/model/RemoteDirection.kt +++ b/data/src/main/java/com/m3u/data/tv/model/RemoteDirection.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.model +package com.m3u.data.tv.model import android.view.KeyEvent import androidx.compose.runtime.Immutable diff --git a/data/src/main/java/com/m3u/data/leanback/model/Television.kt b/data/src/main/java/com/m3u/data/tv/model/TvInfo.kt similarity index 84% rename from data/src/main/java/com/m3u/data/leanback/model/Television.kt rename to data/src/main/java/com/m3u/data/tv/model/TvInfo.kt index d1f58bc19..aea357b1f 100644 --- a/data/src/main/java/com/m3u/data/leanback/model/Television.kt +++ b/data/src/main/java/com/m3u/data/tv/model/TvInfo.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.model +package com.m3u.data.tv.model import androidx.annotation.Keep import androidx.compose.runtime.Immutable @@ -8,7 +8,7 @@ import kotlinx.serialization.Serializable @Keep @Serializable @Immutable -data class Leanback( +data class TvInfo( val model: String, val version: Int, val snapshot: Boolean, diff --git a/data/src/main/java/com/m3u/data/leanback/nsd/NsdDeviceManager.kt b/data/src/main/java/com/m3u/data/tv/nsd/NsdDeviceManager.kt similarity index 93% rename from data/src/main/java/com/m3u/data/leanback/nsd/NsdDeviceManager.kt rename to data/src/main/java/com/m3u/data/tv/nsd/NsdDeviceManager.kt index 32dcdc769..8cb0762c2 100644 --- a/data/src/main/java/com/m3u/data/leanback/nsd/NsdDeviceManager.kt +++ b/data/src/main/java/com/m3u/data/tv/nsd/NsdDeviceManager.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.nsd +package com.m3u.data.tv.nsd import android.net.nsd.NsdServiceInfo import kotlinx.coroutines.flow.Flow diff --git a/data/src/main/java/com/m3u/data/leanback/nsd/NsdDeviceManagerImpl.kt b/data/src/main/java/com/m3u/data/tv/nsd/NsdDeviceManagerImpl.kt similarity index 96% rename from data/src/main/java/com/m3u/data/leanback/nsd/NsdDeviceManagerImpl.kt rename to data/src/main/java/com/m3u/data/tv/nsd/NsdDeviceManagerImpl.kt index cf50a9c68..05f973456 100644 --- a/data/src/main/java/com/m3u/data/leanback/nsd/NsdDeviceManagerImpl.kt +++ b/data/src/main/java/com/m3u/data/tv/nsd/NsdDeviceManagerImpl.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.nsd +package com.m3u.data.tv.nsd import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo @@ -7,9 +7,9 @@ import com.m3u.core.architecture.dispatcher.M3uDispatchers.IO import com.m3u.core.architecture.logger.Logger import com.m3u.core.architecture.logger.Profiles import com.m3u.core.architecture.logger.install -import com.m3u.data.leanback.Utils -import com.m3u.data.leanback.nsd.NsdDeviceManager.Companion.META_DATA_PIN -import com.m3u.data.leanback.nsd.NsdDeviceManager.Companion.SERVICE_TYPE +import com.m3u.data.tv.Utils +import com.m3u.data.tv.nsd.NsdDeviceManager.Companion.META_DATA_PIN +import com.m3u.data.tv.nsd.NsdDeviceManager.Companion.SERVICE_TYPE import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.awaitClose diff --git a/data/src/main/java/com/m3u/data/leanback/nsd/NsdResolveListener.kt b/data/src/main/java/com/m3u/data/tv/nsd/NsdResolveListener.kt similarity index 96% rename from data/src/main/java/com/m3u/data/leanback/nsd/NsdResolveListener.kt rename to data/src/main/java/com/m3u/data/tv/nsd/NsdResolveListener.kt index bd8f647ea..823330974 100644 --- a/data/src/main/java/com/m3u/data/leanback/nsd/NsdResolveListener.kt +++ b/data/src/main/java/com/m3u/data/tv/nsd/NsdResolveListener.kt @@ -1,4 +1,4 @@ -package com.m3u.data.leanback.nsd +package com.m3u.data.tv.nsd import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo diff --git a/feature/channel/src/main/java/com/m3u/feature/channel/ChannelMask.kt b/feature/channel/src/main/java/com/m3u/feature/channel/ChannelMask.kt index ce65d4b00..e889e0899 100644 --- a/feature/channel/src/main/java/com/m3u/feature/channel/ChannelMask.kt +++ b/feature/channel/src/main/java/com/m3u/feature/channel/ChannelMask.kt @@ -86,7 +86,7 @@ import com.m3u.material.components.mask.MaskCircleButton import com.m3u.material.components.mask.MaskPanel import com.m3u.material.components.mask.MaskState import com.m3u.material.effects.currentBackStackEntry -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.material.model.LocalSpacing import com.m3u.ui.FontFamilies @@ -127,7 +127,7 @@ internal fun ChannelMask( val helper = LocalHelper.current val spacing = LocalSpacing.current val configuration = LocalConfiguration.current - val leanback = leanback() + val tv = tv() val coroutineScope = rememberCoroutineScope() val onBackPressedDispatcher = checkNotNull( @@ -215,7 +215,7 @@ internal fun ChannelMask( } } - if (leanback) { + if (tv) { BackHandler(maskState.visible && !maskState.locked) { maskState.sleep() } @@ -298,7 +298,7 @@ internal fun ChannelMask( ) } - if (!leanback && preferences.screencast) { + if (!tv && preferences.screencast) { MaskButton( state = maskState, icon = Icons.Rounded.Cast, @@ -306,7 +306,7 @@ internal fun ChannelMask( contentDescription = stringResource(string.feat_channel_tooltip_cast) ) } - if (!leanback && playerState.videoSize.isNotEmpty) { + if (!tv && playerState.videoSize.isNotEmpty) { MaskButton( state = maskState, icon = Icons.Rounded.PictureInPicture, @@ -441,7 +441,7 @@ internal fun ChannelMask( ) } } - if (!leanback) { + if (!tv) { val autoRotating by ChannelMaskUtils.IsAutoRotatingEnabled LaunchedEffect(autoRotating) { if (autoRotating) { @@ -553,7 +553,7 @@ internal fun ChannelMask( }, modifier = Modifier .weight(1f) - .thenIf(leanback) { tvSliderModifier } + .thenIf(tv) { tvSliderModifier } ) } diff --git a/feature/channel/src/main/java/com/m3u/feature/channel/components/MaskValueButton.kt b/feature/channel/src/main/java/com/m3u/feature/channel/components/MaskValueButton.kt index 39227f886..11074f9f8 100644 --- a/feature/channel/src/main/java/com/m3u/feature/channel/components/MaskValueButton.kt +++ b/feature/channel/src/main/java/com/m3u/feature/channel/components/MaskValueButton.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.m3u.material.components.IconButton import com.m3u.material.components.mask.MaskState -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.ui.FontFamilies @@ -33,7 +33,7 @@ fun MaskTextButton( tint: Color = Color.Unspecified, enabled: Boolean = true ) { - val leanback = leanback() + val tv = tv() TooltipBox( state = tooltipState, @@ -48,7 +48,7 @@ fun MaskTextButton( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, modifier = modifier - .thenIf(leanback) { + .thenIf(tv) { Modifier.onFocusEvent { if (it.isFocused) { state.wake() diff --git a/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerMask.kt b/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerMask.kt index fd7eefc59..f5a6677a0 100644 --- a/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerMask.kt +++ b/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerMask.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import com.m3u.material.components.mask.Mask import com.m3u.material.components.mask.MaskState -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing @Composable @@ -28,7 +28,7 @@ internal fun PlayerMask( slider: (@Composable () -> Unit)? = null ) { val spacing = LocalSpacing.current - val leanback = leanback() + val tv = tv() Mask( state = state, color = Color.Black.copy(alpha = 0.54f), @@ -36,8 +36,8 @@ internal fun PlayerMask( modifier = modifier .then( Modifier.padding( - top = if (leanback) spacing.medium else spacing.small, - bottom = if (!leanback) spacing.medium else spacing.small + top = if (tv) spacing.medium else spacing.small, + bottom = if (!tv) spacing.medium else spacing.small ) ) .padding(WindowInsets.statusBars.asPaddingValues()) @@ -48,7 +48,7 @@ internal fun PlayerMask( .fillMaxWidth() .padding(horizontal = spacing.medium), horizontalArrangement = Arrangement.spacedBy( - if (!leanback) spacing.none else spacing.medium, + if (!tv) spacing.none else spacing.medium, Alignment.End ), verticalAlignment = Alignment.Top, @@ -67,8 +67,7 @@ internal fun PlayerMask( modifier = Modifier.padding(horizontal = spacing.medium) ) { Row( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(spacing.medium), verticalAlignment = Alignment.Bottom, content = footer diff --git a/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerPanel.kt b/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerPanel.kt index 7a8215218..1977ad678 100644 --- a/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerPanel.kt +++ b/feature/channel/src/main/java/com/m3u/feature/channel/components/PlayerPanel.kt @@ -76,7 +76,7 @@ import com.m3u.material.effects.BackStackEntry import com.m3u.material.effects.BackStackHandler import com.m3u.material.ktx.Edge import com.m3u.material.ktx.blurEdges -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.material.model.LocalSpacing import com.m3u.material.shape.AbsoluteSmoothCornerShape @@ -355,7 +355,7 @@ private fun ChannelGallery( ) { val spacing = LocalSpacing.current val lazyListState = rememberLazyListState() - val leanback = leanback() + val tv = tv() ScrollToCurrentEffect( value = value, @@ -402,7 +402,7 @@ private fun ChannelGallery( contentPadding = PaddingValues(spacing.medium), modifier = modifier .fillMaxWidth() - .thenIf(leanback) { + .thenIf(tv) { Modifier.onKeyEvent { when (it.nativeKeyEvent.keyCode) { KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT -> { @@ -441,9 +441,9 @@ private fun ChannelGalleryItem( val spacing = LocalSpacing.current val helper = LocalHelper.current val coroutineScope = rememberCoroutineScope() - val leanback = leanback() + val tv = tv() - if (!leanback) { + if (!tv) { Card( colors = CardDefaults.cardColors( containerColor = if (!isPlaying) diff --git a/feature/channel/src/main/java/com/m3u/feature/channel/components/ProgrammeGuide.kt b/feature/channel/src/main/java/com/m3u/feature/channel/components/ProgrammeGuide.kt index 90b708083..12c68901a 100644 --- a/feature/channel/src/main/java/com/m3u/feature/channel/components/ProgrammeGuide.kt +++ b/feature/channel/src/main/java/com/m3u/feature/channel/components/ProgrammeGuide.kt @@ -65,7 +65,7 @@ import com.m3u.data.database.model.ProgrammeRange.Companion.HOUR_LENGTH import com.m3u.material.components.Icon import com.m3u.material.ktx.Edge import com.m3u.material.ktx.blurEdges -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.material.model.LocalSpacing import com.m3u.ui.FontFamilies @@ -108,7 +108,7 @@ internal fun ProgramGuide( onProgrammePressed: (Programme) -> Unit ) { val spacing = LocalSpacing.current - val leanback = leanback() + val tv = tv() val currentMilliseconds by produceCurrentMillisecondState() val coroutineScope = rememberCoroutineScope() @@ -160,7 +160,7 @@ internal fun ProgramGuide( MaterialTheme.colorScheme.surface, listOf(Edge.Top, Edge.Bottom) ) - .thenIf(!leanback) { zoomGestureModifier } + .thenIf(!tv) { zoomGestureModifier } .then(modifier) ) { // programmes @@ -230,7 +230,7 @@ internal fun ProgramGuide( } } - if (!leanback) { + if (!tv) { Controls( animateToCurrentTimeline = { coroutineScope.launch { animateToCurrentTimeline() } @@ -309,7 +309,7 @@ private fun ProgrammeCell( val currentOnPressed by rememberUpdatedState(onPressed) val spacing = LocalSpacing.current val preferences = hiltPreferences() - val leanback = leanback() + val tv = tv() val clockMode = preferences.twelveHourClock val content = @Composable { Column( @@ -347,7 +347,7 @@ private fun ProgrammeCell( ) } } - if (!leanback) { + if (!tv) { val hapticFeedback = LocalHapticFeedback.current var isPressed by remember { mutableStateOf(false) } val scale by animateFloatAsState( diff --git a/feature/channel/src/main/java/com/m3u/feature/channel/components/VerticalGestureArea.kt b/feature/channel/src/main/java/com/m3u/feature/channel/components/VerticalGestureArea.kt index 0ca010f63..5cc4efa0d 100644 --- a/feature/channel/src/main/java/com/m3u/feature/channel/components/VerticalGestureArea.kt +++ b/feature/channel/src/main/java/com/m3u/feature/channel/components/VerticalGestureArea.kt @@ -9,7 +9,7 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import com.m3u.core.architecture.preferences.hiltPreferences import com.m3u.feature.channel.ChannelMaskUtils.detectVerticalGesture -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf @Composable @@ -21,13 +21,13 @@ internal fun VerticalGestureArea( modifier: Modifier = Modifier ) { val preferences = hiltPreferences() - val leanback = leanback() + val tv = tv() val currentPercent by rememberUpdatedState(percent) BoxWithConstraints(modifier) { Box( modifier = Modifier .fillMaxSize() - .thenIf(!leanback && preferences.brightnessGesture) { + .thenIf(!tv && preferences.brightnessGesture) { Modifier.detectVerticalGesture( time = 0.65f, onDragStart = onDragStart, diff --git a/feature/favorite/src/main/java/com/m3u/feature/favorite/FavoriteScreen.kt b/feature/favorite/src/main/java/com/m3u/feature/favorite/FavoriteScreen.kt index dcbbab932..78050b1c2 100644 --- a/feature/favorite/src/main/java/com/m3u/feature/favorite/FavoriteScreen.kt +++ b/feature/favorite/src/main/java/com/m3u/feature/favorite/FavoriteScreen.kt @@ -33,7 +33,7 @@ import com.m3u.data.service.MediaCommand import com.m3u.feature.favorite.components.FavouriteGallery import com.m3u.i18n.R import com.m3u.material.ktx.interceptVolumeEvent -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.material.model.LocalHazeState import com.m3u.ui.EpisodesBottomSheet @@ -56,7 +56,7 @@ fun FavouriteRoute( modifier: Modifier = Modifier, viewModel: FavouriteViewModel = hiltViewModel() ) { - val leanback = leanback() + val tv = tv() val title = stringResource(R.string.ui_title_favourite) @@ -125,7 +125,7 @@ fun FavouriteRoute( }, modifier = Modifier .fillMaxSize() - .thenIf(!leanback && preferences.godMode) { + .thenIf(!tv && preferences.godMode) { Modifier.interceptVolumeEvent { event -> preferences.rowCount = when (event) { KeyEvent.KEYCODE_VOLUME_UP -> @@ -159,7 +159,7 @@ fun FavouriteRoute( onRefresh = { series?.let { viewModel.seriesReplay.value += 1 } }, onDismissRequest = { viewModel.series.value = null } ) - if (!leanback) { + if (!tv) { SortBottomSheet( visible = isSortSheetVisible, sort = sort, diff --git a/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteGallery.kt b/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteGallery.kt index a2a4bb966..663078271 100644 --- a/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteGallery.kt +++ b/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteGallery.kt @@ -34,7 +34,7 @@ import com.m3u.core.wrapper.Resource import com.m3u.data.database.model.Channel import com.m3u.i18n.R.string import com.m3u.material.components.VerticalDraggableScrollbar -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.plus import com.m3u.material.model.LocalSpacing import com.m3u.ui.createPremiumBrush @@ -123,9 +123,9 @@ private fun RandomTips( modifier: Modifier = Modifier ) { val spacing = LocalSpacing.current - val leanback = leanback() + val tv = tv() val title = stringResource(string.feat_favorite_play_randomly) - if (!leanback) { + if (!tv) { ListItem( headlineContent = { Text( diff --git a/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteItem.kt b/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteItem.kt index cd81e8fe5..80e1b9c84 100644 --- a/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteItem.kt +++ b/feature/favorite/src/main/java/com/m3u/feature/favorite/components/FavoriteItem.kt @@ -18,7 +18,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import com.m3u.data.database.model.Channel import com.m3u.i18n.R.string -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import com.m3u.material.shape.AbsoluteSmoothCornerShape import kotlinx.datetime.Clock @@ -40,8 +40,8 @@ internal fun FavoriteItem( onLongClick: () -> Unit, modifier: Modifier = Modifier ) { - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { SmartphoneFavoriteItemImpl( channel = channel, recently = recently, diff --git a/feature/foryou/src/main/java/com/m3u/feature/foryou/ForyouScreen.kt b/feature/foryou/src/main/java/com/m3u/feature/foryou/ForyouScreen.kt index 9dfef56f6..509b68ed8 100644 --- a/feature/foryou/src/main/java/com/m3u/feature/foryou/ForyouScreen.kt +++ b/feature/foryou/src/main/java/com/m3u/feature/foryou/ForyouScreen.kt @@ -45,7 +45,7 @@ import com.m3u.feature.foryou.components.recommend.Recommend import com.m3u.feature.foryou.components.recommend.RecommendGallery import com.m3u.i18n.R.string import com.m3u.material.ktx.interceptVolumeEvent -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.ui.EpisodesBottomSheet import com.m3u.ui.MediaSheet @@ -71,7 +71,7 @@ fun ForyouRoute( val preferences = hiltPreferences() val coroutineScope = rememberCoroutineScope() - val leanback = leanback() + val tv = tv() val title = stringResource(string.ui_title_foryou) val playlistCounts by viewModel.playlistCounts.collectAsStateWithLifecycle() @@ -127,7 +127,7 @@ fun ForyouRoute( onUnsubscribePlaylist = viewModel::onUnsubscribePlaylist, modifier = Modifier .fillMaxSize() - .thenIf(!leanback && preferences.godMode) { + .thenIf(!tv && preferences.godMode) { Modifier.interceptVolumeEvent { event -> preferences.rowCount = when (event) { KeyEvent.KEYCODE_VOLUME_UP -> (preferences.rowCount - 1).coerceAtLeast(1) diff --git a/feature/foryou/src/main/java/com/m3u/feature/foryou/components/PlaylistItem.kt b/feature/foryou/src/main/java/com/m3u/feature/foryou/components/PlaylistItem.kt index b61dc6ee7..1c2b39ed3 100644 --- a/feature/foryou/src/main/java/com/m3u/feature/foryou/components/PlaylistItem.kt +++ b/feature/foryou/src/main/java/com/m3u/feature/foryou/components/PlaylistItem.kt @@ -31,7 +31,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.m3u.material.components.CircularProgressIndicator import com.m3u.material.components.Icon -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import com.m3u.material.shape.AbsoluteSmoothCornerShape import com.m3u.ui.Badge @@ -51,8 +51,8 @@ internal fun PlaylistItem( onLongClick: () -> Unit, modifier: Modifier = Modifier ) { - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { SmartphonePlaylistItemImpl( label = label, type = type, diff --git a/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendGallery.kt b/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendGallery.kt index e7d713be5..25b1b5c92 100644 --- a/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendGallery.kt +++ b/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendGallery.kt @@ -23,7 +23,7 @@ import com.m3u.core.wrapper.eventOf import com.m3u.data.database.model.Channel import com.m3u.data.database.model.Playlist import com.m3u.material.components.HorizontalPagerIndicator -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.pageOffset import com.m3u.material.model.LocalSpacing import com.m3u.ui.Events @@ -40,7 +40,7 @@ internal fun RecommendGallery( val spacing = LocalSpacing.current val uriHandler = LocalUriHandler.current - val leanback = leanback() + val tv = tv() val onClick = { spec: Recommend.Spec -> when (spec) { @@ -59,7 +59,7 @@ internal fun RecommendGallery( } } - if (!leanback) { + if (!tv) { val state = rememberPagerState { specs.size } Column( modifier = modifier, diff --git a/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendItem.kt b/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendItem.kt index 7e266ca50..d8ed49424 100644 --- a/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendItem.kt +++ b/feature/foryou/src/main/java/com/m3u/feature/foryou/components/recommend/RecommendItem.kt @@ -43,7 +43,7 @@ import com.m3u.core.architecture.preferences.hiltPreferences import com.m3u.core.util.basic.title import com.m3u.i18n.R.string import com.m3u.material.brush.RecommendCardContainerBrush -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import com.m3u.material.shape.AbsoluteSmoothCornerShape import com.m3u.ui.FontFamilies @@ -80,8 +80,8 @@ private fun RecommendItemLayout( content: @Composable () -> Unit ) { val spacing = LocalSpacing.current - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { Card( shape = AbsoluteSmoothCornerShape(spacing.medium, 65), border = BorderStroke(1.dp, MaterialTheme.colorScheme.onSurfaceVariant), diff --git a/feature/playlist/src/main/java/com/m3u/feature/playlist/PlaylistScreen.kt b/feature/playlist/src/main/java/com/m3u/feature/playlist/PlaylistScreen.kt index b04558e84..23dde856e 100644 --- a/feature/playlist/src/main/java/com/m3u/feature/playlist/PlaylistScreen.kt +++ b/feature/playlist/src/main/java/com/m3u/feature/playlist/PlaylistScreen.kt @@ -64,7 +64,7 @@ import com.m3u.i18n.R.string import com.m3u.material.ktx.checkPermissionOrRationale import com.m3u.material.ktx.createScheme import com.m3u.material.ktx.interceptVolumeEvent -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf import com.m3u.material.model.LocalSpacing import com.m3u.material.model.asTvScheme @@ -96,7 +96,7 @@ internal fun PlaylistRoute( val colorScheme = TvMaterialTheme.colorScheme val lifecycleOwner = LocalLifecycleOwner.current - val leanback = leanback() + val tv = tv() val zapping by viewModel.zapping.collectAsStateWithLifecycle() val playlistUrl by viewModel.playlistUrl.collectAsStateWithLifecycle() @@ -247,7 +247,7 @@ internal fun PlaylistRoute( getProgrammeCurrently = { channelId -> viewModel.getProgrammeCurrently(channelId) }, modifier = Modifier .fillMaxSize() - .thenIf(!leanback && preferences.godMode) { + .thenIf(!tv && preferences.godMode) { Modifier.interceptVolumeEvent { event -> preferences.rowCount = when (event) { KeyEvent.KEYCODE_VOLUME_UP -> @@ -343,8 +343,8 @@ private fun PlaylistScreen( onDispose { Metadata.fob = null } } - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { SmartphonePlaylistScreenImpl( categoryWithChannels = categoryWithChannels, pinnedCategories = pinnedCategories, @@ -414,7 +414,7 @@ private fun UnsupportedUIModeContent( UI_MODE_TYPE_NORMAL -> "Normal" UI_MODE_TYPE_DESK -> "Desktop" UI_MODE_TYPE_CAR -> "Car" - UI_MODE_TYPE_TELEVISION -> "Leanback" + UI_MODE_TYPE_TELEVISION -> "Tv" UI_MODE_TYPE_APPLIANCE -> "Appliance" UI_MODE_TYPE_WATCH -> "Watch" UI_MODE_TYPE_VR_HEADSET -> "VR-Headset" diff --git a/feature/playlist/src/main/java/com/m3u/feature/playlist/internal/TvPlaylistScreenImpl.kt b/feature/playlist/src/main/java/com/m3u/feature/playlist/internal/TvPlaylistScreenImpl.kt index 16fd19ffe..f5dce8f8c 100644 --- a/feature/playlist/src/main/java/com/m3u/feature/playlist/internal/TvPlaylistScreenImpl.kt +++ b/feature/playlist/src/main/java/com/m3u/feature/playlist/internal/TvPlaylistScreenImpl.kt @@ -38,7 +38,7 @@ import com.m3u.feature.playlist.components.TvChannelGallery import com.m3u.i18n.R import com.m3u.material.components.Background import com.m3u.material.components.Icon -import com.m3u.material.components.leanback.dialogFocusable +import com.m3u.material.components.tv.dialogFocusable import com.m3u.material.ktx.Edge import com.m3u.material.ktx.blurEdge import com.m3u.material.model.LocalHazeState diff --git a/feature/playlist/src/main/java/com/m3u/feature/playlist/navigation/PlaylistNavigation.kt b/feature/playlist/src/main/java/com/m3u/feature/playlist/navigation/PlaylistNavigation.kt index 9f537aaa1..3a0a95f05 100644 --- a/feature/playlist/src/main/java/com/m3u/feature/playlist/navigation/PlaylistNavigation.kt +++ b/feature/playlist/src/main/java/com/m3u/feature/playlist/navigation/PlaylistNavigation.kt @@ -39,11 +39,11 @@ object PlaylistNavigation { fun NavController.navigateToPlaylist( playlistUrl: String, - leanback: Boolean = false, + tv: Boolean = false, navOptions: NavOptions? = null, ) { val encodedUrl = Uri.encode(playlistUrl) - val route = if (leanback) PlaylistNavigation.createPlaylistTvRoute(encodedUrl) + val route = if (tv) PlaylistNavigation.createPlaylistTvRoute(encodedUrl) else PlaylistNavigation.createPlaylistRoute(encodedUrl) this.navigate(route, navOptions) } diff --git a/feature/setting/src/main/java/com/m3u/feature/setting/SettingScreen.kt b/feature/setting/src/main/java/com/m3u/feature/setting/SettingScreen.kt index edc302a46..a72b10dea 100644 --- a/feature/setting/src/main/java/com/m3u/feature/setting/SettingScreen.kt +++ b/feature/setting/src/main/java/com/m3u/feature/setting/SettingScreen.kt @@ -42,7 +42,7 @@ import com.m3u.feature.setting.fragments.SubscriptionsFragment import com.m3u.feature.setting.fragments.preferences.PreferencesFragment import com.m3u.i18n.R.string import com.m3u.material.ktx.includeChildGlowPadding -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalHazeState import com.m3u.ui.Destination import com.m3u.ui.EventHandler @@ -59,7 +59,7 @@ fun SettingRoute( modifier: Modifier = Modifier, viewModel: SettingViewModel = hiltViewModel() ) { - val leanback = leanback() + val tv = tv() val controller = LocalSoftwareKeyboardController.current val colorSchemes by viewModel.colorSchemes.collectAsStateWithLifecycle() @@ -129,7 +129,7 @@ fun SettingRoute( modifier = modifier.fillMaxSize(), contentPadding = contentPadding ) - if (!leanback) { + if (!tv) { CanvasBottomSheet( sheetState = sheetState, colorScheme = colorScheme, diff --git a/feature/setting/src/main/java/com/m3u/feature/setting/SettingViewModel.kt b/feature/setting/src/main/java/com/m3u/feature/setting/SettingViewModel.kt index 6d4ea1ee8..7b7e1b5ba 100644 --- a/feature/setting/src/main/java/com/m3u/feature/setting/SettingViewModel.kt +++ b/feature/setting/src/main/java/com/m3u/feature/setting/SettingViewModel.kt @@ -22,7 +22,7 @@ import com.m3u.core.architecture.preferences.Preferences import com.m3u.core.unit.DataUnit import com.m3u.core.unit.KB import com.m3u.core.util.basic.startWithHttpScheme -import com.m3u.data.api.LeanbackApiDelegate +import com.m3u.data.api.TvApiDelegate import com.m3u.data.database.dao.ColorSchemeDao import com.m3u.data.database.example.ColorSchemeExample import com.m3u.data.database.model.ColorScheme @@ -58,7 +58,7 @@ class SettingViewModel @Inject constructor( private val workManager: WorkManager, private val preferences: Preferences, private val messager: Messager, - private val leanbackApi: LeanbackApiDelegate, + private val tvApi: TvApiDelegate, private val playerManager: PlayerManager, publisher: Publisher, // FIXME: do not use dao in viewmodel @@ -167,7 +167,7 @@ class SettingViewModel @Inject constructor( when { forTvState.value -> { viewModelScope.launch { - leanbackApi.subscribe( + tvApi.subscribe( title, urlOrUri, basicUrl, diff --git a/feature/setting/src/main/java/com/m3u/feature/setting/fragments/AppearanceFragment.kt b/feature/setting/src/main/java/com/m3u/feature/setting/fragments/AppearanceFragment.kt index be4429765..3b769fd66 100644 --- a/feature/setting/src/main/java/com/m3u/feature/setting/fragments/AppearanceFragment.kt +++ b/feature/setting/src/main/java/com/m3u/feature/setting/fragments/AppearanceFragment.kt @@ -17,6 +17,7 @@ import androidx.compose.material.icons.rounded.ColorLens import androidx.compose.material.icons.rounded.DarkMode import androidx.compose.material.icons.rounded.DeviceHub import androidx.compose.material.icons.rounded.FitScreen +import androidx.compose.material.icons.rounded.FormatSize import androidx.compose.material.icons.rounded.HideImage import androidx.compose.material.icons.rounded.Restore import androidx.compose.material.icons.rounded.Stars @@ -38,7 +39,7 @@ import com.m3u.material.components.Preference import com.m3u.material.components.TextPreference import com.m3u.material.components.ThemeAddSelection import com.m3u.material.components.ThemeSelection -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.minus import com.m3u.material.ktx.only import com.m3u.material.ktx.plus @@ -59,7 +60,7 @@ internal fun AppearanceFragment( val isDarkMode = preferences.darkMode val useDynamicColors = preferences.useDynamicColors - val leanback = leanback() + val tv = tv() Column( modifier = modifier @@ -143,6 +144,14 @@ internal fun AppearanceFragment( } ) } + item { + SwitchSharedPreference( + title = string.feat_setting_compact_dimension, + icon = Icons.Rounded.FormatSize, + checked = preferences.compactDimension, + onChanged = { preferences.compactDimension = !preferences.compactDimension } + ) + } item { SwitchSharedPreference( title = string.feat_setting_no_picture_mode, @@ -172,7 +181,7 @@ internal fun AppearanceFragment( enabled = useDynamicColorsAvailable ) } - if (!leanback) { + if (!tv) { item { SwitchSharedPreference( title = string.feat_setting_colorful_background, @@ -192,7 +201,7 @@ internal fun AppearanceFragment( ) } item { - if (!leanback) { + if (!tv) { SwitchSharedPreference( title = string.feat_setting_god_mode, content = string.feat_setting_god_mode_description, diff --git a/feature/setting/src/main/java/com/m3u/feature/setting/fragments/OptionalFragment.kt b/feature/setting/src/main/java/com/m3u/feature/setting/fragments/OptionalFragment.kt index 2e94a0926..671ce9995 100644 --- a/feature/setting/src/main/java/com/m3u/feature/setting/fragments/OptionalFragment.kt +++ b/feature/setting/src/main/java/com/m3u/feature/setting/fragments/OptionalFragment.kt @@ -38,7 +38,7 @@ import com.m3u.feature.setting.components.SwitchSharedPreference import com.m3u.i18n.R.string import com.m3u.material.components.TextPreference import com.m3u.material.ktx.includeChildGlowPadding -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.plus import com.m3u.material.model.LocalSpacing import kotlin.time.DurationUnit @@ -51,7 +51,7 @@ internal fun OptionalFragment( ) { val spacing = LocalSpacing.current val preferences = hiltPreferences() - val leanback = leanback() + val tv = tv() LazyColumn( verticalArrangement = Arrangement.spacedBy(spacing.small), contentPadding = contentPadding + PaddingValues(horizontal = spacing.medium), @@ -86,7 +86,7 @@ internal fun OptionalFragment( ) } - if (!leanback) { + if (!tv) { item { SwitchSharedPreference( title = string.feat_setting_zapping_mode, @@ -140,7 +140,7 @@ internal fun OptionalFragment( onChanged = { preferences.cache = !preferences.cache } ) } - if (!leanback) { + if (!tv) { item { SwitchSharedPreference( title = string.feat_setting_screen_rotating, @@ -261,9 +261,9 @@ internal fun OptionalFragment( } item { SwitchSharedPreference( - title = if (!leanback) string.feat_setting_remote_control + title = if (!tv) string.feat_setting_remote_control else string.feat_setting_remote_control_tv_side, - content = if (!leanback) string.feat_setting_remote_control_description + content = if (!tv) string.feat_setting_remote_control_description else string.feat_setting_remote_control_tv_side_description, icon = Icons.Rounded.SettingsRemote, checked = preferences.remoteControl, diff --git a/feature/setting/src/main/java/com/m3u/feature/setting/fragments/SubscriptionsFragment.kt b/feature/setting/src/main/java/com/m3u/feature/setting/fragments/SubscriptionsFragment.kt index 31a943ca5..4ee318630 100644 --- a/feature/setting/src/main/java/com/m3u/feature/setting/fragments/SubscriptionsFragment.kt +++ b/feature/setting/src/main/java/com/m3u/feature/setting/fragments/SubscriptionsFragment.kt @@ -50,7 +50,7 @@ import com.m3u.material.components.Icon import com.m3u.material.components.PlaceholderField import com.m3u.material.components.TonalButton import com.m3u.material.ktx.checkPermissionOrRationale -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.textHorizontalLabel import com.m3u.material.model.LocalSpacing import com.m3u.ui.helper.LocalHelper @@ -172,7 +172,7 @@ private fun MainContentImpl( val clipboardManager = LocalClipboardManager.current val helper = LocalHelper.current - val leanback = leanback() + val tv = tv() val remoteControl = preferences.remoteControl LazyColumn( @@ -233,7 +233,7 @@ private fun MainContentImpl( enabled = !forTvState.value ) } - if (!leanback && remoteControl) { + if (!tv && remoteControl) { RemoteControlSubscribeSwitch( checked = forTvState.value, onChanged = { forTvState.value = !forTvState.value }, diff --git a/i18n/src/main/res/values/feat_foryou.xml b/i18n/src/main/res/values/feat_foryou.xml index 5a64b5133..0e4aa5333 100644 --- a/i18n/src/main/res/values/feat_foryou.xml +++ b/i18n/src/main/res/values/feat_foryou.xml @@ -11,6 +11,6 @@ %d days %d hours new release - enter code from leanback + enter code from tv Make sure to connect to the same Wi-Fi \ No newline at end of file diff --git a/i18n/src/main/res/values/feat_setting.xml b/i18n/src/main/res/values/feat_setting.xml index 4f52daf17..1a14a9bdf 100644 --- a/i18n/src/main/res/values/feat_setting.xml +++ b/i18n/src/main/res/values/feat_setting.xml @@ -84,7 +84,7 @@ remote control allow smartphones to control your TV - for leanback + for tv backing up all playlists and channels restoring all playlists and channels @@ -121,6 +121,7 @@ source code + compact dimension epg name epg name is empty 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 25de23809..2a2399d12 100644 --- a/material/src/main/java/com/m3u/material/components/Backgrounds.kt +++ b/material/src/main/java/com/m3u/material/components/Backgrounds.kt @@ -14,7 +14,7 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.unit.dp -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import androidx.tv.material3.LocalContentColor as TvLocalContentColor import androidx.tv.material3.MaterialTheme as TvMtaterialTheme @@ -27,11 +27,11 @@ inline fun Background( crossinline content: @Composable () -> Unit ) { val actualColor = color.takeOrElse { - if (!leanback()) MaterialTheme.colorScheme.background + if (!tv()) MaterialTheme.colorScheme.background else TvMtaterialTheme.colorScheme.background } val actualContentColor = contentColor.takeOrElse { - if (!leanback()) MaterialTheme.colorScheme.onBackground + if (!tv()) MaterialTheme.colorScheme.onBackground else TvMtaterialTheme.colorScheme.onBackground } Box( 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 1dd30d126..f5d9dd320 100644 --- a/material/src/main/java/com/m3u/material/components/Buttons.kt +++ b/material/src/main/java/com/m3u/material/components/Buttons.kt @@ -31,7 +31,7 @@ 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.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import androidx.tv.material3.Button as TvButton import androidx.tv.material3.OutlinedButton as TvOutlinedButton @@ -49,8 +49,8 @@ fun Button( onClick: () -> Unit ) { val spacing = LocalSpacing.current - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { Button( shape = RoundedCornerShape(8.dp), onClick = onClick, @@ -101,8 +101,8 @@ fun TextButton( ) { val spacing = LocalSpacing.current - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { TextButton( shape = RoundedCornerShape(8.dp), onClick = onClick, @@ -147,8 +147,8 @@ fun TonalButton( ) { val spacing = LocalSpacing.current - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { FilledTonalButton( shape = RoundedCornerShape(8.dp), onClick = onClick, @@ -184,8 +184,8 @@ fun IconButton( enabled: Boolean = true, tint: Color = Color.Unspecified ) { - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { IconButton( onClick = onClick, enabled = enabled, diff --git a/material/src/main/java/com/m3u/material/components/Icons.kt b/material/src/main/java/com/m3u/material/components/Icons.kt index 484c87f35..02bed0215 100644 --- a/material/src/main/java/com/m3u/material/components/Icons.kt +++ b/material/src/main/java/com/m3u/material/components/Icons.kt @@ -6,7 +6,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.graphics.vector.ImageVector -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv @Composable fun Icon( @@ -15,8 +15,8 @@ fun Icon( modifier: Modifier = Modifier, tint: Color = Color.Unspecified ) { - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { androidx.compose.material3.Icon( imageVector = imageVector, 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 ceaf2c124..4e88c28a6 100644 --- a/material/src/main/java/com/m3u/material/components/Preferences.kt +++ b/material/src/main/java/com/m3u/material/components/Preferences.kt @@ -33,7 +33,7 @@ import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import com.m3u.material.shape.AbsoluteSmoothCornerShape import androidx.tv.material3.Checkbox as TvCheckbox @@ -73,7 +73,7 @@ fun Preference( } ) { val alpha = if (enabled) 1f else 0.38f - if (!leanback()) { + if (!tv()) { OutlinedCard( colors = CardDefaults.outlinedCardColors(Color.Transparent), shape = AbsoluteSmoothCornerShape(spacing.medium, 65) @@ -189,7 +189,7 @@ fun CheckBoxPreference( }, modifier = modifier, trailing = { - if (!leanback()) { + if (!tv()) { Checkbox( enabled = enabled, checked = checked, @@ -230,7 +230,7 @@ fun SwitchPreference( }, modifier = modifier, trailing = { - if (!leanback()) { + if (!tv()) { Switch( enabled = enabled, checked = checked, @@ -267,7 +267,7 @@ fun TrailingIconPreference( elevation = elevation, modifier = modifier, trailing = { - if (!leanback()) { + if (!tv()) { Icon( imageVector = trailingIcon, contentDescription = null, @@ -305,7 +305,7 @@ fun TextPreference( }, modifier = modifier, trailing = { - if (!leanback()) { + if (!tv()) { Text( text = trailing.uppercase(), color = MaterialTheme.colorScheme.primary, diff --git a/material/src/main/java/com/m3u/material/components/TextFields.kt b/material/src/main/java/com/m3u/material/components/TextFields.kt index 689b46533..92dab9267 100644 --- a/material/src/main/java/com/m3u/material/components/TextFields.kt +++ b/material/src/main/java/com/m3u/material/components/TextFields.kt @@ -61,7 +61,7 @@ import androidx.tv.material3.LocalContentColor import androidx.tv.material3.Surface import com.m3u.material.ktx.InteractionType import com.m3u.material.ktx.interactionBorder -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import androidx.tv.material3.MaterialTheme as TvMaterialTheme import androidx.tv.material3.Text as TvText @@ -185,7 +185,7 @@ fun PlaceholderField( icon: ImageVector? = null, onValueChange: (String) -> Unit = {}, ) { - if (!leanback()) { + if (!tv()) { val focusManager = LocalFocusManager.current val interactionSource = remember { MutableInteractionSource() } val focus by interactionSource.collectIsFocusedAsState() 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 3350605e8..34be26e8c 100644 --- a/material/src/main/java/com/m3u/material/components/ThemeSelection.kt +++ b/material/src/main/java/com/m3u/material/components/ThemeSelection.kt @@ -48,7 +48,7 @@ import com.m3u.material.LocalM3UHapticFeedback import com.m3u.material.ktx.InteractionType import com.m3u.material.ktx.createScheme import com.m3u.material.ktx.interactionBorder -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.model.LocalSpacing import com.m3u.material.model.SugarColors import androidx.tv.material3.Card as TvCard @@ -68,7 +68,7 @@ fun ThemeSelection( modifier: Modifier = Modifier, ) { val spacing = LocalSpacing.current - val leanback = leanback() + val tv = tv() val colorScheme = remember(argb, isDark) { createScheme(argb, isDark) @@ -144,7 +144,7 @@ fun ThemeSelection( Box( contentAlignment = Alignment.Center ) { - if (!leanback) { + if (!tv) { val zoom by animateFloatAsState( targetValue = if (selected) 0.95f else 0.85f, label = "zoom" 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 afb3ad37c..564d4eff0 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 @@ -12,7 +12,7 @@ import androidx.compose.ui.focus.onFocusEvent import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.m3u.material.components.IconButton -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import com.m3u.material.ktx.thenIf @Composable @@ -26,7 +26,7 @@ fun MaskButton( tint: Color = Color.Unspecified, enabled: Boolean = true ) { - val leanback = leanback() + val tv = tv() TooltipBox( state = tooltipState, @@ -45,7 +45,7 @@ fun MaskButton( state.wake() onClick() }, - modifier = modifier.thenIf(leanback) { + modifier = modifier.thenIf(tv) { Modifier.onFocusEvent { if (it.isFocused) { state.wake() 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 68a269e39..3a2dd2ae7 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 @@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp import androidx.tv.material3.ClickableSurfaceDefaults import com.m3u.material.components.Icon -import com.m3u.material.ktx.leanback +import com.m3u.material.ktx.tv import androidx.tv.material3.Icon as TvIcon import androidx.tv.material3.LocalContentColor as TvLocalContentColor import androidx.tv.material3.Surface as TvSurface @@ -25,8 +25,8 @@ fun MaskCircleButton( modifier: Modifier = Modifier, tint: Color = Color.Unspecified ) { - val leanback = leanback() - if (!leanback) { + val tv = tv() + if (!tv) { Surface( shape = CircleShape, onClick = { diff --git a/material/src/main/java/com/m3u/material/components/leanback/Dialog.kt b/material/src/main/java/com/m3u/material/components/tv/Dialog.kt similarity index 99% rename from material/src/main/java/com/m3u/material/components/leanback/Dialog.kt rename to material/src/main/java/com/m3u/material/components/tv/Dialog.kt index cb04322ce..a0266b2a7 100644 --- a/material/src/main/java/com/m3u/material/components/leanback/Dialog.kt +++ b/material/src/main/java/com/m3u/material/components/tv/Dialog.kt @@ -1,4 +1,4 @@ -package com.m3u.material.components.leanback +package com.m3u.material.components.tv import androidx.compose.animation.core.CubicBezierEasing import androidx.compose.animation.core.MutableTransitionState 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 2c8d3733d..35cd4a730 100644 --- a/material/src/main/java/com/m3u/material/ktx/Tv.kt +++ b/material/src/main/java/com/m3u/material/ktx/Tv.kt @@ -15,7 +15,7 @@ import com.m3u.material.model.asTvTypography import androidx.tv.material3.MaterialTheme as TvMaterialTheme @Composable -fun leanback(): Boolean = LocalConfiguration.current.run { +fun tv(): Boolean = LocalConfiguration.current.run { val type = uiMode and Configuration.UI_MODE_TYPE_MASK type == Configuration.UI_MODE_TYPE_TELEVISION } @@ -31,11 +31,11 @@ internal fun PlatformTheme( fallback: Boolean = true, block: @Composable () -> Unit ) { - val leanback = leanback() + val tv = tv() val car = false val content = @Composable { when { - leanback -> { + tv -> { TvMaterialTheme( colorScheme = remember(colorScheme) { colorScheme.asTvScheme() }, typography = remember(typography) { typography.asTvTypography() } @@ -48,7 +48,7 @@ internal fun PlatformTheme( else -> block() } } - val commonPlatform = !leanback && !car + val commonPlatform = !tv && !car if (commonPlatform || fallback) { MaterialTheme( colorScheme = colorScheme, @@ -62,6 +62,6 @@ internal fun PlatformTheme( } @Composable -fun Modifier.includeChildGlowPadding(): Modifier = thenIf(leanback()) { +fun Modifier.includeChildGlowPadding(): Modifier = thenIf(tv()) { Modifier.padding(LocalSpacing.current.medium) } diff --git a/material/src/main/java/com/m3u/material/model/Spacing.kt b/material/src/main/java/com/m3u/material/model/Spacing.kt index dfbc3829c..0f17c88e2 100644 --- a/material/src/main/java/com/m3u/material/model/Spacing.kt +++ b/material/src/main/java/com/m3u/material/model/Spacing.kt @@ -1,7 +1,7 @@ package com.m3u.material.model import androidx.compose.runtime.Immutable -import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.runtime.compositionLocalOf import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -14,6 +14,27 @@ data class Spacing( val large: Dp = 24.dp, val extraLarge: Dp = 32.dp, val largest: Dp = 40.dp -) +) { + companion object { + val REGULAR = Spacing( + none = 0.dp, + extraSmall = 4.dp, + small = 8.dp, + medium = 16.dp, + large = 24.dp, + extraLarge = 32.dp, + largest = 40.dp + ) + val COMPACT = Spacing( + none = 0.dp, + extraSmall = 2.dp, + small = 6.dp, + medium = 12.dp, + large = 16.dp, + extraLarge = 24.dp, + largest = 32.dp + ) + } +} -val LocalSpacing = staticCompositionLocalOf(::Spacing) +val LocalSpacing = compositionLocalOf { Spacing.COMPACT } diff --git a/ui/src/main/java/com/m3u/ui/Events.kt b/ui/src/main/java/com/m3u/ui/Events.kt index 858d8a180..7940aed12 100644 --- a/ui/src/main/java/com/m3u/ui/Events.kt +++ b/ui/src/main/java/com/m3u/ui/Events.kt @@ -11,7 +11,7 @@ import com.m3u.core.wrapper.Event import com.m3u.core.wrapper.eventOf import com.m3u.core.wrapper.handledEvent import com.m3u.data.service.DPadReactionService -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection import dagger.hilt.EntryPoint import dagger.hilt.InstallIn import dagger.hilt.android.EntryPointAccessors diff --git a/ui/src/main/java/com/m3u/ui/FocusDirections.kt b/ui/src/main/java/com/m3u/ui/FocusDirections.kt index fb69fbc6d..43d946229 100644 --- a/ui/src/main/java/com/m3u/ui/FocusDirections.kt +++ b/ui/src/main/java/com/m3u/ui/FocusDirections.kt @@ -2,7 +2,7 @@ package com.m3u.ui import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.focus.FocusDirection -import com.m3u.data.leanback.model.RemoteDirection +import com.m3u.data.tv.model.RemoteDirection @OptIn(ExperimentalComposeUiApi::class) fun RemoteDirection.asFocusDirection(): FocusDirection { diff --git a/ui/src/main/java/com/m3u/ui/SnackHost.kt b/ui/src/main/java/com/m3u/ui/SnackHost.kt index ac8deaef7..779485420 100644 --- a/ui/src/main/java/com/m3u/ui/SnackHost.kt +++ b/ui/src/main/java/com/m3u/ui/SnackHost.kt @@ -53,7 +53,7 @@ fun SnackHost( val message by collectMessageAsState() - val leanback by remember { + val tv by remember { derivedStateOf { message.type == Message.TYPE_TELEVISION } } @@ -131,7 +131,7 @@ fun SnackHost( ) ) { when { - leanback -> { + tv -> { Icon( imageVector = Icons.Rounded.Tv, contentDescription = null diff --git a/ui/src/main/java/com/m3u/ui/SortBottomSheet.kt b/ui/src/main/java/com/m3u/ui/SortBottomSheet.kt index d1bd0679b..5853aa0e4 100644 --- a/ui/src/main/java/com/m3u/ui/SortBottomSheet.kt +++ b/ui/src/main/java/com/m3u/ui/SortBottomSheet.kt @@ -35,7 +35,7 @@ import androidx.tv.material3.DenseListItem import com.m3u.i18n.R.string import com.m3u.material.components.BottomSheet import com.m3u.material.components.Icon -import com.m3u.material.components.leanback.dialogFocusable +import com.m3u.material.components.tv.dialogFocusable import com.m3u.material.model.LocalSpacing import androidx.tv.material3.ListItemDefaults as TvListItemDefaults import androidx.tv.material3.MaterialTheme as TvMaterialTheme diff --git a/ui/src/main/java/com/m3u/ui/Toolkit.kt b/ui/src/main/java/com/m3u/ui/Toolkit.kt index 52021a0ca..9ee2a5333 100644 --- a/ui/src/main/java/com/m3u/ui/Toolkit.kt +++ b/ui/src/main/java/com/m3u/ui/Toolkit.kt @@ -11,15 +11,18 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalView import com.m3u.core.architecture.preferences.hiltPreferences -import com.m3u.data.leanback.model.RemoteDirection -import com.m3u.data.leanback.model.keyCode +import com.m3u.data.tv.model.RemoteDirection +import com.m3u.data.tv.model.keyCode import com.m3u.material.LocalM3UHapticFeedback import com.m3u.material.createM3UHapticFeedback +import com.m3u.material.model.LocalSpacing +import com.m3u.material.model.Spacing import com.m3u.material.model.Theme import com.m3u.ui.helper.Helper import com.m3u.ui.helper.LocalHelper import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.milliseconds +import androidx.compose.material3.Typography as Material3Typography @Composable fun Toolkit( @@ -33,7 +36,7 @@ fun Toolkit( val onBackPressedDispatcher = checkNotNull(LocalOnBackPressedDispatcherOwner.current).onBackPressedDispatcher val prevTypography = MaterialTheme.typography - val smartphoneTypography: androidx.compose.material3.Typography = remember(prevTypography) { + val smartphoneTypography: Material3Typography = remember(prevTypography) { prevTypography.withFontFamily(FontFamilies.GoogleSans) } val useDarkTheme = when { @@ -63,9 +66,13 @@ fun Toolkit( } } + val spacing = if (preferences.compactDimension) Spacing.COMPACT + else Spacing.REGULAR + CompositionLocalProvider( LocalHelper provides helper, - LocalM3UHapticFeedback provides createM3UHapticFeedback() + LocalM3UHapticFeedback provides createM3UHapticFeedback(), + LocalSpacing provides spacing ) { Theme( argb = preferences.argb,