This commit is contained in:
vfsfitvnm
2022-07-25 12:32:19 +02:00
parent 9ed2c84822
commit 457e6712d4
4 changed files with 58 additions and 20 deletions

View File

@@ -40,6 +40,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.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.unit.dp
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.Player import androidx.media3.common.Player
import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.google.accompanist.systemuicontroller.rememberSystemUiController
@@ -215,7 +216,8 @@ class MainActivity : ComponentActivity() {
when (val uri = uri) { when (val uri = uri) {
null -> { null -> {
val playerBottomSheetState = rememberBottomSheetState( val playerBottomSheetState = rememberBottomSheetState(
lowerBound = Dimensions.collapsedPlayer, lowerBound = 0.dp,
collapsedBound = Dimensions.collapsedPlayer,
upperBound = maxHeight, upperBound = maxHeight,
isExpanded = expandPlayerBottomSheet isExpanded = expandPlayerBottomSheet
) )
@@ -263,7 +265,7 @@ fun ExpandPlayerOnPlaylistChange(player: Player, expand: () -> Unit) {
DisposableEffect(player, expand) { DisposableEffect(player, expand) {
player.listener(object : Player.Listener { player.listener(object : Player.Listener {
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) { if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED && mediaItem != null) {
expand() expand()
} }
} }

View File

@@ -213,7 +213,7 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
} }
override fun onTaskRemoved(rootIntent: Intent?) { override fun onTaskRemoved(rootIntent: Intent?) {
if (!player.playWhenReady) { if (!player.shouldBePlaying) {
if (isPersistentQueueEnabled) { if (isPersistentQueueEnabled) {
broadCastPendingIntent<NotificationDismissReceiver>().send() broadCastPendingIntent<NotificationDismissReceiver>().send()
} else { } else {
@@ -398,7 +398,9 @@ class PlayerService : InvincibleService(), Player.Listener, PlaybackStatsListene
val notification = notification() val notification = notification()
if (notification == null) { if (notification == null) {
stopSelf() isNotificationStarted = false
makeInvincible(false)
stopForeground(true)
return return
} }

View File

@@ -52,6 +52,7 @@ fun BottomSheet(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
peekHeight: Dp = 0.dp, peekHeight: Dp = 0.dp,
elevation: Dp = 8.dp, elevation: Dp = 8.dp,
onSwiped: (() -> Unit)? = null,
collapsedContent: @Composable BoxScope.() -> Unit, collapsedContent: @Composable BoxScope.() -> Unit,
content: @Composable BoxScope.() -> Unit content: @Composable BoxScope.() -> Unit
) { ) {
@@ -85,18 +86,36 @@ fun BottomSheet(
velocityTracker.resetTracking() velocityTracker.resetTracking()
if (velocity.absoluteValue > 300 && initialValue != state.value) { if (velocity.absoluteValue > 300 && initialValue != state.value) {
if (initialValue > state.value) { when (initialValue) {
state.collapse() state.upperBound -> state.collapse()
} else { state.collapsedBound -> if (initialValue > state.value && onSwiped != null) {
state.expand() state.swipe()
onSwiped.invoke()
} else {
state.expand()
}
} }
} else { } else {
if (state.upperBound - state.value > state.value - state.lowerBound) { val l0 = state.lowerBound
state.collapse() val l1 = (state.collapsedBound - state.lowerBound) / 2
} else { val l2 = (state.upperBound - state.collapsedBound) / 2
state.expand() val l3 = state.upperBound
when (state.value) {
in l0..l1 -> {
if (onSwiped != null) {
state.swipe()
onSwiped.invoke()
} else {
state.collapse()
}
}
in l1..l2 -> state.collapse()
in l2..l3 -> state.expand()
else -> {}
} }
} }
} }
) )
} }
@@ -107,7 +126,7 @@ fun BottomSheet(
content() content()
} }
if (!state.isExpanded) { if (!state.isExpanded && (onSwiped == null || !state.isDismissed)) {
Box( Box(
modifier = Modifier modifier = Modifier
.graphicsLayer { .graphicsLayer {
@@ -119,7 +138,7 @@ fun BottomSheet(
onClick = state::expandSoft onClick = state::expandSoft
) )
.fillMaxWidth() .fillMaxWidth()
.height(state.lowerBound), .height(state.collapsedBound),
content = collapsedContent content = collapsedContent
) )
} }
@@ -132,6 +151,7 @@ class BottomSheetState(
private val coroutineScope: CoroutineScope, private val coroutineScope: CoroutineScope,
private val animatable: Animatable<Dp, AnimationVector1D>, private val animatable: Animatable<Dp, AnimationVector1D>,
private val onWasExpandedChanged: (Boolean) -> Unit, private val onWasExpandedChanged: (Boolean) -> Unit,
val collapsedBound: Dp,
) : DraggableState by draggableState { ) : DraggableState by draggableState {
val lowerBound: Dp val lowerBound: Dp
get() = animatable.lowerBound!! get() = animatable.lowerBound!!
@@ -141,8 +161,12 @@ class BottomSheetState(
val value by animatable.asState() val value by animatable.asState()
val isDismissed by derivedStateOf {
value == animatable.lowerBound!!
}
val isCollapsed by derivedStateOf { val isCollapsed by derivedStateOf {
value == animatable.lowerBound value == collapsedBound
} }
val isExpanded by derivedStateOf { val isExpanded by derivedStateOf {
@@ -150,13 +174,13 @@ class BottomSheetState(
} }
val progress by derivedStateOf { val progress by derivedStateOf {
1f - (animatable.upperBound!! - animatable.value) / (animatable.upperBound!! - animatable.lowerBound!!) 1f - (animatable.upperBound!! - animatable.value) / (animatable.upperBound!! - collapsedBound)
} }
private fun collapse(animationSpec: AnimationSpec<Dp>) { private fun collapse(animationSpec: AnimationSpec<Dp>) {
onWasExpandedChanged(false) onWasExpandedChanged(false)
coroutineScope.launch { coroutineScope.launch {
animatable.animateTo(animatable.lowerBound!!, animationSpec) animatable.animateTo(collapsedBound, animationSpec)
} }
} }
@@ -183,6 +207,13 @@ class BottomSheetState(
expand(tween(300)) expand(tween(300))
} }
fun swipe() {
onWasExpandedChanged(false)
coroutineScope.launch {
animatable.animateTo(animatable.lowerBound!!)
}
}
fun snapTo(value: Dp) { fun snapTo(value: Dp) {
coroutineScope.launch { coroutineScope.launch {
animatable.snapTo(value) animatable.snapTo(value)
@@ -224,7 +255,7 @@ class BottomSheetState(
if (available.y.absoluteValue > 1000) { if (available.y.absoluteValue > 1000) {
collapse() collapse()
} else { } else {
if (animatable.upperBound!! - value > value - animatable.lowerBound!!) { if (animatable.upperBound!! - value > value - collapsedBound) {
collapse() collapse()
} else { } else {
expand() expand()
@@ -250,6 +281,7 @@ class BottomSheetState(
fun rememberBottomSheetState( fun rememberBottomSheetState(
lowerBound: Dp, lowerBound: Dp,
upperBound: Dp, upperBound: Dp,
collapsedBound: Dp = lowerBound,
isExpanded: Boolean = false isExpanded: Boolean = false
): BottomSheetState { ): BottomSheetState {
val density = LocalDensity.current val density = LocalDensity.current
@@ -259,7 +291,7 @@ fun rememberBottomSheetState(
mutableStateOf(isExpanded) mutableStateOf(isExpanded)
} }
return remember(lowerBound, upperBound, coroutineScope) { return remember(lowerBound, upperBound, collapsedBound, coroutineScope) {
val animatable = val animatable =
Animatable(if (wasExpanded) upperBound else lowerBound, Dp.VectorConverter).also { Animatable(if (wasExpanded) upperBound else lowerBound, Dp.VectorConverter).also {
it.updateBounds(lowerBound.coerceAtMost(upperBound), upperBound) it.updateBounds(lowerBound.coerceAtMost(upperBound), upperBound)
@@ -275,7 +307,8 @@ fun rememberBottomSheetState(
wasExpanded = it wasExpanded = it
}, },
coroutineScope = coroutineScope, coroutineScope = coroutineScope,
animatable = animatable animatable = animatable,
collapsedBound = collapsedBound
) )
} }
} }

View File

@@ -147,6 +147,7 @@ fun PlayerView(
BottomSheet( BottomSheet(
state = layoutState, state = layoutState,
modifier = modifier, modifier = modifier,
onSwiped = binder.player::clearMediaItems,
collapsedContent = { collapsedContent = {
Row( Row(
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp),