Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.metrolist.innertube.YouTube
import com.metrolist.innertube.utils.parseCookieString
import com.metrolist.music.LocalDatabase
import com.metrolist.music.R
Expand Down Expand Up @@ -74,20 +73,19 @@ import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.material3.FilterChip
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.material3.FilterChipDefaults
import com.metrolist.music.LocalSyncUtils

@Composable
fun AddToPlaylistDialog(
isVisible: Boolean,
allowSyncing: Boolean = true,
initialTextFieldValue: String? = null,
multiSelectParams: String? = null,
onGetSong: suspend (Playlist) -> List<String>, // list of song ids. Songs should be inserted to database in this function.
onGetSongIds: (suspend () -> List<String>)? = null,
onDismiss: () -> Unit,
viewModel: PlaylistsViewModel = hiltViewModel()
) {
val database = LocalDatabase.current
val syncUtils = LocalSyncUtils.current
val coroutineScope = rememberCoroutineScope()
val (sortType, onSortTypeChange) = rememberEnumPreference(
AddToPlaylistSortTypeKey,
Expand Down Expand Up @@ -122,20 +120,6 @@ fun AddToPlaylistDialog(
mutableStateOf<Set<String>>(emptySet())
}

suspend fun addSongsAndSync(targetPlaylist: Playlist, ids: List<String>) {
database.addSongsToPlaylist(targetPlaylist, ids.map { it to null }, prepend = true)
targetPlaylist.playlist.browseId?.let { plist ->
ids.forEach { songId ->
syncUtils.registerPendingAdd(plist, songId)
try {
YouTube.addToPlaylist(plist, songId)
} finally {
syncUtils.unregisterPendingAdd(plist, songId)
}
}
}
}

LaunchedEffect(isVisible, playlists.isEmpty()) {
if (!isVisible || playlists.isEmpty()) return@LaunchedEffect
if (songIds != null) return@LaunchedEffect
Expand Down Expand Up @@ -291,26 +275,29 @@ fun AddToPlaylistDialog(
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "playlistBg"
)
PlaylistListItem(
playlist = playlist,
modifier = Modifier
PlaylistListItem(
playlist = playlist,
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 2.dp)
.clip(RoundedCornerShape(16.dp))
.background(rowBg)
.clickable {
selectedPlaylist = playlist
coroutineScope.launch(Dispatchers.IO) {
if (songIds == null) {
songIds = onGetSong(playlist)
} else {
onGetSong(playlist)
}
duplicates = database.playlistDuplicates(playlist.id, songIds!!)
val resolvedSongIds =
if (songIds.isNullOrEmpty()) {
onGetSong(playlist).also { resolved ->
songIds = resolved
}
} else {
songIds!!
}
duplicates = database.playlistDuplicates(playlist.id, resolvedSongIds)
if (duplicates.isNotEmpty()) {
showDuplicateDialog = true
} else {
onDismiss()
addSongsAndSync(playlist, songIds!!)
viewModel.addSongsAndSync(playlist, resolvedSongIds, multiSelectParams)
}
}
}
Expand All @@ -336,12 +323,11 @@ fun AddToPlaylistDialog(
onClick = {
showDuplicateDialog = false
onDismiss()
coroutineScope.launch(Dispatchers.IO) {
addSongsAndSync(
selectedPlaylist!!,
songIds!!.filter { !duplicates.contains(it) }
)
}
viewModel.addSongsAndSync(
selectedPlaylist!!,
songIds!!.filter { !duplicates.contains(it) },
multiSelectParams,
)
}
) {
Text(stringResource(R.string.skip_duplicates))
Expand All @@ -351,9 +337,7 @@ fun AddToPlaylistDialog(
onClick = {
showDuplicateDialog = false
onDismiss()
coroutineScope.launch(Dispatchers.IO) {
addSongsAndSync(selectedPlaylist!!, songIds!!)
}
viewModel.addSongsAndSync(selectedPlaylist!!, songIds!!, multiSelectParams)
}
) {
Text(stringResource(R.string.add_anyway))
Expand Down
9 changes: 1 addition & 8 deletions app/src/main/kotlin/com/metrolist/music/ui/menu/AlbumMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,7 @@ fun AlbumMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { playlistId ->
album.album.playlistId?.let { addPlaylistId ->
YouTube.addPlaylistToPlaylist(playlistId, addPlaylistId)
}
}
}
onGetSong = {
songs.map { it.id }
},
onGetSongIds = { songs.map { it.id } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,10 @@ fun PlayerMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
onGetSong = {
database.withTransaction {
insert(mediaMetadata)
}
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { YouTube.addToPlaylist(it, mediaMetadata.id) }
}
listOf(mediaMetadata.id)
},
onGetSongIds = { listOf(mediaMetadata.id) },
Expand Down
5 changes: 1 addition & 4 deletions app/src/main/kotlin/com/metrolist/music/ui/menu/QueueMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,10 @@ fun QueueMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
onGetSong = {
database.withTransaction {
insert(mediaMetadata)
}
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { YouTube.addToPlaylist(it, mediaMetadata.id) }
}
listOf(mediaMetadata.id)
},
onGetSongIds = { listOf(mediaMetadata.id) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,7 @@ fun SelectionSongMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
coroutineScope.launch(Dispatchers.IO) {
songSelection.forEach { song ->
playlist.playlist.browseId?.let { browseId ->
YouTube.addToPlaylist(browseId, song.id)
}
}
}
onGetSong = {
songSelection.map { it.id }
},
onGetSongIds = { songSelection.map { it.id } },
Expand Down
8 changes: 3 additions & 5 deletions app/src/main/kotlin/com/metrolist/music/ui/menu/SongMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,9 @@ fun SongMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { browseId ->
YouTube.addToPlaylist(browseId, song.id)
}
onGetSong = {
database.withTransaction {
insert(song.toMediaMetadata())
}
listOf(song.id)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,7 @@ fun YouTubeAlbumMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { playlistId ->
album?.album?.playlistId?.let { addPlaylistId ->
YouTube.addPlaylistToPlaylist(playlistId, addPlaylistId)
}
}
}
onGetSong = {
album?.songs?.map { it.id }.orEmpty()
},
onGetSongIds = { album?.songs?.map { it.id }.orEmpty() },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,12 @@ fun YouTubePlaylistMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { targetPlaylist ->
onGetSong = {
val allSongs =
songs
.ifEmpty {
YouTube
.playlist(targetPlaylist.id)
.playlist(playlist.id)
.completed()
.getOrNull()
?.songs
Expand All @@ -142,11 +142,6 @@ fun YouTubePlaylistMenu(
database.withTransaction {
allSongs.forEach(::insert)
}
coroutineScope.launch(Dispatchers.IO) {
targetPlaylist.playlist.browseId?.let { playlistId ->
YouTube.addPlaylistToPlaylist(playlistId, targetPlaylist.id)
}
}
allSongs.map { it.id }
},
onGetSongIds = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
Expand Down Expand Up @@ -122,52 +121,16 @@ fun YouTubeSelectionSongMenu(
}
}

AddToPlaylistDialogOnline(
val selectedSongs = songSelection.map { it.toMediaMetadata() }

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
songs =
remember {
songSelection
.map { song ->
// Convert SongItem to Song entity
val metadata = song.toMediaMetadata()
com.metrolist.music.db.entities.Song(
song =
com.metrolist.music.db.entities.SongEntity(
id = metadata.id,
title = metadata.title,
duration = metadata.duration,
thumbnailUrl = metadata.thumbnailUrl,
albumId = metadata.album?.id,
albumName = metadata.album?.title,
liked = metadata.liked,
totalPlayTime = 0,
inLibrary = metadata.inLibrary,
isLocal = false,
libraryAddToken = metadata.libraryAddToken,
libraryRemoveToken = metadata.libraryRemoveToken,
),
artists =
metadata.artists.map { artist ->
com.metrolist.music.db.entities.ArtistEntity(
id = artist.id ?: "",
name = artist.name,
)
},
album =
metadata.album?.let { album ->
com.metrolist.music.db.entities.AlbumEntity(
id = album.id,
title = album.title,
thumbnailUrl = metadata.thumbnailUrl, // Use song's thumbnail as album thumbnail
songCount = 0,
duration = 0,
)
},
)
}.toMutableStateList()
},
onProgressStart = { },
onPercentageChange = { },
onGetSong = {
database.withTransaction {
selectedSongs.forEach(::insert)
}
selectedSongs.map { it.id }
},
onDismiss = {
showChoosePlaylistDialog = false
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,10 @@ fun YouTubeSongMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
onGetSong = {
database.withTransaction {
insert(song.toMediaMetadata())
}
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { browseId ->
YouTube.addToPlaylist(browseId, song.id)
}
}
listOf(song.id)
},
onGetSongIds = { listOf(song.id) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ private fun NewMiniPlayer(
onClick: () -> Unit = {},
) {
val playerConnection = LocalPlayerConnection.current ?: return
val database = LocalDatabase.current
val menuState = LocalMenuState.current

// Theme settings - these rarely change
Expand Down Expand Up @@ -486,7 +487,12 @@ private fun NewMiniPlayer(
menuState.show {
AddToPlaylistDialog(
isVisible = true,
onGetSong = { listOf(metadata.id) },
onGetSong = {
database.withTransaction {
insert(metadata)
}
listOf(metadata.id)
},
onDismiss = menuState::dismiss,
)
}
Expand Down
Loading
Loading