add ui mode states
This commit is contained in:
parent
151ab85ea8
commit
8ac9a5a6ff
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="1280"
|
||||
height="720"
|
||||
viewBox="0 0 338.66667 190.5"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
||||
sodipodi:docname="tiny_placeholder.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="0.53354917"
|
||||
inkscape:cx="641.92772"
|
||||
inkscape:cy="411.39601"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="vector-effect:non-scaling-stroke;fill:#000000;fill-opacity:0.2358;stroke:none;stroke-width:0.264583;-inkscape-stroke:hairline"
|
||||
id="rect1"
|
||||
width="338.66666"
|
||||
height="190.5"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
style="vector-effect:non-scaling-stroke;fill:#ffffff;fill-opacity:0.671068;stroke:none;stroke-width:0.264583;-inkscape-stroke:hairline"
|
||||
d="M 125.56261,40.662967 V 149.83703 l 91.77479,-52.9862 z"
|
||||
id="path1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
|
@ -31,7 +31,7 @@ class ActivityBrainSlug(val viewModel: VideoPlayerViewModel) {
|
|||
set(value) {
|
||||
field = value
|
||||
field?.let {
|
||||
if (viewModel.uiState.value.fullscreen) {
|
||||
if (viewModel.uiState.value.uiMode.fullscreen) {
|
||||
removeSystemInsets()
|
||||
} else {
|
||||
addSystemInsets()
|
||||
|
@ -43,7 +43,7 @@ class ActivityBrainSlug(val viewModel: VideoPlayerViewModel) {
|
|||
var fullscreenPlayerView: VideoPlayerView? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (viewModel.uiState.value.fullscreen) {
|
||||
if (viewModel.uiState.value.uiMode.fullscreen) {
|
||||
value?.visibility = View.VISIBLE
|
||||
field?.viewModel = viewModel
|
||||
} else {
|
||||
|
@ -55,7 +55,7 @@ class ActivityBrainSlug(val viewModel: VideoPlayerViewModel) {
|
|||
var embeddedPlayerView: VideoPlayerView? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (viewModel.uiState.value.fullscreen) {
|
||||
if (viewModel.uiState.value.uiMode.fullscreen) {
|
||||
field?.viewModel = null
|
||||
value?.visibility = View.GONE
|
||||
} else {
|
||||
|
@ -83,7 +83,7 @@ class ActivityBrainSlug(val viewModel: VideoPlayerViewModel) {
|
|||
|
||||
fun addViewToHideOnFullscreen(view: View) {
|
||||
viewsToHideOnFullscreen.add(view)
|
||||
if (viewModel.uiState.value.fullscreen) {
|
||||
if (viewModel.uiState.value.uiMode.fullscreen) {
|
||||
view.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package net.newpipe.newplayer.model
|
||||
|
||||
enum class UIModeState {
|
||||
PLACEHOLDER,
|
||||
|
||||
EMBEDDED_VIDEO,
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI,
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT,
|
||||
EMBEDDED_VIDEO_STREAM_SELECT,
|
||||
|
||||
FULLSCREEN_VIDEO,
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI,
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT,
|
||||
FULLSCREEN_VIDEO_STREAM_SELECT;
|
||||
|
||||
val fullscreen: Boolean
|
||||
get() =
|
||||
when (this) {
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> true
|
||||
EMBEDDED_VIDEO_STREAM_SELECT -> true
|
||||
FULLSCREEN_VIDEO -> true
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> true
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT -> true
|
||||
FULLSCREEN_VIDEO_STREAM_SELECT -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val controllerUiVisible: Boolean
|
||||
get() =
|
||||
when (this) {
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI -> true
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val systemUiVisible: Boolean
|
||||
get() =
|
||||
when (this) {
|
||||
FULLSCREEN_VIDEO -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
// STATE TRANSITIONS
|
||||
|
||||
fun getControllerUiVisibleState() =
|
||||
when (this) {
|
||||
EMBEDDED_VIDEO -> EMBEDDED_VIDEO_CONTROLLER_UI
|
||||
FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO_CONTROLLER_UI
|
||||
|
||||
else -> this
|
||||
}
|
||||
|
||||
|
||||
fun getUiHiddenState() =
|
||||
when (this) {
|
||||
FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> FULLSCREEN_VIDEO
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT -> FULLSCREEN_VIDEO
|
||||
FULLSCREEN_VIDEO_STREAM_SELECT -> FULLSCREEN_VIDEO
|
||||
|
||||
|
||||
EMBEDDED_VIDEO -> EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI -> EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_STREAM_SELECT -> EMBEDDED_VIDEO
|
||||
|
||||
else -> this
|
||||
}
|
||||
|
||||
|
||||
fun getStreamSelectUiState() =
|
||||
when (this) {
|
||||
FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO_STREAM_SELECT
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT -> FULLSCREEN_VIDEO_STREAM_SELECT
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> FULLSCREEN_VIDEO_STREAM_SELECT
|
||||
|
||||
EMBEDDED_VIDEO -> EMBEDDED_VIDEO_STREAM_SELECT
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> EMBEDDED_VIDEO_STREAM_SELECT
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI -> EMBEDDED_VIDEO_STREAM_SELECT
|
||||
|
||||
else -> this
|
||||
}
|
||||
|
||||
fun getChapterSelectUiState() =
|
||||
when (this) {
|
||||
FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO_CHAPTER_SELECT
|
||||
FULLSCREEN_VIDEO_STREAM_SELECT -> FULLSCREEN_VIDEO_CHAPTER_SELECT
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> FULLSCREEN_VIDEO_CHAPTER_SELECT
|
||||
|
||||
EMBEDDED_VIDEO -> EMBEDDED_VIDEO_CHAPTER_SELECT
|
||||
EMBEDDED_VIDEO_STREAM_SELECT -> EMBEDDED_VIDEO_CHAPTER_SELECT
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI -> EMBEDDED_VIDEO_CHAPTER_SELECT
|
||||
|
||||
else -> this
|
||||
}
|
||||
}
|
|
@ -26,9 +26,8 @@ import net.newpipe.newplayer.ui.ContentScale
|
|||
|
||||
@Parcelize
|
||||
data class VideoPlayerUIState(
|
||||
val uiMode: UIModeState,
|
||||
val playing: Boolean,
|
||||
var fullscreen: Boolean,
|
||||
val uiVisible: Boolean,
|
||||
val contentRatio: Float,
|
||||
val embeddedUiRatio: Float,
|
||||
val contentFitMode: ContentScale,
|
||||
|
@ -45,9 +44,8 @@ data class VideoPlayerUIState(
|
|||
) : Parcelable {
|
||||
companion object {
|
||||
val DEFAULT = VideoPlayerUIState(
|
||||
uiMode = UIModeState.PLACEHOLDER,
|
||||
playing = false,
|
||||
fullscreen = false,
|
||||
uiVisible = false,
|
||||
contentRatio = 16 / 9f,
|
||||
embeddedUiRatio = 16f / 9f,
|
||||
contentFitMode = ContentScale.FIT_INSIDE,
|
||||
|
|
|
@ -133,6 +133,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
|
||||
override fun onVideoSizeChanged(videoSize: androidx.media3.common.VideoSize) {
|
||||
super.onVideoSizeChanged(videoSize)
|
||||
|
||||
updateContentRatio(VideoSize.fromMedia3VideoSize(videoSize))
|
||||
}
|
||||
|
||||
|
@ -210,7 +211,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
|
||||
override fun showUi() {
|
||||
mutableUiState.update {
|
||||
it.copy(uiVisible = true)
|
||||
it.copy(uiMode = it.uiMode.getControllerUiVisibleState())
|
||||
}
|
||||
resetHideUiDelayedJob()
|
||||
resetProgressUpdatePeriodicallyJob()
|
||||
|
@ -255,7 +256,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
progressUpdaterJob?.cancel()
|
||||
uiVisibilityJob?.cancel()
|
||||
mutableUiState.update {
|
||||
it.copy(uiVisible = false)
|
||||
it.copy(uiMode = it.uiMode.getUiHiddenState())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +284,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
if (mutableUiState.value.uiVisible) {
|
||||
if (mutableUiState.value.uiMode.controllerUiVisible) {
|
||||
resetHideUiDelayedJob()
|
||||
}
|
||||
}
|
||||
|
@ -301,7 +302,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
}
|
||||
|
||||
override fun brightnessChange(changeRate: Float, systemBrightness: Float) {
|
||||
if (mutableUiState.value.fullscreen) {
|
||||
if (mutableUiState.value.uiMode.fullscreen) {
|
||||
val currentBrightness = mutableUiState.value.brightness
|
||||
?: if (systemBrightness < 0f) 0.5f else systemBrightness
|
||||
Log.d(
|
||||
|
@ -336,7 +337,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
uiVisibilityJob?.cancel()
|
||||
finishFastSeek()
|
||||
mutableUiState.update {
|
||||
it.copy(fullscreen = false, uiVisible = false)
|
||||
it.copy(uiMode = UIModeState.EMBEDDED_VIDEO)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,7 +346,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
|||
uiVisibilityJob?.cancel()
|
||||
finishFastSeek()
|
||||
mutableUiState.update {
|
||||
it.copy(fullscreen = true, uiVisible = false)
|
||||
it.copy(uiMode = UIModeState.FULLSCREEN_VIDEO)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
package net.newpipe.newplayer.ui
|
||||
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
|
@ -57,15 +56,16 @@ import net.newpipe.newplayer.ui.videoplayer.TopUI
|
|||
import net.newpipe.newplayer.ui.videoplayer.GestureUI
|
||||
import net.newpipe.newplayer.utils.getDefaultBrightness
|
||||
|
||||
val CONTROLLER_UI_BACKGROUND_COLOR = Color(0x75000000)
|
||||
|
||||
@Composable
|
||||
fun VideoPlayerControllerUI(
|
||||
viewModel: VideoPlayerViewModel,
|
||||
uiState: VideoPlayerUIState
|
||||
viewModel: VideoPlayerViewModel, uiState: VideoPlayerUIState
|
||||
) {
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
if (uiState.fullscreen) {
|
||||
if (uiState.uiMode.fullscreen) {
|
||||
BackHandler {
|
||||
viewModel.switchToEmbeddedView()
|
||||
}
|
||||
|
@ -77,21 +77,16 @@ fun VideoPlayerControllerUI(
|
|||
}
|
||||
|
||||
val insets =
|
||||
WindowInsets.systemBars
|
||||
.union(WindowInsets.displayCutout)
|
||||
.union(WindowInsets.waterfall)
|
||||
WindowInsets.systemBars.union(WindowInsets.displayCutout).union(WindowInsets.waterfall)
|
||||
|
||||
AnimatedVisibility(uiState.uiVisible) {
|
||||
AnimatedVisibility(uiState.uiMode.controllerUiVisible) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(), color = Color(0x75000000)
|
||||
modifier = Modifier.fillMaxSize(), color = CONTROLLER_UI_BACKGROUND_COLOR
|
||||
) {}
|
||||
}
|
||||
|
||||
GestureUI(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
viewModel = viewModel,
|
||||
uiState = uiState
|
||||
modifier = Modifier.fillMaxSize(), viewModel = viewModel, uiState = uiState
|
||||
)
|
||||
|
||||
if (uiState.isLoading) {
|
||||
|
@ -106,7 +101,7 @@ fun VideoPlayerControllerUI(
|
|||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(uiState.uiVisible) {
|
||||
AnimatedVisibility(uiState.uiMode.controllerUiVisible) {
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
CenterUI(
|
||||
|
@ -117,7 +112,7 @@ fun VideoPlayerControllerUI(
|
|||
}
|
||||
|
||||
Box(
|
||||
modifier = if (uiState.fullscreen) Modifier.windowInsetsPadding(insets) else Modifier
|
||||
modifier = if (uiState.uiMode.fullscreen) Modifier.windowInsetsPadding(insets) else Modifier
|
||||
) {
|
||||
TopUI(
|
||||
modifier = Modifier
|
||||
|
|
|
@ -87,21 +87,21 @@ fun VideoPlayerUI(
|
|||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
// Setup fullscreen
|
||||
if (uiState.fullscreen) {
|
||||
if (uiState.uiMode.fullscreen) {
|
||||
LaunchedEffect(key1 = true) {
|
||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = false
|
||||
}
|
||||
}
|
||||
|
||||
// Setup immersive mode
|
||||
if (uiState.fullscreen && !uiState.uiVisible) {
|
||||
LaunchedEffect(key1 = true) {
|
||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
} else {
|
||||
if (uiState.uiMode.systemUiVisible) {
|
||||
LaunchedEffect(key1 = false) {
|
||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
} else {
|
||||
LaunchedEffect(key1 = true) {
|
||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare stuff for the SurfaceView to which the video will be rendered
|
||||
|
@ -117,7 +117,7 @@ fun VideoPlayerUI(
|
|||
}
|
||||
|
||||
// Set Screen Rotation
|
||||
if (uiState.fullscreen) {
|
||||
if (uiState.uiMode.fullscreen) {
|
||||
if (uiState.contentRatio < 1) {
|
||||
LockScreenOrientation(orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
||||
} else {
|
||||
|
@ -141,7 +141,7 @@ fun VideoPlayerUI(
|
|||
// Set UI
|
||||
Surface(
|
||||
modifier = Modifier.then(
|
||||
if (uiState.fullscreen) Modifier.fillMaxSize()
|
||||
if (uiState.uiMode.fullscreen) Modifier.fillMaxSize()
|
||||
else Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(uiState.embeddedUiRatio)
|
||||
|
@ -152,7 +152,8 @@ fun VideoPlayerUI(
|
|||
player = viewModel.internalPlayer,
|
||||
lifecycle = lifecycle,
|
||||
fitMode = uiState.contentFitMode,
|
||||
uiRatio = if (uiState.fullscreen) screenRatio else uiState.embeddedUiRatio,
|
||||
uiRatio = if (uiState.uiMode.fullscreen) screenRatio
|
||||
else uiState.embeddedUiRatio,
|
||||
contentRatio = uiState.contentRatio
|
||||
)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ package net.newpipe.newplayer.ui.theme
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import net.newpipe.newplayer.model.UIModeState
|
||||
import net.newpipe.newplayer.model.VideoPlayerUIState
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||
import net.newpipe.newplayer.ui.PreviewBackgroundSurface
|
||||
|
@ -77,9 +78,8 @@ fun VideoPlayerControllerUIPreviewEmbeddedColorPreview() {
|
|||
VideoPlayerControllerUI(
|
||||
viewModel = VideoPlayerViewModelDummy(),
|
||||
uiState = VideoPlayerUIState.DEFAULT.copy(
|
||||
uiMode = UIModeState.EMBEDDED_VIDEO_CONTROLLER_UI,
|
||||
playing = true,
|
||||
fullscreen = false,
|
||||
uiVisible = true,
|
||||
seekerPosition = 0.3f,
|
||||
isLoading = false,
|
||||
durationInMs = 9 * 60 * 1000,
|
||||
|
|
|
@ -42,6 +42,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import net.newpipe.newplayer.R
|
||||
import net.newpipe.newplayer.model.UIModeState
|
||||
import net.newpipe.newplayer.model.VideoPlayerUIState
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||
|
@ -77,11 +78,11 @@ fun BottomUI(
|
|||
Text(getTimeStringFromMs(uiState.durationInMs, getLocale() ?: Locale.US))
|
||||
|
||||
IconButton(
|
||||
onClick = if (uiState.fullscreen) viewModel::switchToEmbeddedView
|
||||
onClick = if (uiState.uiMode.fullscreen) viewModel::switchToEmbeddedView
|
||||
else viewModel::switchToFullscreen
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (uiState.fullscreen) Icons.Filled.FullscreenExit
|
||||
imageVector = if (uiState.uiMode.fullscreen) Icons.Filled.FullscreenExit
|
||||
else Icons.Filled.Fullscreen,
|
||||
contentDescription = stringResource(R.string.widget_description_toggle_fullscreen)
|
||||
)
|
||||
|
@ -152,7 +153,7 @@ fun VideoPlayerControllerBottomUIPreview() {
|
|||
modifier = Modifier,
|
||||
viewModel = VideoPlayerViewModelDummy(),
|
||||
uiState = VideoPlayerUIState.DEFAULT.copy(
|
||||
fullscreen = true,
|
||||
uiMode = UIModeState.FULLSCREEN_VIDEO_CONTROLLER_UI,
|
||||
seekerPosition = 0.4f,
|
||||
durationInMs = 90 * 60 * 1000,
|
||||
playbackPositionInMs = 3 * 60 * 1000,
|
||||
|
|
|
@ -36,7 +36,7 @@ val INDICATOR_BACKGROUND_COLOR = Color.Black.copy(alpha = 0.3f)
|
|||
fun GestureUI(
|
||||
modifier: Modifier, viewModel: VideoPlayerViewModel, uiState: VideoPlayerUIState
|
||||
) {
|
||||
if (uiState.fullscreen) {
|
||||
if (uiState.uiMode.fullscreen) {
|
||||
FullscreenGestureUI(
|
||||
modifier = modifier, viewModel = viewModel, uiState = uiState
|
||||
)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package net.newpipe.newplayer.ui.videoplayer
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import net.newpipe.newplayer.model.VideoPlayerUIState
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||
import net.newpipe.newplayer.ui.CONTROLLER_UI_BACKGROUND_COLOR
|
||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||
|
||||
@Composable
|
||||
fun StreamSelectUI(
|
||||
isChapterSelect: Boolean = false,
|
||||
viewModel: VideoPlayerViewModel,
|
||||
uiState: VideoPlayerUIState
|
||||
) {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = CONTROLLER_UI_BACKGROUND_COLOR) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
|
||||
}
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun ChapterSelectTopBar() {
|
||||
|
||||
}
|
||||
|
||||
@Preview(device = "id:pixel_5")
|
||||
@Composable
|
||||
fun VideoPlayerStreamSelectUIPreview() {
|
||||
VideoPlayerTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = Color.Green) {
|
||||
StreamSelectUI(
|
||||
viewModel = VideoPlayerViewModelDummy(),
|
||||
uiState = VideoPlayerUIState.DEFAULT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ fun EmbeddedGestureUI(
|
|||
}
|
||||
|
||||
val defaultOnRegularTap = {
|
||||
if (uiState.uiVisible) {
|
||||
if (uiState.uiMode.controllerUiVisible) {
|
||||
viewModel.hideUi()
|
||||
} else {
|
||||
viewModel.showUi()
|
||||
|
|
|
@ -44,6 +44,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import net.newpipe.newplayer.model.UIModeState
|
||||
import net.newpipe.newplayer.model.VideoPlayerUIState
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
||||
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||
|
@ -51,16 +52,12 @@ import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
|||
import net.newpipe.newplayer.utils.getDefaultBrightness
|
||||
|
||||
private enum class IndicatorMode {
|
||||
NONE,
|
||||
VOLUME_INDICATOR_VISSIBLE,
|
||||
BRIGHTNESS_INDICATOR_VISSIBLE
|
||||
NONE, VOLUME_INDICATOR_VISSIBLE, BRIGHTNESS_INDICATOR_VISSIBLE
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun FullscreenGestureUI(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: VideoPlayerViewModel,
|
||||
uiState: VideoPlayerUIState
|
||||
modifier: Modifier = Modifier, viewModel: VideoPlayerViewModel, uiState: VideoPlayerUIState
|
||||
) {
|
||||
|
||||
var heightPx by remember {
|
||||
|
@ -72,7 +69,7 @@ fun FullscreenGestureUI(
|
|||
}
|
||||
|
||||
val defaultOnRegularTap = {
|
||||
if (uiState.uiVisible) {
|
||||
if (uiState.uiMode.controllerUiVisible) {
|
||||
viewModel.hideUi()
|
||||
} else {
|
||||
viewModel.showUi()
|
||||
|
@ -87,9 +84,7 @@ fun FullscreenGestureUI(
|
|||
heightPx = coordinates.size.height.toFloat()
|
||||
}) {
|
||||
Row {
|
||||
GestureSurface(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
GestureSurface(modifier = Modifier.weight(1f),
|
||||
onRegularTap = defaultOnRegularTap,
|
||||
onMultiTap = {
|
||||
println("multitap ${-it}")
|
||||
|
@ -100,20 +95,16 @@ fun FullscreenGestureUI(
|
|||
indicatorMode = IndicatorMode.NONE
|
||||
},
|
||||
onMovement = { change ->
|
||||
if (indicatorMode == IndicatorMode.NONE
|
||||
|| indicatorMode == IndicatorMode.BRIGHTNESS_INDICATOR_VISSIBLE
|
||||
) {
|
||||
if (indicatorMode == IndicatorMode.NONE || indicatorMode == IndicatorMode.BRIGHTNESS_INDICATOR_VISSIBLE) {
|
||||
indicatorMode = IndicatorMode.BRIGHTNESS_INDICATOR_VISSIBLE
|
||||
|
||||
if (heightPx != 0f) {
|
||||
viewModel.brightnessChange(-change.y / heightPx, defaultBrightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
}) {
|
||||
FadedAnimationForSeekFeedback(
|
||||
uiState.fastSeekSeconds,
|
||||
backwards = true
|
||||
uiState.fastSeekSeconds, backwards = true
|
||||
) { fastSeekSecondsToDisplay ->
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
FastSeekVisualFeedback(
|
||||
|
@ -124,19 +115,14 @@ fun FullscreenGestureUI(
|
|||
}
|
||||
}
|
||||
}
|
||||
GestureSurface(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
GestureSurface(modifier = Modifier.weight(1f),
|
||||
onRegularTap = defaultOnRegularTap,
|
||||
onMovement = { movement ->
|
||||
if (0 < movement.y) {
|
||||
viewModel.switchToEmbeddedView()
|
||||
}
|
||||
}
|
||||
)
|
||||
GestureSurface(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
})
|
||||
GestureSurface(modifier = Modifier.weight(1f),
|
||||
onRegularTap = defaultOnRegularTap,
|
||||
onMultiTap = viewModel::fastSeek,
|
||||
onMultiTapFinished = viewModel::finishFastSeek,
|
||||
|
@ -144,16 +130,13 @@ fun FullscreenGestureUI(
|
|||
indicatorMode = IndicatorMode.NONE
|
||||
},
|
||||
onMovement = { change ->
|
||||
if (indicatorMode == IndicatorMode.NONE
|
||||
|| indicatorMode == IndicatorMode.VOLUME_INDICATOR_VISSIBLE
|
||||
) {
|
||||
if (indicatorMode == IndicatorMode.NONE || indicatorMode == IndicatorMode.VOLUME_INDICATOR_VISSIBLE) {
|
||||
indicatorMode = IndicatorMode.VOLUME_INDICATOR_VISSIBLE
|
||||
if (heightPx != 0f) {
|
||||
viewModel.volumeChange(-change.y / heightPx)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
}) {
|
||||
FadedAnimationForSeekFeedback(uiState.fastSeekSeconds) { fastSeekSecondsToDisplay ->
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
FastSeekVisualFeedback(
|
||||
|
@ -228,13 +211,11 @@ fun FullscreenGestureUIPreview() {
|
|||
VideoPlayerTheme {
|
||||
Surface(modifier = Modifier.wrapContentSize(), color = Color.DarkGray) {
|
||||
FullscreenGestureUI(
|
||||
modifier = Modifier,
|
||||
object : VideoPlayerViewModelDummy() {
|
||||
modifier = Modifier, object : VideoPlayerViewModelDummy() {
|
||||
override fun fastSeek(steps: Int) {
|
||||
println("fast seek by $steps steps")
|
||||
}
|
||||
},
|
||||
VideoPlayerUIState.DEFAULT
|
||||
}, VideoPlayerUIState.DEFAULT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +271,8 @@ fun FullscreenGestureUIPreviewInteractive() {
|
|||
}
|
||||
},
|
||||
uiState = VideoPlayerUIState.DEFAULT.copy(
|
||||
uiVisible = uiVisible,
|
||||
uiMode = if (uiVisible) UIModeState.FULLSCREEN_VIDEO_CONTROLLER_UI
|
||||
else UIModeState.FULLSCREEN_VIDEO,
|
||||
fastSeekSeconds = seekSeconds,
|
||||
soundVolume = soundVolume,
|
||||
brightness = brightnessValue
|
||||
|
|
Loading…
Reference in New Issue