make embedded ui config foo have a more streamlinet implementation
This commit is contained in:
parent
888d518304
commit
8ad95be57a
|
@ -0,0 +1,4 @@
|
||||||
|
kotlin version: 2.0.20-Beta2
|
||||||
|
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
|
||||||
|
1. Kotlin compile daemon is ready
|
||||||
|
|
|
@ -55,13 +55,39 @@ enum class UIModeState {
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
val systemUiVisible: Boolean
|
val isStreamSelect: Boolean
|
||||||
get() =
|
get() =
|
||||||
when (this) {
|
when(this) {
|
||||||
|
EMBEDDED_VIDEO_STREAM_SELECT -> true
|
||||||
|
FULLSCREEN_VIDEO_STREAM_SELECT -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
val isChapterSelect: Boolean
|
||||||
|
get() =
|
||||||
|
when(this) {
|
||||||
|
EMBEDDED_VIDEO_CHAPTER_SELECT -> true
|
||||||
|
FULLSCREEN_VIDEO_CHAPTER_SELECT -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
val systemInsetsVisible: Boolean
|
||||||
|
get() =
|
||||||
|
when(this) {
|
||||||
FULLSCREEN_VIDEO -> false
|
FULLSCREEN_VIDEO -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val fitScreenRotation: Boolean
|
||||||
|
get() =
|
||||||
|
when(this) {
|
||||||
|
FULLSCREEN_VIDEO -> true
|
||||||
|
FULLSCREEN_VIDEO_CONTROLLER_UI -> true
|
||||||
|
FULLSCREEN_VIDEO_CHAPTER_SELECT -> true
|
||||||
|
FULLSCREEN_VIDEO_STREAM_SELECT -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
// STATE TRANSITIONS
|
// STATE TRANSITIONS
|
||||||
|
|
||||||
fun getControllerUiVisibleState() =
|
fun getControllerUiVisibleState() =
|
||||||
|
@ -72,7 +98,6 @@ enum class UIModeState {
|
||||||
else -> this
|
else -> this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getUiHiddenState() =
|
fun getUiHiddenState() =
|
||||||
when (this) {
|
when (this) {
|
||||||
FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO
|
FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO
|
||||||
|
|
|
@ -43,7 +43,7 @@ interface VideoPlayerViewModel {
|
||||||
fun pause()
|
fun pause()
|
||||||
fun prevStream()
|
fun prevStream()
|
||||||
fun nextStream()
|
fun nextStream()
|
||||||
fun switchToFullscreen()
|
fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig)
|
||||||
fun switchToEmbeddedView()
|
fun switchToEmbeddedView()
|
||||||
fun showUi()
|
fun showUi()
|
||||||
fun hideUi()
|
fun hideUi()
|
||||||
|
@ -54,5 +54,6 @@ interface VideoPlayerViewModel {
|
||||||
fun finishFastSeek()
|
fun finishFastSeek()
|
||||||
fun brightnessChange(changeRate: Float, systemBrightness: Float)
|
fun brightnessChange(changeRate: Float, systemBrightness: Float)
|
||||||
fun volumeChange(changeRate: Float)
|
fun volumeChange(changeRate: Float)
|
||||||
fun onReportEmbeddedConfig(embeddedUiConfig: EmbeddedUiConfig?)
|
fun openStreamSelection(selectChapter: Boolean)
|
||||||
|
fun closeStreamSelection()
|
||||||
}
|
}
|
|
@ -65,12 +65,15 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
private var uiVisibilityJob: Job? = null
|
private var uiVisibilityJob: Job? = null
|
||||||
private var progressUpdaterJob: Job? = null
|
private var progressUpdaterJob: Job? = null
|
||||||
|
|
||||||
|
// this is necesary to restore the embedded view UI configuration when returning from fullscreen
|
||||||
|
private var embeddedUiConfig: EmbeddedUiConfig? = null
|
||||||
|
|
||||||
private val audioManager =
|
private val audioManager =
|
||||||
getSystemService(application.applicationContext, AudioManager::class.java)!!
|
getSystemService(application.applicationContext, AudioManager::class.java)!!
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val soundVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat() /
|
val soundVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||||
audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
|
.toFloat() / audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
|
||||||
mutableUiState.update {
|
mutableUiState.update {
|
||||||
it.copy(soundVolume = soundVolume)
|
it.copy(soundVolume = soundVolume)
|
||||||
}
|
}
|
||||||
|
@ -154,7 +157,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
override fun onPlaylistMetadataChanged(mediaMetadata: MediaMetadata) {
|
override fun onPlaylistMetadataChanged(mediaMetadata: MediaMetadata) {
|
||||||
super.onPlaylistMetadataChanged(mediaMetadata)
|
super.onPlaylistMetadataChanged(mediaMetadata)
|
||||||
updatePlaylist()
|
updatePlaylist()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
newPlayer?.let { newPlayer ->
|
newPlayer?.let { newPlayer ->
|
||||||
|
@ -163,7 +166,8 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
val currentMode = mutableUiState.value.uiMode.toPlayMode()
|
val currentMode = mutableUiState.value.uiMode.toPlayMode()
|
||||||
if (currentMode != newMode) {
|
if (currentMode != newMode) {
|
||||||
mutableUiState.update {
|
mutableUiState.update {
|
||||||
it.copy(uiMode = UIModeState.fromPlayMode(newMode))
|
it.copy(uiMode = UIModeState.fromPlayMode(newMode),
|
||||||
|
embeddedUiConfig = embeddedUiConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,18 +357,20 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReportEmbeddedConfig(embeddedUiConfig: EmbeddedUiConfig?) {
|
override fun openStreamSelection(selectChapter: Boolean) {
|
||||||
if (embeddedUiConfig == null) {
|
mutableUiState.update {
|
||||||
mutableUiState.update {
|
it.copy(
|
||||||
it.copy(embeddedUiConfig = null)
|
uiMode = if (selectChapter) it.uiMode.getChapterSelectUiState()
|
||||||
}
|
else it.uiMode.getStreamSelectUiState()
|
||||||
} else {
|
)
|
||||||
if (uiState.value.embeddedUiConfig == null) {
|
}
|
||||||
println("gurken: ${embeddedUiConfig}")
|
}
|
||||||
mutableUiState.update {
|
|
||||||
it.copy(embeddedUiConfig = embeddedUiConfig)
|
override fun closeStreamSelection() {
|
||||||
}
|
mutableUiState.update {
|
||||||
}
|
it.copy(
|
||||||
|
uiMode = it.uiMode.getUiHiddenState()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,10 +380,11 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
updateUiMode(UIModeState.EMBEDDED_VIDEO)
|
updateUiMode(UIModeState.EMBEDDED_VIDEO)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun switchToFullscreen() {
|
override fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) {
|
||||||
uiVisibilityJob?.cancel()
|
uiVisibilityJob?.cancel()
|
||||||
finishFastSeek()
|
finishFastSeek()
|
||||||
|
|
||||||
|
this.embeddedUiConfig = embeddedUiConfig
|
||||||
updateUiMode(UIModeState.FULLSCREEN_VIDEO)
|
updateUiMode(UIModeState.FULLSCREEN_VIDEO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,8 +412,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
|
||||||
newPlayer?.let { newPlayer ->
|
newPlayer?.let { newPlayer ->
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val playlist = getPlaylistItemsFromItemList(
|
val playlist = getPlaylistItemsFromItemList(
|
||||||
newPlayer.playlist,
|
newPlayer.playlist, newPlayer.repository
|
||||||
newPlayer.repository
|
|
||||||
)
|
)
|
||||||
mutableUiState.update {
|
mutableUiState.update {
|
||||||
it.copy(playList = playlist)
|
it.copy(playList = playlist)
|
||||||
|
|
|
@ -29,7 +29,7 @@ open class VideoPlayerViewModelDummy : VideoPlayerViewModel {
|
||||||
println("dummy impl")
|
println("dummy impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun switchToFullscreen() {
|
override fun switchToFullscreen(embeddedUiConfig: EmbeddedUiConfig) {
|
||||||
println("dummy impl")
|
println("dummy impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,11 @@ open class VideoPlayerViewModelDummy : VideoPlayerViewModel {
|
||||||
println("dummy impl")
|
println("dummy impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReportEmbeddedConfig(embeddedUiConfig: EmbeddedUiConfig?) {
|
override fun openStreamSelection(selectChapter: Boolean) {
|
||||||
|
println("dummy impl")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun closeStreamSelection() {
|
||||||
println("dummy impl")
|
println("dummy impl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,9 @@ fun VideoPlayerControllerUI(
|
||||||
.align(Alignment.TopStart)
|
.align(Alignment.TopStart)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.defaultMinSize(minHeight = 45.dp)
|
.defaultMinSize(minHeight = 45.dp)
|
||||||
.padding(top = 4.dp, start = 16.dp, end = 16.dp)
|
.padding(top = 4.dp, start = 16.dp, end = 16.dp),
|
||||||
|
viewModel = viewModel,
|
||||||
|
uiState = uiState
|
||||||
)
|
)
|
||||||
|
|
||||||
BottomUI(
|
BottomUI(
|
||||||
|
|
|
@ -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.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
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
@ -37,7 +38,6 @@ import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -57,6 +57,7 @@ import net.newpipe.newplayer.model.EmbeddedUiConfig
|
||||||
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
||||||
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
|
import net.newpipe.newplayer.ui.videoplayer.StreamSelectUI
|
||||||
import net.newpipe.newplayer.utils.LockScreenOrientation
|
import net.newpipe.newplayer.utils.LockScreenOrientation
|
||||||
import net.newpipe.newplayer.utils.getDefaultBrightness
|
import net.newpipe.newplayer.utils.getDefaultBrightness
|
||||||
import net.newpipe.newplayer.utils.setScreenBrightness
|
import net.newpipe.newplayer.utils.setScreenBrightness
|
||||||
|
@ -89,37 +90,17 @@ fun VideoPlayerUI(
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
|
||||||
val defaultBrightness = getDefaultBrightness(activity)
|
val defaultBrightness = getDefaultBrightness(activity)
|
||||||
val screenOrientation = activity.requestedOrientation
|
|
||||||
|
|
||||||
// Setup fullscreen
|
// Setup fullscreen
|
||||||
|
|
||||||
var embeddedUiConfig: EmbeddedUiConfig? by rememberSaveable {
|
|
||||||
mutableStateOf(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(uiState.uiMode.fullscreen) {
|
|
||||||
if (uiState.uiMode.fullscreen) {
|
|
||||||
viewModel.onReportEmbeddedConfig(
|
|
||||||
EmbeddedUiConfig(
|
|
||||||
WindowCompat.getInsetsController(
|
|
||||||
window,
|
|
||||||
view
|
|
||||||
).isAppearanceLightStatusBars,
|
|
||||||
defaultBrightness,
|
|
||||||
screenOrientation,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
viewModel.onReportEmbeddedConfig(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(uiState.uiMode.fullscreen) {
|
LaunchedEffect(uiState.uiMode.fullscreen) {
|
||||||
if (uiState.uiMode.fullscreen) {
|
if (uiState.uiMode.fullscreen) {
|
||||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
|
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
println("gurken dings")
|
||||||
uiState.embeddedUiConfig?.let {
|
uiState.embeddedUiConfig?.let {
|
||||||
|
println("gurken bumbs")
|
||||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
|
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
|
||||||
it.systemBarInLightMode
|
it.systemBarInLightMode
|
||||||
}
|
}
|
||||||
|
@ -128,17 +109,16 @@ fun VideoPlayerUI(
|
||||||
|
|
||||||
// setup immersive mode
|
// setup immersive mode
|
||||||
LaunchedEffect(
|
LaunchedEffect(
|
||||||
key1 = uiState.uiMode.controllerUiVisible,
|
key1 = uiState.uiMode.systemInsetsVisible,
|
||||||
key2 = uiState.uiMode.fullscreen
|
|
||||||
) {
|
) {
|
||||||
if (uiState.uiMode.fullscreen && !uiState.uiMode.systemUiVisible) {
|
if (uiState.uiMode.fullscreen && !uiState.uiMode.systemInsetsVisible) {
|
||||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
} else {
|
} else {
|
||||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uiState.uiMode.fullscreen) {
|
if (uiState.uiMode.fitScreenRotation) {
|
||||||
if (uiState.contentRatio < 1) {
|
if (uiState.contentRatio < 1) {
|
||||||
LockScreenOrientation(orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
LockScreenOrientation(orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
||||||
} else {
|
} else {
|
||||||
|
@ -195,9 +175,19 @@ fun VideoPlayerUI(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the checks if VideoPlayerControllerUI should be visible or not are done by
|
||||||
|
// The VideoPlayerControllerUI composable itself. This is because Visibility of
|
||||||
|
// the controller is more complicated than just using a simple if statement.
|
||||||
VideoPlayerControllerUI(
|
VideoPlayerControllerUI(
|
||||||
viewModel, uiState = uiState
|
viewModel, uiState = uiState
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AnimatedVisibility(visible = uiState.uiMode.isStreamSelect) {
|
||||||
|
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = false)
|
||||||
|
}
|
||||||
|
AnimatedVisibility(visible = uiState.uiMode.isChapterSelect) {
|
||||||
|
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
package net.newpipe.newplayer.ui.videoplayer
|
package net.newpipe.newplayer.ui.videoplayer
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.app.LocaleConfig
|
import android.app.LocaleConfig
|
||||||
import android.icu.text.DecimalFormat
|
import android.icu.text.DecimalFormat
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
@ -38,6 +39,7 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
|
@ -51,6 +53,7 @@ import net.newpipe.newplayer.ui.seeker.Seeker
|
||||||
import net.newpipe.newplayer.ui.seeker.SeekerColors
|
import net.newpipe.newplayer.ui.seeker.SeekerColors
|
||||||
import net.newpipe.newplayer.ui.seeker.SeekerDefaults
|
import net.newpipe.newplayer.ui.seeker.SeekerDefaults
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
|
import net.newpipe.newplayer.utils.getEmbeddedUiConfig
|
||||||
import net.newpipe.newplayer.utils.getLocale
|
import net.newpipe.newplayer.utils.getLocale
|
||||||
import net.newpipe.newplayer.utils.getTimeStringFromMs
|
import net.newpipe.newplayer.utils.getTimeStringFromMs
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
@ -79,9 +82,14 @@ fun BottomUI(
|
||||||
|
|
||||||
Text(getTimeStringFromMs(uiState.durationInMs, getLocale() ?: Locale.US))
|
Text(getTimeStringFromMs(uiState.durationInMs, getLocale() ?: Locale.US))
|
||||||
|
|
||||||
|
val embeddedUiConfig = getEmbeddedUiConfig(LocalContext.current as Activity)
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = if (uiState.uiMode.fullscreen) viewModel::switchToEmbeddedView
|
onClick = if (uiState.uiMode.fullscreen) viewModel::switchToEmbeddedView
|
||||||
else viewModel::switchToFullscreen
|
else {
|
||||||
|
{ // <- head of lambda ... yea kotlin is weird
|
||||||
|
viewModel.switchToFullscreen(embeddedUiConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = if (uiState.uiMode.fullscreen) Icons.Filled.FullscreenExit
|
imageVector = if (uiState.uiMode.fullscreen) Icons.Filled.FullscreenExit
|
||||||
|
|
|
@ -80,7 +80,7 @@ fun StreamSelectUI(
|
||||||
topBar = {
|
topBar = {
|
||||||
if (isChapterSelect) {
|
if (isChapterSelect) {
|
||||||
ChapterSelectTopBar(onClose = {
|
ChapterSelectTopBar(onClose = {
|
||||||
TODO("implement me")
|
viewModel.closeStreamSelection()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
StreamSelectTopBar()
|
StreamSelectTopBar()
|
||||||
|
|
|
@ -44,11 +44,18 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import net.newpipe.newplayer.R
|
import net.newpipe.newplayer.R
|
||||||
|
import net.newpipe.newplayer.model.VideoPlayerUIState
|
||||||
|
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
||||||
|
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
import net.newpipe.newplayer.ui.theme.video_player_onSurface
|
import net.newpipe.newplayer.ui.theme.video_player_onSurface
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TopUI(modifier: Modifier) {
|
fun TopUI(
|
||||||
|
modifier: Modifier,
|
||||||
|
viewModel: VideoPlayerViewModel,
|
||||||
|
uiState: VideoPlayerUIState
|
||||||
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
@ -81,7 +88,7 @@ fun TopUI(modifier: Modifier) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { /*TODO*/ },
|
onClick = { viewModel.openStreamSelection(selectChapter = true) },
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.AutoMirrored.Filled.MenuBook,
|
imageVector = Icons.AutoMirrored.Filled.MenuBook,
|
||||||
|
@ -89,7 +96,7 @@ fun TopUI(modifier: Modifier) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { /*TODO*/ },
|
onClick = { viewModel.openStreamSelection(selectChapter = false) },
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.AutoMirrored.Filled.List,
|
imageVector = Icons.AutoMirrored.Filled.List,
|
||||||
|
@ -109,7 +116,7 @@ fun TopUI(modifier: Modifier) {
|
||||||
fun VideoPlayerControllerTopUIPreview() {
|
fun VideoPlayerControllerTopUIPreview() {
|
||||||
VideoPlayerTheme {
|
VideoPlayerTheme {
|
||||||
Surface(color = Color.Black) {
|
Surface(color = Color.Black) {
|
||||||
TopUI(modifier = Modifier)
|
TopUI(modifier = Modifier, VideoPlayerViewModelDummy(), VideoPlayerUIState.DEFAULT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
package net.newpipe.newplayer.ui.videoplayer.gesture_ui
|
package net.newpipe.newplayer.ui.videoplayer.gesture_ui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
@ -35,11 +36,13 @@ import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import net.newpipe.newplayer.model.VideoPlayerUIState
|
import net.newpipe.newplayer.model.VideoPlayerUIState
|
||||||
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
import net.newpipe.newplayer.model.VideoPlayerViewModel
|
||||||
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
|
import net.newpipe.newplayer.utils.getEmbeddedUiConfig
|
||||||
|
|
||||||
private const val TAG = "EmbeddedGestureUI"
|
private const val TAG = "EmbeddedGestureUI"
|
||||||
|
|
||||||
|
@ -52,6 +55,8 @@ fun EmbeddedGestureUI(
|
||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val embeddedUiConfig = getEmbeddedUiConfig(LocalContext.current as Activity)
|
||||||
|
|
||||||
val handleMovement = { movement: TouchedPosition ->
|
val handleMovement = { movement: TouchedPosition ->
|
||||||
Log.d(TAG, "${movement.x}:${movement.y}")
|
Log.d(TAG, "${movement.x}:${movement.y}")
|
||||||
if (0 < movement.y) {
|
if (0 < movement.y) {
|
||||||
|
@ -61,7 +66,7 @@ fun EmbeddedGestureUI(
|
||||||
|
|
||||||
// this check is there to allow a temporary move up in the downward gesture
|
// this check is there to allow a temporary move up in the downward gesture
|
||||||
if (downwardMovementMode == false) {
|
if (downwardMovementMode == false) {
|
||||||
viewModel.switchToFullscreen()
|
viewModel.switchToFullscreen(embeddedUiConfig)
|
||||||
} else {
|
} else {
|
||||||
viewModel.embeddedDraggedDown(movement.y)
|
viewModel.embeddedDraggedDown(movement.y)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,10 @@ import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import net.newpipe.newplayer.model.EmbeddedUiConfig
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -44,14 +47,14 @@ fun LockScreenOrientation(orientation: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
fun getDefaultBrightness(activity: Activity) : Float {
|
fun getDefaultBrightness(activity: Activity): Float {
|
||||||
val window = activity.window
|
val window = activity.window
|
||||||
val layout = window.attributes as WindowManager.LayoutParams
|
val layout = window.attributes as WindowManager.LayoutParams
|
||||||
return if(layout.screenBrightness < 0) 0.5f else layout.screenBrightness
|
return if (layout.screenBrightness < 0) 0.5f else layout.screenBrightness
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
fun setScreenBrightness(value:Float, activity: Activity) {
|
fun setScreenBrightness(value: Float, activity: Activity) {
|
||||||
val window = activity.window
|
val window = activity.window
|
||||||
val layout = window.attributes as WindowManager.LayoutParams
|
val layout = window.attributes as WindowManager.LayoutParams
|
||||||
layout.screenBrightness = value
|
layout.screenBrightness = value
|
||||||
|
@ -72,6 +75,24 @@ fun getLocale(): Locale? {
|
||||||
return ConfigurationCompat.getLocales(configuration).get(0)
|
return ConfigurationCompat.getLocales(configuration).get(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@ReadOnlyComposable
|
||||||
|
fun getEmbeddedUiConfig(activity: Activity): EmbeddedUiConfig {
|
||||||
|
val window = activity.window
|
||||||
|
val view = LocalView.current
|
||||||
|
|
||||||
|
val isLightStatusBar = WindowCompat.getInsetsController(
|
||||||
|
window,
|
||||||
|
view
|
||||||
|
).isAppearanceLightStatusBars
|
||||||
|
val screenOrientation = activity.requestedOrientation
|
||||||
|
val defaultBrightness = getDefaultBrightness(activity)
|
||||||
|
return EmbeddedUiConfig(
|
||||||
|
systemBarInLightMode = isLightStatusBar,
|
||||||
|
brightness = defaultBrightness,
|
||||||
|
screenOrientation = screenOrientation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private const val HOURS_PER_DAY = 24
|
private const val HOURS_PER_DAY = 24
|
||||||
private const val MINUTES_PER_HOUR = 60
|
private const val MINUTES_PER_HOUR = 60
|
||||||
|
|
Loading…
Reference in New Issue