add touchable surface

This commit is contained in:
Christian Schabesberger 2024-07-23 14:09:11 +02:00
parent b5b75558b5
commit 5a2f62b55e
3 changed files with 123 additions and 44 deletions

View File

@ -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")
}

View File

@ -18,10 +18,11 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/
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 = {})
}
}
}

View File

@ -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
)
}
}