make item deletion almost possible

This commit is contained in:
Christian Schabesberger 2024-09-06 20:10:25 +02:00
parent 430bed20b6
commit 3dc5ca3e10
6 changed files with 216 additions and 161 deletions

View File

@ -40,6 +40,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import net.newpipe.newplayer.model.UIModeState
import net.newpipe.newplayer.playerInternals.PlaylistItem
import net.newpipe.newplayer.playerInternals.fetchPlaylistItem
import net.newpipe.newplayer.playerInternals.getPlaylistItemsFromExoplayer
@ -47,6 +48,7 @@ import kotlin.Exception
import kotlin.random.Random
enum class PlayMode {
IDLE,
EMBEDDED_VIDEO,
FULLSCREEN_VIDEO,
PIP,
@ -73,7 +75,7 @@ interface NewPlayer {
val sharingLinkWithOffsetPossible: Boolean
var currentPosition: Long
var fastSeekAmountSec: Int
val playBackMode: MutableStateFlow<PlayMode?>
val playBackMode: MutableStateFlow<PlayMode>
var shuffle: Boolean
var repeatMode: RepeatMode
@ -162,7 +164,7 @@ class NewPlayerImpl(
private var playerScope = CoroutineScope(Dispatchers.Main + Job())
override var playBackMode = MutableStateFlow<PlayMode?>(null)
override var playBackMode = MutableStateFlow(PlayMode.IDLE)
override var shuffle: Boolean
get() = internalPlayer.shuffleModeEnabled
@ -281,6 +283,11 @@ class NewPlayerImpl(
}
private fun updatePlaylistItems() {
if (internalPlayer.mediaItemCount == 0) {
playBackMode.update {
PlayMode.IDLE
}
}
playerScope.launch {
val playlist =
getPlaylistItemsFromExoplayer(internalPlayer, repository, uniqueIdToIdLookup)

View File

@ -142,7 +142,7 @@ enum class UIModeState {
}
fun toPlayMode() = when (this) {
PLACEHOLDER -> null
PLACEHOLDER -> PlayMode.IDLE
EMBEDDED_VIDEO -> PlayMode.EMBEDDED_VIDEO
EMBEDDED_VIDEO_CONTROLLER_UI -> PlayMode.EMBEDDED_VIDEO
EMBEDDED_VIDEO_CHAPTER_SELECT -> PlayMode.EMBEDDED_VIDEO
@ -164,16 +164,14 @@ enum class UIModeState {
}
companion object {
fun fromPlayMode(playMode: PlayMode?) =
if (playMode != null)
fun fromPlayMode(playMode: PlayMode) =
when (playMode) {
PlayMode.IDLE -> PLACEHOLDER
PlayMode.EMBEDDED_VIDEO -> EMBEDDED_VIDEO
PlayMode.FULLSCREEN_VIDEO -> FULLSCREEN_VIDEO
PlayMode.PIP -> TODO()
PlayMode.BACKGROUND -> TODO()
PlayMode.AUDIO_FOREGROUND -> TODO()
}
else PLACEHOLDER
}
}

View File

@ -145,6 +145,11 @@ class VideoPlayerViewModelImpl @Inject constructor(
mutableUiState.update {
it.copy(playing = isPlaying, isLoading = false)
}
if(isPlaying && uiState.value.uiMode.controllerUiVisible) {
resetHideUiDelayedJob()
} else {
uiVisibilityJob?.cancel()
}
}
override fun onVideoSizeChanged(videoSize: androidx.media3.common.VideoSize) {
@ -181,6 +186,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
viewModelScope.launch {
newPlayer.playBackMode.collect { newMode ->
val currentMode = mutableUiState.value.uiMode.toPlayMode()
println("gurken mode: $currentMode newMode: $newMode")
if (currentMode != newMode) {
mutableUiState.update {
it.copy(

View File

@ -55,6 +55,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.media3.common.Player
import net.newpipe.newplayer.model.EmbeddedUiConfig
import net.newpipe.newplayer.model.UIModeState
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelDummy
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
@ -116,10 +117,10 @@ fun VideoPlayerUI(
LaunchedEffect(
key1 = uiState.uiMode.systemInsetsVisible,
) {
if (uiState.uiMode.fullscreen && !uiState.uiMode.systemInsetsVisible) {
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
} else {
if (uiState.uiMode.systemInsetsVisible) {
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
} else {
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
}
}
@ -161,6 +162,9 @@ fun VideoPlayerUI(
}
// Set UI
if (uiState.uiMode == UIModeState.PLACEHOLDER) {
VideoPlayerLoadingPlaceholder(uiState.embeddedUiRatio)
} else {
Surface(
modifier = Modifier.then(
if (uiState.uiMode.fullscreen) Modifier.fillMaxSize()
@ -188,7 +192,11 @@ fun VideoPlayerUI(
)
AnimatedVisibility(visible = uiState.uiMode.isStreamSelect) {
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = false)
StreamSelectUI(
viewModel = viewModel,
uiState = uiState,
isChapterSelect = false
)
}
AnimatedVisibility(visible = uiState.uiMode.isChapterSelect) {
StreamSelectUI(viewModel = viewModel, uiState = uiState, isChapterSelect = true)
@ -196,6 +204,7 @@ fun VideoPlayerUI(
}
}
}
}
@Composable
fun PlaySurface(

View File

@ -157,7 +157,10 @@ fun ReorderableStreamItemsList(
haptic = haptic,
onDragFinished = viewModel::onStreamItemDragFinished,
isDragging = isDragging,
isCurrentlyPlaying = playlistItem.uniqueId == uiState.currentlyPlaying.uniqueId
isCurrentlyPlaying = playlistItem.uniqueId == uiState.currentlyPlaying.uniqueId,
onDelete = {
viewModel.removePlaylistItem(index)
}
)
}
}

View File

@ -21,6 +21,7 @@
package net.newpipe.newplayer.ui.videoplayer.streamselect
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
@ -42,12 +43,17 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DragHandle
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.SwipeToDismissBox
import androidx.compose.material3.SwipeToDismissBoxValue
import androidx.compose.material3.Text
import androidx.compose.material3.rememberSwipeToDismissBoxState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -78,12 +84,14 @@ import net.newpipe.newplayer.utils.getLocale
import net.newpipe.newplayer.utils.getTimeStringFromMs
import sh.calvin.reorderable.ReorderableCollectionItemScope
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StreamItem(
modifier: Modifier = Modifier,
playlistItem: PlaylistItem,
onClicked: (Long) -> Unit,
onDragFinished: () -> Unit,
onDelete: () -> Unit,
reorderableScope: ReorderableCollectionItemScope?,
haptic: ReorderHapticFeedback?,
isDragging: Boolean,
@ -92,14 +100,36 @@ fun StreamItem(
val locale = getLocale()!!
val interactionSource = remember { MutableInteractionSource() }
Box(modifier = modifier
.height(60.dp)
val dismissState = rememberSwipeToDismissBoxState(confirmValueChange = {
when (it) {
SwipeToDismissBoxValue.StartToEnd -> {
onDelete()
true
}
SwipeToDismissBoxValue.EndToStart -> {
onDelete()
true
}
SwipeToDismissBoxValue.Settled -> true
}
})
SwipeToDismissBox(
modifier = modifier.height(60.dp), state = dismissState,
backgroundContent = {
},
) {
Box(modifier = Modifier
.fillMaxSize()
.clip(ITEM_CORNER_SHAPE)
.clickable {
onClicked(playlistItem.uniqueId)
}) {
AnimatedVisibility(
androidx.compose.animation.AnimatedVisibility(
visible = isDragging,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(400))
@ -112,7 +142,7 @@ fun StreamItem(
) {}
}
AnimatedVisibility(
androidx.compose.animation.AnimatedVisibility(
visible = isCurrentlyPlaying,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(400))
@ -218,6 +248,7 @@ fun StreamItem(
}
}
}
}
@Preview(device = "spec:width=1080px,height=400px,dpi=440,orientation=landscape")
@ -233,7 +264,8 @@ fun StreamItemPreview() {
haptic = null,
onDragFinished = {},
isDragging = false,
isCurrentlyPlaying = true
isCurrentlyPlaying = true,
onDelete = {println("has ben deleted")}
)
}
}