diff --git a/app/src/main/kotlin/com/arflix/tv/MainActivity.kt b/app/src/main/kotlin/com/arflix/tv/MainActivity.kt index 54ef1eea..c1556d15 100644 --- a/app/src/main/kotlin/com/arflix/tv/MainActivity.kt +++ b/app/src/main/kotlin/com/arflix/tv/MainActivity.kt @@ -212,9 +212,6 @@ class MainActivity : ComponentActivity() { DeviceType.PHONE -> ActivityInfo.SCREEN_ORIENTATION_FULL_USER } - // Keep screen on during playback - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) - // All devices use edge-to-edge (setDecorFitsSystemWindows=false). // TV hides the bars; mobile keeps them visible and Compose handles // insets via systemBarsPadding() in the root layout. diff --git a/app/src/main/kotlin/com/arflix/tv/ui/components/KeepScreenOn.kt b/app/src/main/kotlin/com/arflix/tv/ui/components/KeepScreenOn.kt new file mode 100644 index 00000000..b15a3e90 --- /dev/null +++ b/app/src/main/kotlin/com/arflix/tv/ui/components/KeepScreenOn.kt @@ -0,0 +1,30 @@ +package com.arflix.tv.ui.components + +import android.app.Activity +import android.content.ContextWrapper +import android.view.WindowManager +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.platform.LocalContext + +/** + * Keeps the screen on while this composable is in the composition and [active] is true. + * Releases the flag when [active] becomes false or the composable leaves composition. + * + * Use in any screen where media is playing (player, live TV, trailer). + */ +@Composable +fun KeepScreenOn(active: Boolean = true) { + val context = LocalContext.current + DisposableEffect(active) { + if (!active) return@DisposableEffect onDispose {} + val window = generateSequence(context) { (it as? ContextWrapper)?.baseContext } + .filterIsInstance() + .firstOrNull() + ?.window + window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + onDispose { + window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } +} diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsScreen.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsScreen.kt index 4ddfce2f..71484a8c 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsScreen.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsScreen.kt @@ -133,6 +133,7 @@ import com.arflix.tv.data.model.MediaType import com.arflix.tv.data.model.Review import com.arflix.tv.network.OkHttpProvider import com.arflix.tv.ui.components.EpisodeContextMenu +import com.arflix.tv.ui.components.KeepScreenOn import com.arflix.tv.ui.components.SeasonContextMenu import com.arflix.tv.ui.components.LoadingIndicator import com.arflix.tv.ui.components.AppTopBar @@ -228,6 +229,7 @@ fun DetailsScreen( // Stream Selector state var showStreamSelector by remember { mutableStateOf(false) } var showTrailerPlayer by remember { mutableStateOf(false) } + KeepScreenOn(active = showTrailerPlayer) var pendingAutoPlayRequest by remember { mutableStateOf(null) } // Episode Context Menu state diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/player/PlayerScreen.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/player/PlayerScreen.kt index 9afdf44d..585ecdd2 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/player/PlayerScreen.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/player/PlayerScreen.kt @@ -137,6 +137,7 @@ import com.arflix.tv.network.OkHttpProvider import com.arflix.tv.data.model.MediaType import com.arflix.tv.data.model.StreamSource import com.arflix.tv.data.model.Subtitle +import com.arflix.tv.ui.components.KeepScreenOn import com.arflix.tv.ui.components.LoadingIndicator import com.arflix.tv.ui.components.Toast import com.arflix.tv.ui.components.ToastType @@ -302,6 +303,7 @@ fun PlayerScreen( onDispose { } } + KeepScreenOn() var isPlaying by remember { mutableStateOf(false) } var isBuffering by remember { mutableStateOf(true) } var hasPlaybackStarted by remember { mutableStateOf(false) } // Track if playback has actually started diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/TvScreen.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/TvScreen.kt index 54b53b44..225fec9a 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/TvScreen.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/TvScreen.kt @@ -119,6 +119,7 @@ import com.arflix.tv.data.model.IptvNowNext import com.arflix.tv.data.model.IptvProgram import com.arflix.tv.network.OkHttpProvider import com.arflix.tv.ui.components.AppTopBar +import com.arflix.tv.ui.components.KeepScreenOn import com.arflix.tv.ui.components.AppTopBarContentTopInset import com.arflix.tv.util.LocalDeviceType import com.arflix.tv.ui.components.SidebarItem @@ -240,6 +241,7 @@ fun TvScreen( var channelIndex by rememberSaveable { mutableIntStateOf(0) } var selectedChannelId by rememberSaveable { mutableStateOf(null) } var playingChannelId by rememberSaveable { mutableStateOf(null) } + KeepScreenOn(active = playingChannelId != null) var showGroupContextMenu by remember { mutableStateOf(false) } // When launched from Home with a stream URL, start in fullscreen immediately // to avoid a flash of the TV page channel list. diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/live/LiveTvScreen.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/live/LiveTvScreen.kt index 8111aea3..e89b7c87 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/live/LiveTvScreen.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/tv/live/LiveTvScreen.kt @@ -82,6 +82,7 @@ import com.arflix.tv.ui.screens.tv.TvUiState import com.arflix.tv.ui.screens.tv.TvViewModel import com.arflix.tv.network.OkHttpProvider import com.arflix.tv.ui.components.AppTopBar +import com.arflix.tv.ui.components.KeepScreenOn import com.arflix.tv.ui.components.AppTopBarHeight import com.arflix.tv.ui.components.SidebarItem import com.arflix.tv.ui.components.topBarFocusedItem @@ -519,6 +520,7 @@ fun LiveTvScreen( // channel of the first non-empty category. val rememberedChannelByCategory = remember { mutableMapOf() } var playingChannelId by rememberSaveable { mutableStateOf(initialChannelId) } + KeepScreenOn(active = playingChannelId != null) var focusedChannelId by rememberSaveable { mutableStateOf(initialChannelId) } var epgPrefetchAnchorId by rememberSaveable { mutableStateOf(initialChannelId) } var startupChannelApplied by rememberSaveable(selectedProviderId) { mutableStateOf(false) }