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.platform.LocalDensity
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.media3.common.Player
import com.valentinilk.shimmer.ShimmerBounds import com.valentinilk.shimmer.ShimmerBounds
import com.valentinilk.shimmer.rememberShimmer import com.valentinilk.shimmer.rememberShimmer
import it.vfsfitvnm.route.RouteHandler import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.R 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.Error
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.Message import it.vfsfitvnm.vimusic.ui.components.Message
import it.vfsfitvnm.vimusic.ui.components.TopAppBar 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.ui.styling.LocalColorPalette
import it.vfsfitvnm.vimusic.utils.* import it.vfsfitvnm.vimusic.utils.*
import it.vfsfitvnm.youtubemusic.Outcome import it.vfsfitvnm.youtubemusic.Outcome
import it.vfsfitvnm.youtubemusic.YouTube import it.vfsfitvnm.youtubemusic.YouTube
import it.vfsfitvnm.youtubemusic.toNullable import it.vfsfitvnm.youtubemusic.toNullable
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ExperimentalAnimationApi @ExperimentalAnimationApi
@ -54,10 +65,12 @@ fun IntentUriScreen(uri: Uri) {
} }
host { host {
val menuState = LocalMenuState.current
val colorPalette = LocalColorPalette.current val colorPalette = LocalColorPalette.current
val density = LocalDensity.current val density = LocalDensity.current
val player = LocalYoutubePlayer.current val player = LocalYoutubePlayer.current
val coroutineScope = rememberCoroutineScope()
val shimmer = rememberShimmer(shimmerBounds = ShimmerBounds.Window) 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( LazyColumn(
state = lazyListState, state = lazyListState,
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
@ -100,6 +151,47 @@ fun IntentUriScreen(uri: Uri) {
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
.size(24.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 { } else {
itemsIndexed(currentItems.value) { index, item -> itemsIndexed(currentItems.value) { index, item ->
SmallSongItem( SmallSongItem(
song = item, song = item,
thumbnailSizePx = density.run { 54.dp.roundToPx() }, thumbnailSizePx = density.run { 54.dp.roundToPx() },
onClick = { onClick = {
YoutubePlayer.Radio.reset() YoutubePlayer.Radio.reset()
player?.mediaController?.forcePlayAtIndex(currentItems.value.map(YouTube.Item.Song::asMediaItem), index) player?.mediaController?.forcePlayAtIndex(
pop() currentItems.value.map(
} YouTube.Item.Song::asMediaItem
) ), index
)
pop()
}
)
} }
} }
} }