From 9b0e39919b96909c7cf0bdd7d0c010ebd2da3610 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Tue, 27 Jun 2023 19:43:15 -0600 Subject: [PATCH] music: simplify playlist decision events Simplify the 4 stateflows controlling when playlist decision dialogs must be opened to just one enum. This is like the detail view, and makes the amount of observers I have to spin up much smaller. Eventually, most of even these observer calls will be collapsed into the menu itself. --- .../java/org/oxycblt/auxio/MainFragment.kt | 2 - .../auxio/detail/AlbumDetailFragment.kt | 44 ++++++++++++----- .../auxio/detail/ArtistDetailFragment.kt | 46 +++++++++++++----- .../auxio/detail/GenreDetailFragment.kt | 46 +++++++++++++----- .../auxio/detail/PlaylistDetailFragment.kt | 47 +++++++++++++----- .../oxycblt/auxio/detail/SongDetailDialog.kt | 1 + .../org/oxycblt/auxio/home/HomeFragment.kt | 41 ++++++++++++++-- .../org/oxycblt/auxio/music/MusicViewModel.kt | 34 +++++-------- .../oxycblt/auxio/search/SearchFragment.kt | 48 +++++++++++++++++-- 9 files changed, 229 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 00c88bd53..9b6b47a08 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -62,8 +62,6 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * high-level navigation features. * * @author Alexander Capehart (OxygenCobalt) - * - * TODO: Break up the god navigation setup going on here */ @AndroidEntryPoint class MainFragment : diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 8844de56e..b0c60107f 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -46,6 +46,7 @@ import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel +import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.info.Disc import org.oxycblt.auxio.playback.PlaybackViewModel @@ -124,6 +125,7 @@ class AlbumDetailFragment : collectImmediately(detailModel.albumList, ::updateList) collect(detailModel.toShow.flow, ::handleShow) collectImmediately(selectionModel.selected, ::updateSelection) + collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(playbackModel.artistPickerSong.flow, ::handlePlayFromArtist) @@ -298,6 +300,36 @@ class AlbumDetailFragment : } } + private fun updateSelection(selected: List) { + albumListAdapter.setSelected(selected.toSet()) + + val binding = requireBinding() + if (selected.isNotEmpty()) { + binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) + binding.detailToolbar.setVisible(R.id.detail_selection_toolbar) + } else { + binding.detailToolbar.setVisible(R.id.detail_normal_toolbar) + } + } + + private fun handleDecision(decision: PlaylistDecision?) { + when (decision) { + is PlaylistDecision.Add ->{ + logD("Adding ${decision.songs.size} songs to a playlist") + findNavController().navigateSafe( + AlbumDetailFragmentDirections.addToPlaylist( + decision.songs.map { it.uid }.toTypedArray()) + ) + musicModel.playlistDecision.consume() + } + + is PlaylistDecision.New, is PlaylistDecision.Rename, is PlaylistDecision.Delete -> + error("Unexpected decision $decision") + + null -> {} + } + } + private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { albumListAdapter.setPlaying( song.takeIf { parent == detailModel.currentAlbum.value }, isPlaying) @@ -352,16 +384,4 @@ class AlbumDetailFragment : } } } - - private fun updateSelection(selected: List) { - albumListAdapter.setSelected(selected.toSet()) - - val binding = requireBinding() - if (selected.isNotEmpty()) { - binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) - binding.detailToolbar.setVisible(R.id.detail_selection_toolbar) - } else { - binding.detailToolbar.setVisible(R.id.detail_normal_toolbar) - } - } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index b55bc9be1..347c13a1b 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -46,6 +46,7 @@ import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel +import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.collect @@ -124,11 +125,12 @@ class ArtistDetailFragment : collectImmediately(detailModel.currentArtist, ::updateArtist) collectImmediately(detailModel.artistList, ::updateList) collect(detailModel.toShow.flow, ::handleShow) + collectImmediately(selectionModel.selected, ::updateSelection) + collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(playbackModel.artistPickerSong.flow, ::handlePlayFromArtist) collect(playbackModel.genrePickerSong.flow, ::handlePlayFromGenre) - collectImmediately(selectionModel.selected, ::updateSelection) } override fun onDestroyBinding(binding: FragmentDetailBinding) { @@ -308,6 +310,36 @@ class ArtistDetailFragment : } } + private fun updateSelection(selected: List) { + artistListAdapter.setSelected(selected.toSet()) + + val binding = requireBinding() + if (selected.isNotEmpty()) { + binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) + binding.detailToolbar.setVisible(R.id.detail_selection_toolbar) + } else { + binding.detailToolbar.setVisible(R.id.detail_normal_toolbar) + } + } + + private fun handleDecision(decision: PlaylistDecision?) { + when (decision) { + is PlaylistDecision.Add ->{ + logD("Adding ${decision.songs.size} songs to a playlist") + findNavController().navigateSafe( + ArtistDetailFragmentDirections.addToPlaylist( + decision.songs.map { it.uid }.toTypedArray()) + ) + musicModel.playlistDecision.consume() + } + + is PlaylistDecision.New, is PlaylistDecision.Rename, is PlaylistDecision.Delete -> + error("Unexpected decision $decision") + + null -> {} + } + } + private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { val currentArtist = unlikelyToBeNull(detailModel.currentArtist.value) val playingItem = @@ -334,16 +366,4 @@ class ArtistDetailFragment : logD("Launching play from genre dialog for $song") findNavController().navigateSafe(AlbumDetailFragmentDirections.playFromGenre(song.uid)) } - - private fun updateSelection(selected: List) { - artistListAdapter.setSelected(selected.toSet()) - - val binding = requireBinding() - if (selected.isNotEmpty()) { - binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) - binding.detailToolbar.setVisible(R.id.detail_selection_toolbar) - } else { - binding.detailToolbar.setVisible(R.id.detail_normal_toolbar) - } - } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index 5934d4a11..d0d4ff1bd 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -46,6 +46,7 @@ import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel +import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.collect @@ -122,11 +123,12 @@ class GenreDetailFragment : collectImmediately(detailModel.currentGenre, ::updatePlaylist) collectImmediately(detailModel.genreList, ::updateList) collect(detailModel.toShow.flow, ::handleShow) + collectImmediately(selectionModel.selected, ::updateSelection) + collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(playbackModel.artistPickerSong.flow, ::handlePlayFromArtist) collect(playbackModel.genrePickerSong.flow, ::handlePlayFromGenre) - collectImmediately(selectionModel.selected, ::updateSelection) } override fun onDestroyBinding(binding: FragmentDetailBinding) { @@ -295,6 +297,36 @@ class GenreDetailFragment : } } + private fun updateSelection(selected: List) { + genreListAdapter.setSelected(selected.toSet()) + + val binding = requireBinding() + if (selected.isNotEmpty()) { + binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) + binding.detailToolbar.setVisible(R.id.detail_selection_toolbar) + } else { + binding.detailToolbar.setVisible(R.id.detail_normal_toolbar) + } + } + + private fun handleDecision(decision: PlaylistDecision?) { + when (decision) { + is PlaylistDecision.Add ->{ + logD("Adding ${decision.songs.size} songs to a playlist") + findNavController().navigateSafe( + GenreDetailFragmentDirections.addToPlaylist( + decision.songs.map { it.uid }.toTypedArray()) + ) + musicModel.playlistDecision.consume() + } + + is PlaylistDecision.New, is PlaylistDecision.Rename, is PlaylistDecision.Delete -> + error("Unexpected decision $decision") + + null -> {} + } + } + private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { val currentGenre = unlikelyToBeNull(detailModel.currentGenre.value) val playingItem = @@ -321,16 +353,4 @@ class GenreDetailFragment : logD("Launching play from genre dialog for $song") findNavController().navigateSafe(AlbumDetailFragmentDirections.playFromGenre(song.uid)) } - - private fun updateSelection(selected: List) { - genreListAdapter.setSelected(selected.toSet()) - - val binding = requireBinding() - if (selected.isNotEmpty()) { - binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) - binding.detailToolbar.setVisible(R.id.detail_selection_toolbar) - } else { - binding.detailToolbar.setVisible(R.id.detail_normal_toolbar) - } - } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt index e2ae60c93..38aac6dcf 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt @@ -48,6 +48,7 @@ import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.Playlist +import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.collect @@ -137,11 +138,12 @@ class PlaylistDetailFragment : collectImmediately(detailModel.playlistList, ::updateList) collectImmediately(detailModel.editedPlaylist, ::updateEditedList) collect(detailModel.toShow.flow, ::handleShow) + collectImmediately(selectionModel.selected, ::updateSelection) + collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(playbackModel.artistPickerSong.flow, ::handlePlayFromArtist) collect(playbackModel.genrePickerSong.flow, ::handlePlayFromGenre) - collectImmediately(selectionModel.selected, ::updateSelection) } override fun onStart() { @@ -342,6 +344,38 @@ class PlaylistDetailFragment : } } + private fun updateSelection(selected: List) { + playlistListAdapter.setSelected(selected.toSet()) + + val binding = requireBinding() + if (selected.isNotEmpty()) { + binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) + } + updateMultiToolbar() + } + + private fun handleDecision(decision: PlaylistDecision?) { + if (decision == null) return + when (decision) { + is PlaylistDecision.Rename -> { + logD("Renaming ${decision.playlist}") + findNavController().navigateSafe( + PlaylistDetailFragmentDirections.renamePlaylist(decision.playlist.uid) + ) + } + + is PlaylistDecision.Delete -> { + logD("Deleting ${decision.playlist}") + findNavController().navigateSafe( + PlaylistDetailFragmentDirections.deletePlaylist(decision.playlist.uid) + ) + } + + is PlaylistDecision.Add, is PlaylistDecision.New -> error("Unexpected decision $decision") + } + musicModel.playlistDecision.consume() + } + private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { // Prefer songs that are playing from this playlist. playlistListAdapter.setPlaying( @@ -359,17 +393,6 @@ class PlaylistDetailFragment : logD("Launching play from genre dialog for $song") findNavController().navigateSafe(AlbumDetailFragmentDirections.playFromGenre(song.uid)) } - - private fun updateSelection(selected: List) { - playlistListAdapter.setSelected(selected.toSet()) - - val binding = requireBinding() - if (selected.isNotEmpty()) { - binding.detailSelectionToolbar.title = getString(R.string.fmt_selected, selected.size) - } - updateMultiToolbar() - } - private fun updateMultiToolbar() { val id = when { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt b/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt index c46d23ea7..f7b293a06 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt @@ -130,6 +130,7 @@ class SongDetailDialog : ViewBindingDialogFragment() { if (show == null) return if (show is Show.SongDetails) { logD("Navigated to this song") + detailModel.toShow.consume() } else { error("Unexpected show command $show") } diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index 0d2e40ad3..3d08cdfa0 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -65,6 +65,7 @@ import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.NoAudioPermissionException import org.oxycblt.auxio.music.NoMusicException import org.oxycblt.auxio.music.PERMISSION_READ_AUDIO +import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.collect @@ -85,9 +86,9 @@ import org.oxycblt.auxio.util.unlikelyToBeNull @AndroidEntryPoint class HomeFragment : SelectionFragment(), AppBarLayout.OnOffsetChangedListener { - override val playbackModel: PlaybackViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() + override val playbackModel: PlaybackViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private var storagePermissionLauncher: ActivityResultLauncher? = null @@ -171,9 +172,10 @@ class HomeFragment : collect(homeModel.recreateTabs.flow, ::handleRecreate) collectImmediately(homeModel.currentTabMode, ::updateCurrentTab) collectImmediately(homeModel.songsList, homeModel.isFastScrolling, ::updateFab) - collectImmediately(musicModel.indexingState, ::updateIndexerState) - collect(detailModel.toShow.flow, ::handleShow) collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(musicModel.indexingState, ::updateIndexerState) + collect(musicModel.playlistDecision.flow, ::handleDecision) + collect(detailModel.toShow.flow, ::handleShow) } override fun onSaveInstanceState(outState: Bundle) { @@ -479,6 +481,39 @@ class HomeFragment : } } + private fun handleDecision(decision: PlaylistDecision?) { + if (decision == null) return + when (decision) { + is PlaylistDecision.New -> { + logD("Creating new playlist") + findNavController().navigateSafe( + HomeFragmentDirections.newPlaylist(decision.songs.map { it.uid }.toTypedArray())) + } + + is PlaylistDecision.Rename -> { + logD("Renaming ${decision.playlist}") + findNavController().navigateSafe( + HomeFragmentDirections.renamePlaylist(decision.playlist.uid) + ) + } + + is PlaylistDecision.Delete -> { + logD("Deleting ${decision.playlist}") + findNavController().navigateSafe( + HomeFragmentDirections.deletePlaylist(decision.playlist.uid) + ) + } + + is PlaylistDecision.Add -> { + logD("Adding ${decision.songs.size} to a playlist") + findNavController().navigateSafe( + HomeFragmentDirections.addToPlaylist(decision.songs.map { it.uid }.toTypedArray()) + ) + } + } + musicModel.playlistDecision.consume() + } + private fun updateFab(songs: List, isFastScrolling: Boolean) { val binding = requireBinding() // If there are no songs, it's likely that the library has not been loaded, so diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt index 6390929b7..b8717d220 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt @@ -52,23 +52,8 @@ constructor( val statistics: StateFlow get() = _statistics - private val _newPlaylistSongs = MutableEvent>() - /** Flag for opening a dialog to create a playlist of the given [Song]s. */ - val newPlaylistSongs: Event> = _newPlaylistSongs - - private val _playlistToRename = MutableEvent() - /** Flag for opening a dialog to rename the given [Playlist]. */ - val playlistToRename: Event - get() = _playlistToRename - - private val _playlistToDelete = MutableEvent() - /** Flag for opening a dialog to confirm deletion of the given [Playlist]. */ - val playlistToDelete: Event - get() = _playlistToDelete - - private val _songsToAdd = MutableEvent>() - /** Flag for opening a dialog to add the given [Song]s to a playlist. */ - val songsToAdd: Event> = _songsToAdd + private val _playlistDecision = MutableEvent() + val playlistDecision: Event get() = _playlistDecision init { musicRepository.addUpdateListener(this) @@ -121,7 +106,7 @@ constructor( viewModelScope.launch(Dispatchers.IO) { musicRepository.createPlaylist(name, songs) } } else { logD("Launching creation dialog for ${songs.size} songs") - _newPlaylistSongs.put(songs) + _playlistDecision.put(PlaylistDecision.New(songs)) } } @@ -137,7 +122,7 @@ constructor( viewModelScope.launch(Dispatchers.IO) { musicRepository.renamePlaylist(playlist, name) } } else { logD("Launching rename dialog for $playlist") - _playlistToRename.put(playlist) + _playlistDecision.put(PlaylistDecision.Rename(playlist)) } } @@ -154,7 +139,7 @@ constructor( viewModelScope.launch(Dispatchers.IO) { musicRepository.deletePlaylist(playlist) } } else { logD("Launching deletion dialog for $playlist") - _playlistToDelete.put(playlist) + _playlistDecision.put(PlaylistDecision.Delete(playlist)) } } @@ -214,7 +199,7 @@ constructor( viewModelScope.launch(Dispatchers.IO) { musicRepository.addToPlaylist(songs, playlist) } } else { logD("Launching addition dialog for songs=${songs.size}") - _songsToAdd.put(songs) + _playlistDecision.put(PlaylistDecision.Add(songs)) } } @@ -235,3 +220,10 @@ constructor( val durationMs: Long ) } + +sealed interface PlaylistDecision { + data class New(val songs: List) : PlaylistDecision + data class Rename(val playlist: Playlist) : PlaylistDecision + data class Delete(val playlist: Playlist) : PlaylistDecision + data class Add(val songs: List) : PlaylistDecision +} diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index 90184814b..7239221f0 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -34,8 +34,10 @@ import com.google.android.material.transition.MaterialSharedAxis import dagger.hilt.android.AndroidEntryPoint import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentSearchBinding +import org.oxycblt.auxio.detail.ArtistDetailFragmentDirections import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.Show +import org.oxycblt.auxio.home.HomeFragmentDirections import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item @@ -48,6 +50,7 @@ import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.Playlist +import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.collect @@ -136,10 +139,11 @@ class SearchFragment : ListFragment() { // --- VIEWMODEL SETUP --- collectImmediately(searchModel.searchResults, ::updateSearchResults) + collectImmediately(selectionModel.selected, ::updateSelection) + collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) collect(detailModel.toShow.flow, ::handleShow) - collectImmediately(selectionModel.selected, ::updateSelection) } override fun onDestroyBinding(binding: FragmentSearchBinding) { @@ -200,9 +204,7 @@ class SearchFragment : ListFragment() { } } - private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { - searchAdapter.setPlaying(parent ?: song, isPlaying) - } + private fun handleShow(show: Show?) { when (show) { @@ -257,6 +259,44 @@ class SearchFragment : ListFragment() { hideKeyboard() } + + private fun handleDecision(decision: PlaylistDecision?) { + if (decision == null) return + when (decision) { + is PlaylistDecision.New -> { + logD("Creating new playlist") + findNavController().navigateSafe( + HomeFragmentDirections.newPlaylist(decision.songs.map { it.uid }.toTypedArray())) + } + + is PlaylistDecision.Rename -> { + logD("Renaming ${decision.playlist}") + findNavController().navigateSafe( + HomeFragmentDirections.renamePlaylist(decision.playlist.uid) + ) + } + + is PlaylistDecision.Delete -> { + logD("Deleting ${decision.playlist}") + findNavController().navigateSafe( + SearchFragmentDirections.deletePlaylist(decision.playlist.uid) + ) + } + + is PlaylistDecision.Add -> { + logD("Adding ${decision.songs.size} to a playlist") + findNavController().navigateSafe( + HomeFragmentDirections.addToPlaylist(decision.songs.map { it.uid }.toTypedArray()) + ) + } + } + musicModel.playlistDecision.consume() + } + + private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { + searchAdapter.setPlaying(parent ?: song, isPlaying) + } + private fun updateSelection(selected: List) { searchAdapter.setSelected(selected.toSet()) val binding = requireBinding()