Add the ability to import a YouTube playlist link as local playlist

This commit is contained in:
vfsfitvnm 2022-06-06 20:35:08 +02:00
parent c3b2435623
commit 0230624809

View file

@ -17,19 +17,30 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.media3.common.Player
import com.valentinilk.shimmer.ShimmerBounds
import com.valentinilk.shimmer.rememberShimmer
import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.internal
import it.vfsfitvnm.vimusic.models.Playlist
import it.vfsfitvnm.vimusic.models.SongInPlaylist
import it.vfsfitvnm.vimusic.ui.components.Error
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.Message
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.components.themed.Menu
import it.vfsfitvnm.vimusic.ui.components.themed.MenuCloseButton
import it.vfsfitvnm.vimusic.ui.components.themed.MenuEntry
import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.utils.*
import it.vfsfitvnm.youtubemusic.Outcome
import it.vfsfitvnm.youtubemusic.YouTube
import it.vfsfitvnm.youtubemusic.toNullable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ExperimentalAnimationApi
@ -54,10 +65,12 @@ fun IntentUriScreen(uri: Uri) {
}
host {
val menuState = LocalMenuState.current
val colorPalette = LocalColorPalette.current
val density = LocalDensity.current
val player = LocalYoutubePlayer.current
val coroutineScope = rememberCoroutineScope()
val shimmer = rememberShimmer(shimmerBounds = ShimmerBounds.Window)
@ -77,6 +90,44 @@ fun IntentUriScreen(uri: Uri) {
}
}
var isImportingAsPlaylist by remember {
mutableStateOf(false)
}
if (isImportingAsPlaylist) {
TextFieldDialog(
hintText = "Enter the playlist name",
onDismiss = {
isImportingAsPlaylist = false
},
onDone = { text ->
menuState.hide()
coroutineScope.launch(Dispatchers.IO) {
Database.internal.runInTransaction {
val playlistId = Database.insert(Playlist(name = text))
items.valueOrNull
?.map(YouTube.Item.Song::asMediaItem)
?.forEachIndexed { index, mediaItem ->
if (Database.song(mediaItem.mediaId) == null) {
Database.insert(mediaItem)
}
Database.insert(
SongInPlaylist(
songId = mediaItem.mediaId,
playlistId = playlistId,
position = index
)
)
}
}
}
}
)
}
LazyColumn(
state = lazyListState,
horizontalAlignment = Alignment.CenterHorizontally,
@ -100,6 +151,47 @@ fun IntentUriScreen(uri: Uri) {
.padding(horizontal = 16.dp)
.size(24.dp)
)
Image(
painter = painterResource(R.drawable.ellipsis_horizontal),
contentDescription = null,
colorFilter = ColorFilter.tint(colorPalette.text),
modifier = Modifier
.clickable {
menuState.display {
Menu {
MenuCloseButton(onClick = menuState::hide)
MenuEntry(
icon = R.drawable.time,
text = "Enqueue",
enabled = player?.playbackState == Player.STATE_READY,
onClick = {
menuState.hide()
items.valueOrNull
?.map(YouTube.Item.Song::asMediaItem)
?.let { mediaItems ->
player?.mediaController?.enqueue(
mediaItems
)
}
}
)
MenuEntry(
icon = R.drawable.list,
text = "Import as playlist",
onClick = {
isImportingAsPlaylist = true
}
)
}
}
}
.padding(horizontal = 16.dp, vertical = 8.dp)
.size(24.dp)
)
}
}
@ -140,16 +232,20 @@ fun IntentUriScreen(uri: Uri) {
}
} else {
itemsIndexed(currentItems.value) { index, item ->
SmallSongItem(
song = item,
thumbnailSizePx = density.run { 54.dp.roundToPx() },
onClick = {
YoutubePlayer.Radio.reset()
SmallSongItem(
song = item,
thumbnailSizePx = density.run { 54.dp.roundToPx() },
onClick = {
YoutubePlayer.Radio.reset()
player?.mediaController?.forcePlayAtIndex(currentItems.value.map(YouTube.Item.Song::asMediaItem), index)
pop()
}
)
player?.mediaController?.forcePlayAtIndex(
currentItems.value.map(
YouTube.Item.Song::asMediaItem
), index
)
pop()
}
)
}
}
}