From 4ca57d9449bb3575a6bac2817a7a7ee14833dfb8 Mon Sep 17 00:00:00 2001 From: Nils Pukropp Date: Sat, 31 Oct 2026 14:12:28 +0100 Subject: [PATCH] fix(android): a chooser in the player no longer closes on its own The episode, track, speed, chapter and sleep choosers and the More menu live inside the player's controls, and the controls hide four seconds after they come up while the video plays. Hiding them took the open chooser with them, so a sheet being picked from closed at what looked like random. The controls now hold still while a chooser is open. --- .../io/narl/protonstream/playback/PlayerScreen.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/io/narl/protonstream/playback/PlayerScreen.kt b/android/app/src/main/java/io/narl/protonstream/playback/PlayerScreen.kt index 904bfc9..11a3e39 100644 --- a/android/app/src/main/java/io/narl/protonstream/playback/PlayerScreen.kt +++ b/android/app/src/main/java/io/narl/protonstream/playback/PlayerScreen.kt @@ -477,8 +477,12 @@ fun PlayerScreen( // four seconds after it is reached cannot be found again. val exploring = rememberTouchExploration() LaunchedEffect(exploring) { if (exploring) showControls = true } - LaunchedEffect(showControls, state.paused, exploring) { - if (showControls && !state.paused && !exploring) { + // A chooser open over the controls. They hold still under it: the + // choosers live inside the controls, so hiding them closed whatever was + // being picked from, four seconds after the controls came up. + var picking by remember { mutableStateOf(false) } + LaunchedEffect(showControls, state.paused, exploring, picking) { + if (showControls && !state.paused && !exploring && !picking) { delay(CONTROLS_SECONDS * 1_000) showControls = false } @@ -698,6 +702,7 @@ fun PlayerScreen( landscapeLocked = landscapeLocked, media = key, sleep = sleep, + onPicking = { picking = it }, onLock = { locked = true showControls = false @@ -949,6 +954,7 @@ private fun PlayerControls( landscapeLocked: Boolean, media: String, sleep: SleepTimer?, + onPicking: (Boolean) -> Unit, onLock: () -> Unit, ) { val scope = rememberCoroutineScope() @@ -957,6 +963,10 @@ private fun PlayerControls( var showEpisodes by remember { mutableStateOf(false) } var showChapters by remember { mutableStateOf(false) } var showSpeeds by remember { mutableStateOf(false) } + var more by remember { mutableStateOf(false) } + val picking = more || showSleep || choosing != null || showEpisodes || showChapters || showSpeeds + LaunchedEffect(picking) { onPicking(picking) } + DisposableEffect(Unit) { onDispose { onPicking(false) } } // What the store says, so the dialog opens on the rate that is playing. var speed by remember { mutableStateOf(1.0) } LaunchedEffect(Unit) { @@ -1037,7 +1047,6 @@ private fun PlayerControls( Row(verticalAlignment = Alignment.CenterVertically) { if (!roomForAll) { CompactIcon(Icons.Default.Subtitles, "Subtitles") { choosing = "sub" } - var more by remember { mutableStateOf(false) } Box { CompactIcon(Icons.Default.MoreVert, "More") { more = true } DropdownMenu(expanded = more, onDismissRequest = { more = false }) {