Tweak shuffle queue button UI

This commit is contained in:
vfsfitvnm
2022-10-08 13:00:28 +02:00
parent d363f35801
commit 7b6676e7c4
2 changed files with 132 additions and 124 deletions

View File

@@ -11,6 +11,7 @@ import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.only
@@ -38,6 +39,7 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
visible: Boolean = true, visible: Boolean = true,
iconId: Int? = null, iconId: Int? = null,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
windowInsets: WindowInsets = LocalPlayerAwareWindowInsets.current
) { ) {
val transitionState = remember { val transitionState = remember {
MutableTransitionState<ScrollingInfo?>(ScrollingInfo()) MutableTransitionState<ScrollingInfo?>(ScrollingInfo())
@@ -48,6 +50,7 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
onScrollToTop = lazyGridState::smoothScrollToTop, onScrollToTop = lazyGridState::smoothScrollToTop,
iconId = iconId, iconId = iconId,
onClick = onClick, onClick = onClick,
windowInsets = windowInsets,
modifier = modifier modifier = modifier
) )
} }
@@ -60,6 +63,7 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
visible: Boolean = true, visible: Boolean = true,
iconId: Int? = null, iconId: Int? = null,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
windowInsets: WindowInsets = LocalPlayerAwareWindowInsets.current
) { ) {
val transitionState = remember { val transitionState = remember {
MutableTransitionState<ScrollingInfo?>(ScrollingInfo()) MutableTransitionState<ScrollingInfo?>(ScrollingInfo())
@@ -70,6 +74,7 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
onScrollToTop = lazyListState::smoothScrollToTop, onScrollToTop = lazyListState::smoothScrollToTop,
iconId = iconId, iconId = iconId,
onClick = onClick, onClick = onClick,
windowInsets = windowInsets,
modifier = modifier modifier = modifier
) )
} }
@@ -82,6 +87,7 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
visible: Boolean = true, visible: Boolean = true,
iconId: Int? = null, iconId: Int? = null,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
windowInsets: WindowInsets = LocalPlayerAwareWindowInsets.current
) { ) {
val transitionState = remember { val transitionState = remember {
MutableTransitionState<ScrollingInfo?>(ScrollingInfo()) MutableTransitionState<ScrollingInfo?>(ScrollingInfo())
@@ -91,6 +97,7 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
transitionState = transitionState, transitionState = transitionState,
iconId = iconId, iconId = iconId,
onClick = onClick, onClick = onClick,
windowInsets = windowInsets,
modifier = modifier modifier = modifier
) )
} }
@@ -99,13 +106,13 @@ fun BoxScope.FloatingActionsContainerWithScrollToTop(
@Composable @Composable
fun BoxScope.FloatingActions( fun BoxScope.FloatingActions(
transitionState: MutableTransitionState<ScrollingInfo?>, transitionState: MutableTransitionState<ScrollingInfo?>,
windowInsets: WindowInsets,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
onScrollToTop: (suspend () -> Unit)? = null, onScrollToTop: (suspend () -> Unit)? = null,
iconId: Int? = null, iconId: Int? = null,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null
) { ) {
val transition = updateTransition(transitionState, "") val transition = updateTransition(transitionState, "")
val windowInsets = LocalPlayerAwareWindowInsets.current
val bottomPaddingValues = windowInsets.only(WindowInsetsSides.Bottom).asPaddingValues() val bottomPaddingValues = windowInsets.only(WindowInsetsSides.Bottom).asPaddingValues()

View File

@@ -50,6 +50,7 @@ import it.vfsfitvnm.vimusic.ui.components.BottomSheet
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.MusicBars import it.vfsfitvnm.vimusic.ui.components.MusicBars
import it.vfsfitvnm.vimusic.ui.components.themed.FloatingActionsContainerWithScrollToTop
import it.vfsfitvnm.vimusic.ui.components.themed.IconButton import it.vfsfitvnm.vimusic.ui.components.themed.IconButton
import it.vfsfitvnm.vimusic.ui.components.themed.QueuedMediaItemMenu import it.vfsfitvnm.vimusic.ui.components.themed.QueuedMediaItemMenu
import it.vfsfitvnm.vimusic.ui.items.SongItem import it.vfsfitvnm.vimusic.ui.items.SongItem
@@ -125,134 +126,150 @@ fun Queue(
extraItemCount = 0 extraItemCount = 0
) )
val rippleIndication = rememberRipple(bounded = false) val rippleIndication = rememberRipple(bounded = false)
Column { Column {
ReorderingLazyColumn( Box(
reorderingState = reorderingState,
contentPadding = windowInsets
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top).asPaddingValues(),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier modifier = Modifier
.background(colorPalette.background0)
.fillMaxSize()
.nestedScroll(remember {
layoutState.nestedScrollConnection(reorderingState.lazyListState.firstVisibleItemIndex == 0 && reorderingState.lazyListState.firstVisibleItemScrollOffset == 0)
})
.background(colorPalette.background1) .background(colorPalette.background1)
.weight(1f) .weight(1f)
) { ) {
items( ReorderingLazyColumn(
items = windows, reorderingState = reorderingState,
key = { it.uid.hashCode() } contentPadding = windowInsets
) { window -> .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top).asPaddingValues(),
val isPlayingThisMediaItem = mediaItemIndex == window.firstPeriodIndex horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.nestedScroll(remember {
layoutState.nestedScrollConnection(reorderingState.lazyListState.firstVisibleItemIndex == 0 && reorderingState.lazyListState.firstVisibleItemScrollOffset == 0)
})
SongItem( ) {
song = window.mediaItem, items(
thumbnailSizePx = thumbnailSizePx, items = windows,
thumbnailSizeDp = thumbnailSizeDp, key = { it.uid.hashCode() }
onThumbnailContent = { ) { window ->
androidx.compose.animation.AnimatedVisibility( val isPlayingThisMediaItem = mediaItemIndex == window.firstPeriodIndex
visible = isPlayingThisMediaItem,
enter = fadeIn(), SongItem(
exit = fadeOut(), song = window.mediaItem,
) { thumbnailSizePx = thumbnailSizePx,
Box( thumbnailSizeDp = thumbnailSizeDp,
contentAlignment = Alignment.Center, onThumbnailContent = {
modifier = Modifier androidx.compose.animation.AnimatedVisibility(
.background( visible = isPlayingThisMediaItem,
color = Color.Black.copy(alpha = 0.25f), enter = fadeIn(),
shape = thumbnailShape exit = fadeOut(),
)
.size(Dimensions.thumbnails.song)
) { ) {
if (shouldBePlaying) { Box(
MusicBars( contentAlignment = Alignment.Center,
color = colorPalette.onOverlay, modifier = Modifier
modifier = Modifier .background(
.height(24.dp) color = Color.Black.copy(alpha = 0.25f),
) shape = thumbnailShape
} else { )
Image( .size(Dimensions.thumbnails.song)
painter = painterResource(R.drawable.play), ) {
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.onOverlay),
modifier = Modifier
.size(24.dp)
)
}
}
}
},
trailingContent = {
IconButton(
icon = R.drawable.reorder,
color = colorPalette.textDisabled,
indication = rippleIndication,
onClick = {},
modifier = Modifier
.reorder(
reorderingState = reorderingState,
index = window.firstPeriodIndex
)
.size(18.dp)
)
},
modifier = Modifier
.combinedClickable(
onLongClick = {
menuState.display {
QueuedMediaItemMenu(
mediaItem = window.mediaItem,
indexInQueue = if (isPlayingThisMediaItem) null else window.firstPeriodIndex,
onDismiss = menuState::hide
)
}
},
onClick = {
if (isPlayingThisMediaItem) {
if (shouldBePlaying) { if (shouldBePlaying) {
binder.player.pause() MusicBars(
color = colorPalette.onOverlay,
modifier = Modifier
.height(24.dp)
)
} else { } else {
binder.player.play() Image(
painter = painterResource(R.drawable.play),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.onOverlay),
modifier = Modifier
.size(24.dp)
)
} }
} else {
binder.player.playWhenReady = true
binder.player.seekToDefaultPosition(window.firstPeriodIndex)
} }
} }
) },
.animateItemPlacement(reorderingState = reorderingState) trailingContent = {
.draggedItem( IconButton(
reorderingState = reorderingState, icon = R.drawable.reorder,
index = window.firstPeriodIndex color = colorPalette.textDisabled,
) indication = rippleIndication,
) onClick = {},
}
item {
if (binder.isLoadingRadio) {
Column(
modifier = Modifier
.shimmer()
) {
repeat(3) { index ->
SongItemPlaceholder(
thumbnailSizeDp = Dimensions.thumbnails.song,
modifier = Modifier modifier = Modifier
.alpha(1f - index * 0.125f) .reorder(
.fillMaxWidth() reorderingState = reorderingState,
.padding(vertical = 4.dp, horizontal = 16.dp) index = window.firstPeriodIndex
)
.size(18.dp)
) )
},
modifier = Modifier
.combinedClickable(
onLongClick = {
menuState.display {
QueuedMediaItemMenu(
mediaItem = window.mediaItem,
indexInQueue = if (isPlayingThisMediaItem) null else window.firstPeriodIndex,
onDismiss = menuState::hide
)
}
},
onClick = {
if (isPlayingThisMediaItem) {
if (shouldBePlaying) {
binder.player.pause()
} else {
binder.player.play()
}
} else {
binder.player.playWhenReady = true
binder.player.seekToDefaultPosition(window.firstPeriodIndex)
}
}
)
.animateItemPlacement(reorderingState = reorderingState)
.draggedItem(
reorderingState = reorderingState,
index = window.firstPeriodIndex
)
)
}
item {
if (binder.isLoadingRadio) {
Column(
modifier = Modifier
.shimmer()
) {
repeat(3) { index ->
SongItemPlaceholder(
thumbnailSizeDp = Dimensions.thumbnails.song,
modifier = Modifier
.alpha(1f - index * 0.125f)
.fillMaxWidth()
.padding(vertical = 4.dp, horizontal = 16.dp)
)
}
} }
} }
} }
} }
FloatingActionsContainerWithScrollToTop(
lazyListState = reorderingState.lazyListState,
iconId = R.drawable.shuffle,
visible = !reorderingState.isDragging,
windowInsets = windowInsets.only(WindowInsetsSides.Horizontal),
onClick = {
reorderingState.coroutineScope.launch {
reorderingState.lazyListState.smoothScrollToTop()
}.invokeOnCompletion {
binder.player.shuffleQueue()
}
}
)
} }
Box( Box(
modifier = Modifier modifier = Modifier
.clickable(onClick = layoutState::collapseSoft) .clickable(onClick = layoutState::collapseSoft)
@@ -282,22 +299,6 @@ fun Queue(
.align(Alignment.Center) .align(Alignment.Center)
.size(18.dp) .size(18.dp)
) )
IconButton(
icon = R.drawable.shuffle,
color = colorPalette.text,
onClick = {
reorderingState.coroutineScope.launch {
reorderingState.lazyListState.smoothScrollToTop()
}.invokeOnCompletion {
binder.player.shuffleQueue()
}
},
modifier = Modifier
.padding(horizontal = 4.dp, vertical = 8.dp)
.size(20.dp)
.align(Alignment.CenterEnd)
)
} }
} }
} }