music: add playlist deletion
Add basic playlist deletion flow. No confirmation dialog yet, that will need to be implemented later.
This commit is contained in:
parent
956b6fda2b
commit
dcc82608bd
13 changed files with 92 additions and 37 deletions
|
@ -186,14 +186,11 @@ constructor(
|
|||
}
|
||||
|
||||
override fun onMusicChanges(changes: MusicRepository.Changes) {
|
||||
if (!changes.deviceLibrary) return
|
||||
val deviceLibrary = musicRepository.deviceLibrary ?: return
|
||||
val userLibrary = musicRepository.userLibrary ?: return
|
||||
|
||||
// If we are showing any item right now, we will need to refresh it (and any information
|
||||
// related to it) with the new library in order to prevent stale items from showing up
|
||||
// in the UI.
|
||||
|
||||
val deviceLibrary = musicRepository.deviceLibrary
|
||||
if (changes.deviceLibrary && deviceLibrary != null) {
|
||||
val song = currentSong.value
|
||||
if (song != null) {
|
||||
_currentSong.value = deviceLibrary.findSong(song.uid)?.also(::refreshAudioInfo)
|
||||
|
@ -208,7 +205,8 @@ constructor(
|
|||
|
||||
val artist = currentArtist.value
|
||||
if (artist != null) {
|
||||
_currentArtist.value = deviceLibrary.findArtist(artist.uid)?.also(::refreshArtistList)
|
||||
_currentArtist.value =
|
||||
deviceLibrary.findArtist(artist.uid)?.also(::refreshArtistList)
|
||||
logD("Updated artist to ${currentArtist.value}")
|
||||
}
|
||||
|
||||
|
@ -217,13 +215,17 @@ constructor(
|
|||
_currentGenre.value = deviceLibrary.findGenre(genre.uid)?.also(::refreshGenreList)
|
||||
logD("Updated genre to ${currentGenre.value}")
|
||||
}
|
||||
}
|
||||
|
||||
val userLibrary = musicRepository.userLibrary
|
||||
if (changes.userLibrary && userLibrary != null) {
|
||||
val playlist = currentPlaylist.value
|
||||
if (playlist != null) {
|
||||
_currentPlaylist.value =
|
||||
userLibrary.findPlaylist(playlist.uid)?.also(::refreshPlaylistList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new [currentSong] from it's [Music.UID]. If the [Music.UID] differs, [currentSong] and
|
||||
|
|
|
@ -126,6 +126,10 @@ class PlaylistDetailFragment :
|
|||
requireContext().showToast(R.string.lng_queue_added)
|
||||
true
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
musicModel.deletePlaylist(currentPlaylist)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,6 +255,9 @@ abstract class ListFragment<in T : Music, VB : ViewBinding> :
|
|||
playbackModel.addToQueue(playlist)
|
||||
requireContext().showToast(R.string.lng_queue_added)
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
musicModel.deletePlaylist(playlist)
|
||||
}
|
||||
else -> {
|
||||
error("Unexpected menu item selected")
|
||||
}
|
||||
|
|
|
@ -350,8 +350,8 @@ interface Playlist : MusicParent {
|
|||
}
|
||||
|
||||
/**
|
||||
* Run [Name.resolve] on each instance in the given list and concatenate them into a [String]
|
||||
* in a localized manner.
|
||||
* Run [Name.resolve] on each instance in the given list and concatenate them into a [String] in a
|
||||
* localized manner.
|
||||
*
|
||||
* @param context [Context] required
|
||||
* @return A concatenated string.
|
||||
|
|
|
@ -118,6 +118,13 @@ interface MusicRepository {
|
|||
*/
|
||||
fun createPlaylist(name: String, songs: List<Song>)
|
||||
|
||||
/**
|
||||
* Delete a [Playlist].
|
||||
*
|
||||
* @param playlist The playlist to delete.
|
||||
*/
|
||||
fun deletePlaylist(playlist: Playlist)
|
||||
|
||||
/**
|
||||
* Add the given [Song]s to a [Playlist].
|
||||
*
|
||||
|
@ -262,6 +269,15 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun deletePlaylist(playlist: Playlist) {
|
||||
val userLibrary = userLibrary ?: return
|
||||
userLibrary.deletePlaylist(playlist)
|
||||
for (listener in updateListeners) {
|
||||
listener.onMusicChanges(
|
||||
MusicRepository.Changes(deviceLibrary = false, userLibrary = true))
|
||||
}
|
||||
}
|
||||
|
||||
override fun addToPlaylist(songs: List<Song>, playlist: Playlist) {
|
||||
val userLibrary = userLibrary ?: return
|
||||
userLibrary.addToPlaylist(playlist, songs)
|
||||
|
|
|
@ -106,6 +106,17 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a [Playlist].
|
||||
*
|
||||
* @param playlist The playlist to delete.
|
||||
*
|
||||
* TODO: Prompt the user before deleting.
|
||||
*/
|
||||
fun deletePlaylist(playlist: Playlist) {
|
||||
musicRepository.deletePlaylist(playlist)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a [Song] to a [Playlist].
|
||||
*
|
||||
|
|
|
@ -210,6 +210,8 @@ private class DeviceLibraryImpl(rawSongs: List<RawSong>, settings: MusicSettings
|
|||
albums: List<AlbumImpl>,
|
||||
settings: MusicSettings
|
||||
): List<ArtistImpl> {
|
||||
// TODO: Debug an issue with my current library config that results in two duplicate
|
||||
// artists.
|
||||
// Add every raw artist credited to each Song/Album to the grouping. This way,
|
||||
// different multi-artist combinations are not treated as different artists.
|
||||
val musicByArtist = mutableMapOf<RawArtist, MutableList<Music>>()
|
||||
|
|
|
@ -99,11 +99,6 @@ class SeparatorsDialog : ViewBindingDialogFragment<DialogSeparatorsBinding>() {
|
|||
return separators
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the allowed separator characters that can be used to delimit multi-value tags.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
private object Separators {
|
||||
const val COMMA = ','
|
||||
const val SEMICOLON = ';'
|
||||
|
|
|
@ -130,6 +130,9 @@ private class TagWorkerImpl(
|
|||
// 3. ID3v2.4 Release Date, as it is the second most common date type
|
||||
// 4. ID3v2.3 Original Date, as it is like #1
|
||||
// 5. ID3v2.3 Release Year, as it is the most common date type
|
||||
// TODO: Show original and normal dates side-by-side
|
||||
// TODO: Handle dates that are in "January" because the actual specific release date
|
||||
// isn't known?
|
||||
(textFrames["TDOR"]?.run { Date.from(first()) }
|
||||
?: textFrames["TDRC"]?.run { Date.from(first()) }
|
||||
?: textFrames["TDRL"]?.run { Date.from(first()) }
|
||||
|
|
|
@ -80,6 +80,13 @@ interface MutableUserLibrary : UserLibrary {
|
|||
*/
|
||||
fun createPlaylist(name: String, songs: List<Song>)
|
||||
|
||||
/**
|
||||
* Delete a [Playlist].
|
||||
*
|
||||
* @param playlist The playlist to delete.
|
||||
*/
|
||||
fun deletePlaylist(playlist: Playlist)
|
||||
|
||||
/**
|
||||
* Add [Song]s to a [Playlist].
|
||||
*
|
||||
|
@ -120,6 +127,11 @@ private class UserLibraryImpl(
|
|||
playlistMap[playlistImpl.uid] = playlistImpl
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun deletePlaylist(playlist: Playlist) {
|
||||
playlistMap.remove(playlist.uid)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun addToPlaylist(playlist: Playlist, songs: List<Song>) {
|
||||
val playlistImpl =
|
||||
|
|
|
@ -12,4 +12,7 @@
|
|||
<item
|
||||
android:id="@+id/action_queue_add"
|
||||
android:title="@string/lbl_queue_add" />
|
||||
<item
|
||||
android:id="@+id/action_delete"
|
||||
android:title="@string/lbl_delete" />
|
||||
</menu>
|
|
@ -6,4 +6,7 @@
|
|||
<item
|
||||
android:id="@+id/action_queue_add"
|
||||
android:title="@string/lbl_queue_add" />
|
||||
<item
|
||||
android:id="@+id/action_delete"
|
||||
android:title="@string/lbl_delete" />
|
||||
</menu>
|
|
@ -79,6 +79,7 @@
|
|||
<string name="lbl_playlist">Playlist</string>
|
||||
<string name="lbl_playlists">Playlists</string>
|
||||
<string name="lbl_new_playlist">New playlist</string>
|
||||
<string name="lbl_delete">Delete</string>
|
||||
|
||||
<!-- Search for music -->
|
||||
<string name="lbl_search">Search</string>
|
||||
|
|
Loading…
Reference in a new issue