Add swipe gesture to PlayerBottomSheet (#79)
This commit is contained in:
@@ -3,11 +3,9 @@ package it.vfsfitvnm.vimusic.ui.views
|
|||||||
import android.app.SearchManager
|
import android.app.SearchManager
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.animation.AnimatedContentScope
|
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.animation.animateColorAsState
|
import androidx.compose.animation.animateColorAsState
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.with
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
@@ -21,23 +19,19 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.scale
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import it.vfsfitvnm.route.Route
|
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
|
||||||
import it.vfsfitvnm.route.empty
|
|
||||||
import it.vfsfitvnm.route.rememberRoute
|
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.models.Song
|
import it.vfsfitvnm.vimusic.models.Song
|
||||||
import it.vfsfitvnm.vimusic.query
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.ui.components.BottomSheet
|
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.screens.rememberLyricsRoute
|
import it.vfsfitvnm.vimusic.ui.components.HorizontalTabPager
|
||||||
|
import it.vfsfitvnm.vimusic.ui.components.rememberTabPagerState
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
|
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
|
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
|
||||||
import it.vfsfitvnm.vimusic.utils.PlayerState
|
import it.vfsfitvnm.vimusic.utils.PlayerState
|
||||||
import it.vfsfitvnm.vimusic.utils.center
|
import it.vfsfitvnm.vimusic.utils.center
|
||||||
import it.vfsfitvnm.vimusic.utils.color
|
import it.vfsfitvnm.vimusic.utils.color
|
||||||
import it.vfsfitvnm.vimusic.utils.medium
|
|
||||||
import it.vfsfitvnm.youtubemusic.YouTube
|
import it.vfsfitvnm.youtubemusic.YouTube
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -58,9 +52,7 @@ fun PlayerBottomSheet(
|
|||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
val lyricsRoute = rememberLyricsRoute()
|
val tabPagerState = rememberTabPagerState(initialPageIndex = 0, pageCount = 2)
|
||||||
|
|
||||||
var route by rememberRoute()
|
|
||||||
|
|
||||||
var nextResult by remember(playerState?.mediaItem?.mediaId) {
|
var nextResult by remember(playerState?.mediaItem?.mediaId) {
|
||||||
mutableStateOf<Result<YouTube.NextResult>?>(null)
|
mutableStateOf<Result<YouTube.NextResult>?>(null)
|
||||||
@@ -100,10 +92,10 @@ fun PlayerBottomSheet(
|
|||||||
@Composable
|
@Composable
|
||||||
fun Element(
|
fun Element(
|
||||||
text: String,
|
text: String,
|
||||||
targetRoute: Route?
|
pageIndex: Int
|
||||||
) {
|
) {
|
||||||
val color by animateColorAsState(
|
val color by animateColorAsState(
|
||||||
if (targetRoute == route) {
|
if (tabPagerState.pageIndex == pageIndex) {
|
||||||
colorPalette.text
|
colorPalette.text
|
||||||
} else {
|
} else {
|
||||||
colorPalette.textDisabled
|
colorPalette.textDisabled
|
||||||
@@ -111,7 +103,7 @@ fun PlayerBottomSheet(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val scale by animateFloatAsState(
|
val scale by animateFloatAsState(
|
||||||
if (targetRoute == route) {
|
if (pageIndex == pageIndex) {
|
||||||
1f
|
1f
|
||||||
} else {
|
} else {
|
||||||
0.9f
|
0.9f
|
||||||
@@ -120,17 +112,22 @@ fun PlayerBottomSheet(
|
|||||||
|
|
||||||
BasicText(
|
BasicText(
|
||||||
text = text,
|
text = text,
|
||||||
style = typography.xs.medium.color(color).center,
|
style = typography.xs.color(color).center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = rememberRipple(bounded = true),
|
indication = rememberRipple(bounded = true),
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
) {
|
onClick = {
|
||||||
route = targetRoute
|
|
||||||
coroutineScope.launch(Dispatchers.Main) {
|
coroutineScope.launch(Dispatchers.Main) {
|
||||||
layoutState.expand()
|
layoutState.expand()
|
||||||
|
if (layoutState.isCollapsed) {
|
||||||
|
tabPagerState.pageIndex = pageIndex
|
||||||
|
} else {
|
||||||
|
tabPagerState.animateScrollTo(pageIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
.padding(vertical = 8.dp)
|
.padding(vertical = 8.dp)
|
||||||
.scale(scale)
|
.scale(scale)
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@@ -139,47 +136,41 @@ fun PlayerBottomSheet(
|
|||||||
|
|
||||||
Element(
|
Element(
|
||||||
text = "UP NEXT",
|
text = "UP NEXT",
|
||||||
targetRoute = null
|
pageIndex = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
Element(
|
Element(
|
||||||
text = "LYRICS",
|
text = "LYRICS",
|
||||||
targetRoute = lyricsRoute
|
pageIndex = 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
var lyricsResult by remember(song) {
|
HorizontalTabPager(
|
||||||
mutableStateOf(song?.lyrics?.let { Result.success(it) })
|
state = tabPagerState,
|
||||||
}
|
|
||||||
|
|
||||||
RouteHandler(
|
|
||||||
route = route,
|
|
||||||
onRouteChanged = {
|
|
||||||
route = it
|
|
||||||
},
|
|
||||||
handleBackPress = false,
|
|
||||||
transitionSpec = {
|
|
||||||
when (targetState.route) {
|
|
||||||
lyricsRoute -> slideIntoContainer(AnimatedContentScope.SlideDirection.Left) with
|
|
||||||
slideOutOfContainer(AnimatedContentScope.SlideDirection.Left)
|
|
||||||
else -> when (initialState.route) {
|
|
||||||
lyricsRoute -> slideIntoContainer(AnimatedContentScope.SlideDirection.Right) with
|
|
||||||
slideOutOfContainer(AnimatedContentScope.SlideDirection.Right)
|
|
||||||
else -> empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(colorPalette.elevatedBackground)
|
.background(colorPalette.elevatedBackground)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
) {
|
) { index ->
|
||||||
lyricsRoute {
|
when (index) {
|
||||||
|
0 -> {
|
||||||
|
CurrentPlaylistView(
|
||||||
|
playerState = playerState,
|
||||||
|
layoutState = layoutState,
|
||||||
|
onGlobalRouteEmitted = onGlobalRouteEmitted,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 64.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
val player = LocalPlayerServiceBinder.current?.player
|
val player = LocalPlayerServiceBinder.current?.player
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
var lyricsResult by remember(song) {
|
||||||
|
mutableStateOf(song?.lyrics?.let { Result.success(it) })
|
||||||
|
}
|
||||||
|
|
||||||
LyricsView(
|
LyricsView(
|
||||||
lyrics = lyricsResult?.getOrNull(),
|
lyrics = lyricsResult?.getOrNull(),
|
||||||
nestedScrollConnectionProvider = layoutState::nestedScrollConnection,
|
nestedScrollConnectionProvider = layoutState::nestedScrollConnection,
|
||||||
@@ -240,15 +231,7 @@ fun PlayerBottomSheet(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
else -> {}
|
||||||
host {
|
|
||||||
CurrentPlaylistView(
|
|
||||||
playerState = playerState,
|
|
||||||
layoutState = layoutState,
|
|
||||||
onGlobalRouteEmitted = onGlobalRouteEmitted,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(top = 64.dp)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user