add touchable surface
This commit is contained in:
parent
b5b75558b5
commit
5a2f62b55e
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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 = {})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue