fix(video): pause playback when app goes to background

Re-introduces the lifecycle observer that was dropped in the Feb 24
flow refactor of GetVideoController (f2410a69 "removing most of the
little hacks to get the controller to work in the lifecycle"). Without
it, the scroll-position mutex is the only thing that pauses a video —
and the window's visible rect doesn't change on ON_PAUSE, so the
currently-playing video kept playing forever behind other apps.

Pause on ON_PAUSE, resume on ON_RESUME if the video is still the
visible/active one. The explicit BackgroundMedia (PiP) instance is
preserved as the opt-in to keep playing.
This commit is contained in:
Claude
2026-05-16 02:27:05 +00:00
parent 3eb1403540
commit 0de70e51cd
@@ -26,6 +26,9 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.ui.platform.LocalView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.media3.common.Player
import com.vitorpamplona.amethyst.service.playback.pip.BackgroundMedia
@@ -75,6 +78,44 @@ fun ControlWhenPlayerIsActive(
listener.destroy()
}
}
// Pause when the host activity leaves the foreground; resume the visible
// video when it comes back. The scroll-based mutex above only reacts to
// on-screen position, which doesn't change on background — so without
// this, videos play forever behind another app.
// Skip the explicit BackgroundMedia (PiP) instance: the user opted that
// one into keep-playing.
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner, mediaControllerState) {
val observer =
LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_PAUSE -> {
if (controller.isPlaying && !BackgroundMedia.isMutex(mediaControllerState)) {
controller.pause()
}
}
Lifecycle.Event.ON_RESUME -> {
if (automaticallyStartPlayback &&
isClosestToTheCenterOfTheScreen.value &&
!controller.isPlaying
) {
if (BackgroundMedia.hasBackgroundButNot(mediaControllerState)) {
controller.volume = 0f
}
controller.play()
}
}
else -> {
Unit
}
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}
}
class PlayerEventListener(