Skip to content

Commit

Permalink
Remove swipeable artwork for stability
Browse files Browse the repository at this point in the history
  • Loading branch information
z-huang committed Aug 7, 2023
1 parent cf14a29 commit 7c3bb2b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 135 deletions.
71 changes: 15 additions & 56 deletions app/src/main/java/com/zionhuang/music/ui/player/MiniPlayer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package com.zionhuang.music.ui.player

import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand All @@ -18,19 +16,15 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -47,15 +41,9 @@ import com.zionhuang.music.LocalPlayerConnection
import com.zionhuang.music.R
import com.zionhuang.music.constants.MiniPlayerHeight
import com.zionhuang.music.constants.ThumbnailCornerRadius
import com.zionhuang.music.extensions.metadata
import com.zionhuang.music.extensions.togglePlayPause
import com.zionhuang.music.models.MediaMetadata
import com.zionhuang.music.ui.utils.HorizontalPager
import com.zionhuang.music.ui.utils.SnapLayoutInfoProvider
import kotlinx.coroutines.flow.drop
import kotlin.math.abs

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MiniPlayer(
position: Long,
Expand All @@ -66,40 +54,8 @@ fun MiniPlayer(
val isPlaying by playerConnection.isPlaying.collectAsState()
val playbackState by playerConnection.playbackState.collectAsState()
val error by playerConnection.error.collectAsState()
val windows by playerConnection.queueWindows.collectAsState()
val currentWindowIndex by playerConnection.currentWindowIndex.collectAsState()

val pagerState = rememberPagerState(
initialPage = currentWindowIndex.takeIf { it != -1 } ?: 0
)

val snapLayoutInfoProvider = remember(pagerState) {
SnapLayoutInfoProvider(
pagerState = pagerState,
positionInLayout = { _, _ -> 0f }
)
}

LaunchedEffect(pagerState, currentWindowIndex) {
if (windows.isNotEmpty()) {
try {
if (abs(pagerState.currentPage - currentWindowIndex) <= 1) {
pagerState.animateScrollToPage(currentWindowIndex)
} else {
pagerState.scrollToPage(currentWindowIndex)
}
} catch (_: Exception) {
}
}
}

LaunchedEffect(pagerState) {
snapshotFlow { pagerState.settledPage }.drop(1).collect { index ->
if (!pagerState.isScrollInProgress && index != currentWindowIndex && windows.isNotEmpty()) {
playerConnection.player.seekToDefaultPosition(windows[index].firstPeriodIndex)
}
}
}
val mediaMetadata by playerConnection.mediaMetadata.collectAsState()
val canSkipNext by playerConnection.canSkipNext.collectAsState()

Box(
modifier = modifier
Expand All @@ -118,17 +74,10 @@ fun MiniPlayer(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxSize()
.padding(end = 12.dp),
.padding(end = 6.dp),
) {
HorizontalPager(
state = pagerState,
flingBehavior = rememberSnapFlingBehavior(snapLayoutInfoProvider),
items = windows,
key = { it.uid.hashCode() },
beyondBoundsPageCount = 2,
modifier = Modifier.weight(1f)
) { window ->
window.mediaItem.metadata?.let {
Box(Modifier.weight(1f)) {
mediaMetadata?.let {
MiniMediaInfo(
mediaMetadata = it,
error = error,
Expand All @@ -152,6 +101,16 @@ fun MiniPlayer(
contentDescription = null
)
}

IconButton(
enabled = canSkipNext,
onClick = playerConnection.player::seekToNext
) {
Icon(
painter = painterResource(R.drawable.skip_next),
contentDescription = null
)
}
}
}
}
Expand Down
112 changes: 33 additions & 79 deletions app/src/main/java/com/zionhuang/music/ui/player/Thumbnail.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ package com.zionhuang.music.ui.player
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -20,15 +24,9 @@ import coil.compose.AsyncImage
import com.zionhuang.music.LocalPlayerConnection
import com.zionhuang.music.constants.ShowLyricsKey
import com.zionhuang.music.constants.ThumbnailCornerRadius
import com.zionhuang.music.extensions.metadata
import com.zionhuang.music.ui.component.Lyrics
import com.zionhuang.music.ui.utils.HorizontalPager
import com.zionhuang.music.ui.utils.SnapLayoutInfoProvider
import com.zionhuang.music.utils.rememberPreference
import kotlinx.coroutines.flow.drop
import kotlin.math.abs

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Thumbnail(
sliderPositionProvider: () -> Long?,
Expand All @@ -37,50 +35,11 @@ fun Thumbnail(
val playerConnection = LocalPlayerConnection.current ?: return
val currentView = LocalView.current

val windows by playerConnection.queueWindows.collectAsState()
val currentWindowIndex by playerConnection.currentWindowIndex.collectAsState()
val mediaMetadata by playerConnection.mediaMetadata.collectAsState()
val error by playerConnection.error.collectAsState()

val showLyrics by rememberPreference(ShowLyricsKey, false)

val pagerState = rememberPagerState(
initialPage = currentWindowIndex.takeIf { it != -1 } ?: 0
)

val snapLayoutInfoProvider = remember(pagerState) {
SnapLayoutInfoProvider(
pagerState = pagerState,
positionInLayout = { _, _ -> 0f }
)
}

LaunchedEffect(pagerState, currentWindowIndex) {
if (windows.isNotEmpty()) {
try {
if (abs(pagerState.currentPage - currentWindowIndex) <= 1) {
pagerState.animateScrollToPage(currentWindowIndex)
} else {
pagerState.scrollToPage(currentWindowIndex)
}
} catch (_: Exception) {
}
}
}

LaunchedEffect(pagerState) {
snapshotFlow { pagerState.settledPage }.drop(1).collect { index ->
if (!pagerState.isScrollInProgress && index != currentWindowIndex && windows.isNotEmpty()) {
playerConnection.player.seekToDefaultPosition(windows[index].firstPeriodIndex)
}
}
}

LaunchedEffect(showLyrics) {
if (!showLyrics) {
pagerState.scrollToPage(currentWindowIndex)
}
}

DisposableEffect(showLyrics) {
currentView.keepScreenOn = showLyrics
onDispose {
Expand All @@ -97,35 +56,30 @@ fun Thumbnail(
.fillMaxSize()
.statusBarsPadding()
) {
HorizontalPager(
state = pagerState,
flingBehavior = rememberSnapFlingBehavior(snapLayoutInfoProvider),
items = windows,
key = { it.uid.hashCode() },
beyondBoundsPageCount = 2
) { window ->
Box(Modifier.fillMaxSize()) {
AsyncImage(
model = window.mediaItem.metadata?.thumbnailUrl,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.clip(RoundedCornerShape(ThumbnailCornerRadius))
.align(Alignment.Center)
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { offset ->
if (offset.x < size.width / 2) {
playerConnection.player.seekBack()
} else {
playerConnection.player.seekForward()
}
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
AsyncImage(
model = mediaMetadata?.thumbnailUrl,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(ThumbnailCornerRadius))
.pointerInput(Unit) {
detectTapGestures(
onDoubleTap = { offset ->
if (offset.x < size.width / 2) {
playerConnection.player.seekBack()
} else {
playerConnection.player.seekForward()
}
)
}
)
}
}
)
}
)
}
}

Expand Down

0 comments on commit 7c3bb2b

Please sign in to comment.