endtangle StreamSelect and ChapterSelect and fix glitches asociated with them
This commit is contained in:
parent
a4f8e490ae
commit
de507b2291
|
@ -330,18 +330,23 @@ class NewPlayerViewModelImpl @Inject constructor(
|
|||
}
|
||||
|
||||
override fun changeUiMode(newUiModeState: UIModeState, embeddedUiConfig: EmbeddedUiConfig) {
|
||||
if (!uiState.value.uiMode.fullscreen) {
|
||||
if (!uiState.value.uiMode.fullscreen && newUiModeState.fullscreen) {
|
||||
this.embeddedUiConfig = embeddedUiConfig
|
||||
}
|
||||
|
||||
if(!(newUiModeState == UIModeState.EMBEDDED_VIDEO_CONTROLLER_UI ||
|
||||
newUiModeState == UIModeState.FULLSCREEN_VIDEO_CONTROLLER_UI)) {
|
||||
uiVisibilityJob?.cancel()
|
||||
} else {
|
||||
resetHideUiDelayedJob()
|
||||
}
|
||||
|
||||
if (newUiModeState.isStreamSelect) {
|
||||
resetPlaylistProgressUpdaterJob()
|
||||
uiVisibilityJob?.cancel()
|
||||
}
|
||||
|
||||
if (newUiModeState.isChapterSelect) {
|
||||
resetPlaylistProgressUpdaterJob()
|
||||
uiVisibilityJob?.cancel()
|
||||
}
|
||||
|
||||
if ((uiState.value.uiMode.isStreamSelect || uiState.value.uiMode.isChapterSelect)
|
||||
|
@ -351,16 +356,6 @@ class NewPlayerViewModelImpl @Inject constructor(
|
|||
progressUpdaterJob?.cancel()
|
||||
}
|
||||
|
||||
if(uiState.value.uiMode.fullscreen && !newUiModeState.fullscreen) {
|
||||
uiVisibilityJob?.cancel()
|
||||
finishFastSeek()
|
||||
}
|
||||
|
||||
if(!uiState.value.uiMode.fullscreen && newUiModeState.fullscreen) {
|
||||
uiVisibilityJob?.cancel()
|
||||
finishFastSeek()
|
||||
}
|
||||
|
||||
updateUiMode(newUiModeState)
|
||||
}
|
||||
|
||||
|
@ -373,10 +368,17 @@ class NewPlayerViewModelImpl @Inject constructor(
|
|||
}
|
||||
|
||||
private fun resetHideUiDelayedJob() {
|
||||
var ex:Exception? = null
|
||||
try {
|
||||
throw Exception()
|
||||
} catch(e: Exception) {
|
||||
ex = e
|
||||
}
|
||||
uiVisibilityJob?.cancel()
|
||||
uiVisibilityJob = viewModelScope.launch {
|
||||
delay(2000)
|
||||
hideUi()
|
||||
ex?.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/* NewPlayer
|
||||
*
|
||||
* @author Christian Schabesberger
|
||||
*
|
||||
* Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de>
|
||||
*
|
||||
* NewPlayer is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NewPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package net.newpipe.newplayer.model
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.Player
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.async
|
||||
import net.newpipe.newplayer.MediaRepository
|
||||
import net.newpipe.newplayer.NewPlayerException
|
||||
import net.newpipe.newplayer.utils.Thumbnail
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
|
@ -55,6 +55,7 @@ import net.newpipe.newplayer.model.NewPlayerViewModel
|
|||
import net.newpipe.newplayer.model.NewPlayerViewModelDummy
|
||||
import net.newpipe.newplayer.model.UIModeState
|
||||
import net.newpipe.newplayer.ui.common.NewPlayerSeeker
|
||||
import net.newpipe.newplayer.ui.streamselect.ChapterSelectUI
|
||||
import net.newpipe.newplayer.ui.streamselect.StreamSelectUI
|
||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||
import net.newpipe.newplayer.utils.Thumbnail
|
||||
|
@ -85,7 +86,7 @@ fun AudioPlayerUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
|||
enter = UI_ENTER_ANIMATION,
|
||||
exit = UI_EXIT_ANIMATION
|
||||
) {
|
||||
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true)
|
||||
ChapterSelectUI(viewModel = viewModel, uiState = uiState)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
|
@ -93,7 +94,7 @@ fun AudioPlayerUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
|||
enter = UI_ENTER_ANIMATION,
|
||||
exit = UI_EXIT_ANIMATION
|
||||
) {
|
||||
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = false)
|
||||
StreamSelectUI(viewModel = viewModel, uiState = uiState)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/* NewPlayer
|
||||
*
|
||||
* @author Christian Schabesberger
|
||||
*
|
||||
* Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de>
|
||||
*
|
||||
* NewPlayer is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NewPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.newpipe.newplayer.ui.streamselect
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
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.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import net.newpipe.newplayer.model.EmbeddedUiConfig
|
||||
import net.newpipe.newplayer.model.NewPlayerUIState
|
||||
import net.newpipe.newplayer.model.NewPlayerViewModel
|
||||
import net.newpipe.newplayer.model.NewPlayerViewModelDummy
|
||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||
import net.newpipe.newplayer.utils.getEmbeddedUiConfig
|
||||
import net.newpipe.newplayer.utils.getInsets
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Composable
|
||||
fun ChapterSelectUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
||||
val insets = getInsets()
|
||||
|
||||
val embeddedUiConfig = if (LocalContext.current is Activity)
|
||||
getEmbeddedUiConfig(activity = LocalContext.current as Activity)
|
||||
else
|
||||
EmbeddedUiConfig.DUMMY
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.windowInsetsPadding(insets),
|
||||
containerColor = Color.Transparent,
|
||||
topBar = {
|
||||
ChapterSelectTopBar(
|
||||
onClose = {
|
||||
viewModel.changeUiMode(
|
||||
uiState.uiMode.getNextModeWhenBackPressed() ?: uiState.uiMode,
|
||||
embeddedUiConfig
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(modifier = Modifier.padding(innerPadding)) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(start = 5.dp, end = 5.dp)
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.spacedBy(5.dp),
|
||||
) {
|
||||
items(uiState.chapters.size) { chapterIndex ->
|
||||
val chapter = uiState.chapters[chapterIndex]
|
||||
ChapterItem(
|
||||
id = chapterIndex,
|
||||
chapterTitle = chapter.chapterTitle ?: "",
|
||||
chapterStartInMs = chapter.chapterStartInMs,
|
||||
thumbnail = chapter.thumbnail,
|
||||
onClicked = {
|
||||
viewModel.chapterSelected(chapterIndex)
|
||||
},
|
||||
isCurrentChapter = isActiveChapter(
|
||||
chapterIndex,
|
||||
uiState.chapters,
|
||||
uiState.playbackPositionInMs
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Preview(device = "id:pixel_5")
|
||||
@Composable
|
||||
fun VideoPlayerChannelSelectUIPreview() {
|
||||
VideoPlayerTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = Color.Red) {
|
||||
ChapterSelectUI(
|
||||
viewModel = NewPlayerViewModelDummy(),
|
||||
uiState = NewPlayerUIState.DUMMY
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -59,65 +59,21 @@ val ITEM_CORNER_SHAPE = RoundedCornerShape(10.dp)
|
|||
@OptIn(UnstableApi::class)
|
||||
@Composable
|
||||
fun StreamSelectUI(
|
||||
isChapterSelect: Boolean = false,
|
||||
viewModel: NewPlayerViewModel,
|
||||
uiState: NewPlayerUIState
|
||||
) {
|
||||
val insets = getInsets()
|
||||
|
||||
val embeddedUiConfig = if (LocalContext.current is Activity)
|
||||
getEmbeddedUiConfig(activity = LocalContext.current as Activity)
|
||||
else
|
||||
EmbeddedUiConfig.DUMMY
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.windowInsetsPadding(insets),
|
||||
containerColor = Color.Transparent,
|
||||
topBar = {
|
||||
if (isChapterSelect) {
|
||||
ChapterSelectTopBar(
|
||||
onClose = {
|
||||
viewModel.changeUiMode(
|
||||
uiState.uiMode.getNextModeWhenBackPressed() ?: uiState.uiMode,
|
||||
embeddedUiConfig
|
||||
)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
StreamSelectTopBar(viewModel = viewModel, uiState = uiState)
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(modifier = Modifier.padding(innerPadding)) {
|
||||
if (isChapterSelect) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(start = 5.dp, end = 5.dp)
|
||||
.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.spacedBy(5.dp),
|
||||
) {
|
||||
items(uiState.chapters.size) { chapterIndex ->
|
||||
val chapter = uiState.chapters[chapterIndex]
|
||||
ChapterItem(
|
||||
id = chapterIndex,
|
||||
chapterTitle = chapter.chapterTitle ?: "",
|
||||
chapterStartInMs = chapter.chapterStartInMs,
|
||||
thumbnail = chapter.thumbnail,
|
||||
onClicked = {
|
||||
viewModel.chapterSelected(chapterIndex)
|
||||
},
|
||||
isCurrentChapter = isActiveChapter(
|
||||
chapterIndex,
|
||||
uiState.chapters,
|
||||
uiState.playbackPositionInMs
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
ReorderableStreamItemsList(
|
||||
padding = PaddingValues(start = 5.dp, end = 5.dp),
|
||||
viewModel = viewModel,
|
||||
|
@ -127,8 +83,6 @@ fun StreamSelectUI(
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Composable
|
||||
fun ReorderableStreamItemsList(
|
||||
|
@ -176,21 +130,6 @@ fun ReorderableStreamItemsList(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Preview(device = "id:pixel_5")
|
||||
@Composable
|
||||
fun VideoPlayerChannelSelectUIPreview() {
|
||||
VideoPlayerTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = Color.Red) {
|
||||
StreamSelectUI(
|
||||
isChapterSelect = true,
|
||||
viewModel = NewPlayerViewModelDummy(),
|
||||
uiState = NewPlayerUIState.DUMMY
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Preview(device = "id:pixel_5")
|
||||
@Composable
|
||||
|
@ -198,7 +137,6 @@ fun VideoPlayerStreamSelectUIPreview() {
|
|||
VideoPlayerTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = Color.Red) {
|
||||
StreamSelectUI(
|
||||
isChapterSelect = false,
|
||||
viewModel = NewPlayerViewModelDummy(),
|
||||
uiState = NewPlayerUIState.DUMMY
|
||||
)
|
||||
|
|
|
@ -47,6 +47,7 @@ import net.newpipe.newplayer.model.NewPlayerViewModel
|
|||
import net.newpipe.newplayer.ui.PlaySurface
|
||||
import net.newpipe.newplayer.ui.streamselect.StreamSelectUI
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import net.newpipe.newplayer.ui.streamselect.ChapterSelectUI
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
@Composable
|
||||
|
@ -116,7 +117,6 @@ fun VideoPlayerUi(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
|||
StreamSelectUI(
|
||||
viewModel = viewModel,
|
||||
uiState = uiState,
|
||||
isChapterSelect = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ fun VideoPlayerUi(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
|||
modifier = Modifier.fillMaxSize(),
|
||||
color = STREAMSELECT_UI_BACKGROUND_COLOR
|
||||
) {
|
||||
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true)
|
||||
ChapterSelectUI(viewModel = viewModel, uiState = uiState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue