make onBackPress action adhere to the ui flow

This commit is contained in:
Christian Schabesberger 2024-08-30 11:21:10 +02:00
parent 8684bf95e1
commit cb122306c6
6 changed files with 47 additions and 18 deletions

View File

@ -153,6 +153,16 @@ enum class UIModeState {
FULLSCREEN_VIDEO_STREAM_SELECT -> PlayMode.FULLSCREEN_VIDEO FULLSCREEN_VIDEO_STREAM_SELECT -> PlayMode.FULLSCREEN_VIDEO
} }
fun getNextModeWhenBackPressed() = when(this) {
EMBEDDED_VIDEO_CHAPTER_SELECT -> EMBEDDED_VIDEO
EMBEDDED_VIDEO_STREAM_SELECT -> EMBEDDED_VIDEO
FULLSCREEN_VIDEO -> EMBEDDED_VIDEO
FULLSCREEN_VIDEO_STREAM_SELECT -> FULLSCREEN_VIDEO
FULLSCREEN_VIDEO_CHAPTER_SELECT -> FULLSCREEN_VIDEO
FULLSCREEN_VIDEO_CONTROLLER_UI -> EMBEDDED_VIDEO
else -> null
}
companion object { companion object {
fun fromPlayMode(playMode: PlayMode?) = fun fromPlayMode(playMode: PlayMode?) =
if (playMode != null) if (playMode != null)

View File

@ -37,6 +37,7 @@ interface VideoPlayerViewModel {
var maxContentRatio: Float var maxContentRatio: Float
var contentFitMode: ContentScale var contentFitMode: ContentScale
val embeddedPlayerDraggedDownBy: SharedFlow<Float> val embeddedPlayerDraggedDownBy: SharedFlow<Float>
val onBackPressed: SharedFlow<Unit>
fun initUIState(instanceState: Bundle) fun initUIState(instanceState: Bundle)
fun play() fun play()
@ -45,6 +46,7 @@ interface VideoPlayerViewModel {
fun nextStream() fun nextStream()
fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig)
fun switchToEmbeddedView() fun switchToEmbeddedView()
fun onBackPressed()
fun showUi() fun showUi()
fun hideUi() fun hideUi()
fun seekPositionChanged(newValue: Float) fun seekPositionChanged(newValue: Float)

View File

@ -37,6 +37,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -127,6 +128,9 @@ class VideoPlayerViewModelImpl @Inject constructor(
private var mutableEmbeddedPlayerDraggedDownBy = MutableSharedFlow<Float>() private var mutableEmbeddedPlayerDraggedDownBy = MutableSharedFlow<Float>()
override val embeddedPlayerDraggedDownBy = mutableEmbeddedPlayerDraggedDownBy.asSharedFlow() override val embeddedPlayerDraggedDownBy = mutableEmbeddedPlayerDraggedDownBy.asSharedFlow()
private var mutableOnBackPressed = MutableSharedFlow<Unit>()
override val onBackPressed: SharedFlow<Unit> = mutableOnBackPressed.asSharedFlow()
private fun installNewPlayer() { private fun installNewPlayer() {
internalPlayer?.let { player -> internalPlayer?.let { player ->
Log.d(TAG, "Install player: ${player.videoSize.width}") Log.d(TAG, "Install player: ${player.videoSize.width}")
@ -298,9 +302,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
} }
override fun embeddedDraggedDown(offset: Float) { override fun embeddedDraggedDown(offset: Float) {
viewModelScope.launch { saveTryEmit(mutableEmbeddedPlayerDraggedDownBy, offset)
mutableEmbeddedPlayerDraggedDownBy.emit(offset)
}
} }
override fun fastSeek(count: Int) { override fun fastSeek(count: Int) {
@ -328,7 +330,6 @@ class VideoPlayerViewModelImpl @Inject constructor(
} }
override fun brightnessChange(changeRate: Float, systemBrightness: Float) { override fun brightnessChange(changeRate: Float, systemBrightness: Float) {
if (mutableUiState.value.uiMode.fullscreen) { if (mutableUiState.value.uiMode.fullscreen) {
val currentBrightness = mutableUiState.value.brightness val currentBrightness = mutableUiState.value.brightness
?: if (systemBrightness < 0f) 0.5f else systemBrightness ?: if (systemBrightness < 0f) 0.5f else systemBrightness
@ -381,8 +382,16 @@ class VideoPlayerViewModelImpl @Inject constructor(
updateUiMode(UIModeState.EMBEDDED_VIDEO) updateUiMode(UIModeState.EMBEDDED_VIDEO)
} }
override fun onBackPressed() {
val nextMode = uiState.value.uiMode.getNextModeWhenBackPressed()
if (nextMode != null) {
updateUiMode(nextMode)
} else {
saveTryEmit(mutableOnBackPressed, Unit)
}
}
override fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) { override fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) {
println("gurken fullscreen: ${embeddedUiConfig}")
uiVisibilityJob?.cancel() uiVisibilityJob?.cancel()
finishFastSeek() finishFastSeek()
@ -422,4 +431,12 @@ class VideoPlayerViewModelImpl @Inject constructor(
} }
} }
} }
private fun <T> saveTryEmit(sharedFlow: MutableSharedFlow<T>, value: T) {
if(sharedFlow.tryEmit(value)) {
viewModelScope.launch {
sharedFlow.emit(value)
}
}
}
} }

View File

@ -4,6 +4,7 @@ import android.os.Bundle
import androidx.media3.common.Player import androidx.media3.common.Player
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import net.newpipe.newplayer.NewPlayer import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.ui.ContentScale import net.newpipe.newplayer.ui.ContentScale
@ -16,6 +17,7 @@ open class VideoPlayerViewModelDummy : VideoPlayerViewModel {
override var maxContentRatio = 16F / 9F override var maxContentRatio = 16F / 9F
override var contentFitMode = ContentScale.FIT_INSIDE override var contentFitMode = ContentScale.FIT_INSIDE
override val embeddedPlayerDraggedDownBy = MutableSharedFlow<Float>().asSharedFlow() override val embeddedPlayerDraggedDownBy = MutableSharedFlow<Float>().asSharedFlow()
override val onBackPressed: SharedFlow<Unit> = MutableSharedFlow<Unit>().asSharedFlow()
override fun initUIState(instanceState: Bundle) { override fun initUIState(instanceState: Bundle) {
println("dummy impl") println("dummy impl")
@ -29,6 +31,10 @@ open class VideoPlayerViewModelDummy : VideoPlayerViewModel {
println("dummy impl") println("dummy impl")
} }
override fun onBackPressed() {
println("dummy impl")
}
override fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) { override fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) {
println("dummy impl") println("dummy impl")
} }

View File

@ -64,19 +64,6 @@ fun VideoPlayerControllerUI(
viewModel: VideoPlayerViewModel, uiState: VideoPlayerUIState viewModel: VideoPlayerViewModel, uiState: VideoPlayerUIState
) { ) {
val context = LocalContext.current
if (uiState.uiMode.fullscreen) {
BackHandler {
viewModel.switchToEmbeddedView()
}
}
val internalBrightnessChange = { rateChange: Float ->
val systemBrightness = getDefaultBrightness(context as Activity)
viewModel.brightnessChange(rateChange, systemBrightness)
}
val insets = getInsets() val insets = getInsets()
AnimatedVisibility(uiState.uiMode.controllerUiVisible) { AnimatedVisibility(uiState.uiMode.controllerUiVisible) {

View File

@ -24,6 +24,7 @@ import android.app.Activity
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.util.Log import android.util.Log
import android.view.SurfaceView import android.view.SurfaceView
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
@ -105,6 +106,12 @@ fun VideoPlayerUI(
} }
} }
if (uiState.uiMode.fullscreen) {
BackHandler {
viewModel.onBackPressed()
}
}
// setup immersive mode // setup immersive mode
LaunchedEffect( LaunchedEffect(
key1 = uiState.uiMode.systemInsetsVisible, key1 = uiState.uiMode.systemInsetsVisible,