From 5a2f62b55e357c9ecb5aa691ec58d93ad8fc18dc Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 23 Jul 2024 14:09:11 +0200 Subject: [PATCH] add touchable surface --- .../newplayer/model/VideoPlayerViewModel.kt | 41 +++++- .../newplayer/ui/VideoPlayerControllerUI.kt | 121 ++++++++++++------ .../net/newpipe/newplayer/ui/VideoPlayerUI.kt | 5 +- 3 files changed, 123 insertions(+), 44 deletions(-) diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt index 304201c..768be28 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt @@ -28,17 +28,23 @@ import android.util.Log import androidx.annotation.RequiresApi import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.media3.common.Player import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import javax.inject.Inject import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch import net.newpipe.newplayer.utils.VideoSize import kotlinx.parcelize.Parcelize import net.newpipe.newplayer.NewPlayer import net.newpipe.newplayer.ui.ContentScale +import java.lang.Thread.sleep val VIDEOPLAYER_UI_STATE = "video_player_ui_state" @@ -48,6 +54,7 @@ private const val TAG = "VideoPlayerViewModel" data class VideoPlayerUIState( val playing: Boolean, var fullscreen: Boolean, + val uiVissible: Boolean, var uiVisible: Boolean, val contentRatio: Float, val uiRatio: Float, @@ -57,6 +64,7 @@ data class VideoPlayerUIState( val DEFAULT = VideoPlayerUIState( playing = false, fullscreen = false, + uiVissible = false, uiVisible = false, contentRatio = 16 / 9F, uiRatio = 16F / 9F, @@ -81,6 +89,8 @@ interface VideoPlayerViewModel { fun nextStream() fun switchToFullscreen() fun switchToEmbeddedView() + fun showUi() + fun hideUi() interface FullscreenListener { fun onFullscreenToggle(isFullscreen: Boolean) @@ -96,6 +106,7 @@ class VideoPlayerViewModelImpl @Inject constructor( // private private val mutableUiState = MutableStateFlow(VideoPlayerUIState.DEFAULT) private var currentContentRatio = 1F + private var uiVisibilityJob:Job? = null //interface override var fullscreenListener: VideoPlayerViewModel.FullscreenListener? = null @@ -169,7 +180,7 @@ class VideoPlayerViewModelImpl @Inject constructor( fun updateContentRatio(videoSize: VideoSize) { val newRatio = videoSize.getRatio() - val ratio = if(newRatio.isNaN()) currentContentRatio else newRatio + val ratio = if (newRatio.isNaN()) currentContentRatio else newRatio currentContentRatio = ratio Log.d(TAG, "Update Content ratio: $ratio") mutableUiState.update { @@ -217,6 +228,26 @@ class VideoPlayerViewModelImpl @Inject constructor( Log.e(TAG, "implement next stream") } + override fun showUi() { + mutableUiState.update { + it.copy(uiVissible = true) + } + uiVisibilityJob?.cancel() + uiVisibilityJob = viewModelScope.launch { + delay(2000) + mutableUiState.update { + it.copy(uiVissible = false) + } + } + } + + override fun hideUi() { + uiVisibilityJob?.cancel() + mutableUiState.update { + it.copy(uiVissible = false) + } + } + override fun switchToEmbeddedView() { fullscreenListener?.onFullscreenToggle(false) mutableUiState.update { @@ -267,6 +298,14 @@ class VideoPlayerViewModelImpl @Inject constructor( println("dummy impl") } + override fun showUi() { + println("dummy impl") + } + + override fun hideUi() { + println("dummy impl") + } + override fun pause() { println("dummy pause") } diff --git a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerControllerUI.kt b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerControllerUI.kt index 55c4cb4..42ea72a 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerControllerUI.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerControllerUI.kt @@ -18,10 +18,11 @@ * along with NewPlayer. If not, see . */ - package net.newpipe.newplayer.ui +package net.newpipe.newplayer.ui import androidx.activity.compose.BackHandler import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -85,51 +86,58 @@ import net.newpipe.newplayer.ui.theme.video_player_onSurface fun VideoPlayerControllerUI( isPlaying: Boolean, fullscreen: Boolean, + uiVissible: Boolean, play: () -> Unit, pause: () -> Unit, prevStream: () -> Unit, nextStream: () -> Unit, switchToFullscreen: () -> Unit, - switchToEmbeddedView: () -> Unit + switchToEmbeddedView: () -> Unit, + showUi: () -> Unit, + hideUi: () -> Unit ) { - Surface( - modifier = Modifier.fillMaxSize(), color = Color(0x75000000) - ) { - Box( - modifier = if (fullscreen) { - Modifier - .background(Color.Transparent) - .windowInsetsPadding(WindowInsets.systemBars) - } else { - Modifier - .background(Color.Transparent) + TouchControll(modifier = Modifier, hideUi = hideUi, showUi = showUi, uiVissible = uiVissible) { + if (uiVissible) { + Surface( + modifier = Modifier.fillMaxSize(), color = Color(0x75000000) + ) { + Box( + modifier = if (fullscreen) { + Modifier + .background(Color.Transparent) + .windowInsetsPadding(WindowInsets.systemBars) + } else { + Modifier + .background(Color.Transparent) + } + ) { + TopUI( + modifier = Modifier + .align(Alignment.TopStart) + .fillMaxWidth() + .defaultMinSize(minHeight = 45.dp) + .padding(top = 4.dp, start = 16.dp, end = 16.dp) + ) + CenterUI( + modifier = Modifier.align(Alignment.Center), + isPlaying, + play = play, + pause = pause, + prevStream = prevStream, + nextStream = nextStream + ) + BottomUI( + modifier = Modifier + .align(Alignment.BottomStart) + .padding(start = 16.dp, end = 16.dp) + .defaultMinSize(minHeight = 40.dp) + .fillMaxWidth(), + isFullscreen = fullscreen, + switchToFullscreen, + switchToEmbeddedView + ) + } } - ) { - TopUI( - modifier = Modifier - .align(Alignment.TopStart) - .fillMaxWidth() - .defaultMinSize(minHeight = 45.dp) - .padding(top = 4.dp, start = 16.dp, end = 16.dp) - ) - CenterUI( - modifier = Modifier.align(Alignment.Center), - isPlaying, - play = play, - pause = pause, - prevStream = prevStream, - nextStream = nextStream - ) - BottomUI( - modifier = Modifier - .align(Alignment.BottomStart) - .padding(start = 16.dp, end = 16.dp) - .defaultMinSize(minHeight = 40.dp) - .fillMaxWidth(), - isFullscreen = fullscreen, - switchToFullscreen, - switchToEmbeddedView - ) } } if (fullscreen) { @@ -196,6 +204,26 @@ private fun TopUI(modifier: Modifier) { } } +@Composable +private fun TouchControll( + modifier: Modifier, + hideUi: () -> Unit, + showUi: () -> kotlin.Unit, + uiVissible: Boolean, + content: @Composable () -> Unit +) { + Box(modifier = Modifier + .fillMaxSize() + .clickable { + if (uiVissible) + hideUi() + else + showUi() + }) { + content() + } +} + @Composable private fun MainMenu() { var showMainMenu: Boolean by remember { mutableStateOf(false) } @@ -399,12 +427,15 @@ fun VideoPlayerControllerUIPreviewEmbeded() { PreviewBackgroundSurface { VideoPlayerControllerUI(isPlaying = false, fullscreen = false, + uiVissible = true, play = {}, pause = {}, prevStream = {}, nextStream = {}, switchToFullscreen = {}, - switchToEmbeddedView = {}) + switchToEmbeddedView = {}, + showUi = {}, + hideUi = {}) } } } @@ -416,12 +447,15 @@ fun VideoPlayerControllerUIPreviewLandscape() { PreviewBackgroundSurface { VideoPlayerControllerUI(isPlaying = true, fullscreen = true, + uiVissible = true, play = {}, pause = {}, prevStream = {}, nextStream = {}, switchToEmbeddedView = {}, - switchToFullscreen = {}) + switchToFullscreen = {}, + showUi = {}, + hideUi = {}) } } } @@ -434,12 +468,15 @@ fun VideoPlayerControllerUIPreviewPortrait() { VideoPlayerControllerUI( isPlaying = false, fullscreen = true, + uiVissible = true, play = {}, pause = {}, prevStream = {}, nextStream = {}, switchToEmbeddedView = {}, - switchToFullscreen = {}) + switchToFullscreen = {}, + showUi = {}, + hideUi = {}) } } } \ No newline at end of file diff --git a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt index 893a3f8..12b852f 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt @@ -121,12 +121,15 @@ fun VideoPlayerUI( VideoPlayerControllerUI( isPlaying = uiState.playing, fullscreen = uiState.fullscreen, + uiVissible = uiState.uiVissible, play = viewModel::play, pause = viewModel::pause, prevStream = viewModel::prevStream, nextStream = viewModel::nextStream, switchToFullscreen = viewModel::switchToFullscreen, - switchToEmbeddedView = viewModel::switchToEmbeddedView + switchToEmbeddedView = viewModel::switchToEmbeddedView, + showUi = viewModel::showUi, + hideUi = viewModel::hideUi ) } }