make item deletion almost possible
This commit is contained in:
parent
430bed20b6
commit
3dc5ca3e10
|
@ -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)
|
||||
|
|
|
@ -57,7 +57,7 @@ enum class UIModeState {
|
|||
|
||||
val isStreamSelect: Boolean
|
||||
get() =
|
||||
when(this) {
|
||||
when (this) {
|
||||
EMBEDDED_VIDEO_STREAM_SELECT -> true
|
||||
FULLSCREEN_VIDEO_STREAM_SELECT -> true
|
||||
else -> false
|
||||
|
@ -65,7 +65,7 @@ enum class UIModeState {
|
|||
|
||||
val isChapterSelect: Boolean
|
||||
get() =
|
||||
when(this) {
|
||||
when (this) {
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> true
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT -> true
|
||||
else -> false
|
||||
|
@ -73,14 +73,14 @@ enum class UIModeState {
|
|||
|
||||
val systemInsetsVisible: Boolean
|
||||
get() =
|
||||
when(this) {
|
||||
when (this) {
|
||||
FULLSCREEN_VIDEO -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
val fitScreenRotation: Boolean
|
||||
get() =
|
||||
when(this) {
|
||||
when (this) {
|
||||
FULLSCREEN_VIDEO -> true
|
||||
FULLSCREEN_VIDEO_CONTROLLER_UI -> true
|
||||
FULLSCREEN_VIDEO_CHAPTER_SELECT -> true
|
||||
|
@ -141,8 +141,8 @@ enum class UIModeState {
|
|||
else -> this
|
||||
}
|
||||
|
||||
fun toPlayMode() = when(this) {
|
||||
PLACEHOLDER -> null
|
||||
fun toPlayMode() = when (this) {
|
||||
PLACEHOLDER -> PlayMode.IDLE
|
||||
EMBEDDED_VIDEO -> PlayMode.EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_CONTROLLER_UI -> PlayMode.EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> PlayMode.EMBEDDED_VIDEO
|
||||
|
@ -153,7 +153,7 @@ enum class UIModeState {
|
|||
FULLSCREEN_VIDEO_STREAM_SELECT -> PlayMode.FULLSCREEN_VIDEO
|
||||
}
|
||||
|
||||
fun getNextModeWhenBackPressed() = when(this) {
|
||||
fun getNextModeWhenBackPressed() = when (this) {
|
||||
EMBEDDED_VIDEO_CHAPTER_SELECT -> EMBEDDED_VIDEO
|
||||
EMBEDDED_VIDEO_STREAM_SELECT -> EMBEDDED_VIDEO
|
||||
FULLSCREEN_VIDEO -> 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
|
||||
|
||||
}
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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,13 +192,18 @@ 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
@ -217,6 +247,7 @@ fun StreamItem(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,7 +264,8 @@ fun StreamItemPreview() {
|
|||
haptic = null,
|
||||
onDragFinished = {},
|
||||
isDragging = false,
|
||||
isCurrentlyPlaying = true
|
||||
isCurrentlyPlaying = true,
|
||||
onDelete = {println("has ben deleted")}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue