diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 72c9c4d9c..785de520d 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -39,7 +39,7 @@ import kotlin.math.max import kotlin.math.min import org.oxycblt.auxio.databinding.FragmentMainBinding import org.oxycblt.auxio.detail.DetailViewModel -import org.oxycblt.auxio.list.selection.SelectionViewModel +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.OpenPanel @@ -67,7 +67,7 @@ class MainFragment : ViewTreeObserver.OnPreDrawListener, NavController.OnDestinationChangedListener { private val playbackModel: PlaybackViewModel by activityViewModels() - private val selectionModel: SelectionViewModel by activityViewModels() + private val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private var sheetBackCallback: SheetBackPressedCallback? = null private var detailBackCallback: DetailBackPressedCallback? = null @@ -100,7 +100,7 @@ class MainFragment : val detailBackCallback = DetailBackPressedCallback(detailModel).also { detailBackCallback = it } val selectionBackCallback = - SelectionBackPressedCallback(selectionModel).also { selectionBackCallback = it } + SelectionBackPressedCallback(listModel).also { selectionBackCallback = it } val exploreBackCallback = ExploreBackPressedCallback(binding.exploreNavHost).also { exploreBackCallback = it } @@ -152,7 +152,7 @@ class MainFragment : // --- VIEWMODEL SETUP --- collectImmediately(detailModel.editedPlaylist, detailBackCallback::invalidateEnabled) - collectImmediately(selectionModel.selected, selectionBackCallback::invalidateEnabled) + collectImmediately(listModel.selected, selectionBackCallback::invalidateEnabled) collectImmediately(playbackModel.song, ::updateSong) collectImmediately(playbackModel.openPanel.flow, ::handlePanel) } @@ -289,7 +289,7 @@ class MainFragment : initialNavDestinationChange = true return } - selectionModel.drop() + listModel.dropSelection() } private fun updateSong(song: Song?) { @@ -450,11 +450,10 @@ class MainFragment : } } - private inner class SelectionBackPressedCallback( - private val selectionModel: SelectionViewModel - ) : OnBackPressedCallback(false) { + private inner class SelectionBackPressedCallback(private val listModel: ListViewModel) : + OnBackPressedCallback(false) { override fun handleOnBackPressed() { - if (selectionModel.drop()) { + if (listModel.dropSelection()) { logD("Dropped selection") } } 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 26545af8f..6dae706e3 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -39,10 +39,9 @@ import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.list.Menu import org.oxycblt.auxio.list.Sort -import org.oxycblt.auxio.list.menu.MenuViewModel -import org.oxycblt.auxio.list.menu.PendingMenu -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode @@ -75,8 +74,7 @@ class AlbumDetailFragment : AlbumDetailHeaderAdapter.Listener, DetailListAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() // Information about what album to display is initially within the navigation arguments @@ -128,8 +126,8 @@ class AlbumDetailFragment : collectImmediately(detailModel.currentAlbum, ::updateAlbum) collectImmediately(detailModel.albumList, ::updateList) collect(detailModel.toShow.flow, ::handleShow) - collect(menuModel.pendingMenu.flow, ::handleMenu) - collectImmediately(selectionModel.selected, ::updateSelection) + collect(listModel.menu.flow, ::handleMenu) + collectImmediately(listModel.selected, ::updateSelection) collect(musicModel.playlistDecision.flow, ::handlePlaylistDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -187,7 +185,7 @@ class AlbumDetailFragment : } override fun onOpenMenu(item: Song, anchor: View) { - menuModel.open(R.menu.item_album_song, item) + listModel.openMenu(R.menu.item_album_song, item) } override fun onPlay() { @@ -304,17 +302,16 @@ class AlbumDetailFragment : } } - private fun handleMenu(pendingMenu: PendingMenu?) { - if (pendingMenu == null) return + private fun handleMenu(menu: Menu?) { + if (menu == null) return val directions = - when (pendingMenu) { - is PendingMenu.ForSong -> - AlbumDetailFragmentDirections.openSongMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForAlbum, - is PendingMenu.ForArtist, - is PendingMenu.ForGenre, - is PendingMenu.ForPlaylist -> error("Unexpected menu $pendingMenu") + when (menu) { + is Menu.ForSong -> + AlbumDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForAlbum, + is Menu.ForArtist, + is Menu.ForGenre, + is Menu.ForPlaylist -> error("Unexpected menu $menu") } findNavController().navigateSafe(directions) } 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 c133f26ad..35e72d7cd 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -39,10 +39,9 @@ import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.list.Menu import org.oxycblt.auxio.list.Sort -import org.oxycblt.auxio.list.menu.MenuViewModel -import org.oxycblt.auxio.list.menu.PendingMenu -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Music @@ -73,8 +72,7 @@ class ArtistDetailFragment : DetailHeaderAdapter.Listener, DetailListAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() // Information about what artist to display is initially within the navigation arguments @@ -129,8 +127,8 @@ class ArtistDetailFragment : collectImmediately(detailModel.currentArtist, ::updateArtist) collectImmediately(detailModel.artistList, ::updateList) collect(detailModel.toShow.flow, ::handleShow) - collect(menuModel.pendingMenu.flow, ::handleMenu) - collectImmediately(selectionModel.selected, ::updateSelection) + collect(listModel.menu.flow, ::handleMenu) + collectImmediately(listModel.selected, ::updateSelection) collect(musicModel.playlistDecision.flow, ::handlePlaylistDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -198,8 +196,8 @@ class ArtistDetailFragment : override fun onOpenMenu(item: Music, anchor: View) { when (item) { - is Song -> menuModel.open(R.menu.item_artist_song, item) - is Album -> menuModel.open(R.menu.item_artist_album, item) + is Song -> listModel.openMenu(R.menu.item_artist_song, item) + is Album -> listModel.openMenu(R.menu.item_artist_album, item) else -> error("Unexpected datatype: ${item::class.simpleName}") } } @@ -314,19 +312,17 @@ class ArtistDetailFragment : } } - private fun handleMenu(pendingMenu: PendingMenu?) { - if (pendingMenu == null) return + private fun handleMenu(menu: Menu?) { + if (menu == null) return val directions = - when (pendingMenu) { - is PendingMenu.ForSong -> - ArtistDetailFragmentDirections.openSongMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForAlbum -> - ArtistDetailFragmentDirections.openAlbumMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForArtist, - is PendingMenu.ForGenre, - is PendingMenu.ForPlaylist -> error("Unexpected menu $pendingMenu") + when (menu) { + is Menu.ForSong -> + ArtistDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForAlbum -> + ArtistDetailFragmentDirections.openAlbumMenu(menu.menuRes, menu.music.uid) + is Menu.ForArtist, + is Menu.ForGenre, + is Menu.ForPlaylist -> error("Unexpected menu $menu") } findNavController().navigateSafe(directions) } 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 51527b5f8..7ba2cc6c9 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -39,10 +39,9 @@ import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.list.Menu import org.oxycblt.auxio.list.Sort -import org.oxycblt.auxio.list.menu.MenuViewModel -import org.oxycblt.auxio.list.menu.PendingMenu -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music @@ -73,8 +72,7 @@ class GenreDetailFragment : DetailHeaderAdapter.Listener, DetailListAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() // Information about what genre to display is initially within the navigation arguments @@ -127,8 +125,8 @@ class GenreDetailFragment : collectImmediately(detailModel.currentGenre, ::updatePlaylist) collectImmediately(detailModel.genreList, ::updateList) collect(detailModel.toShow.flow, ::handleShow) - collect(menuModel.pendingMenu.flow, ::handleMenu) - collectImmediately(selectionModel.selected, ::updateSelection) + collect(listModel.menu.flow, ::handleMenu) + collectImmediately(listModel.selected, ::updateSelection) collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -196,8 +194,8 @@ class GenreDetailFragment : override fun onOpenMenu(item: Music, anchor: View) { when (item) { - is Artist -> menuModel.open(R.menu.item_parent, item) - is Song -> menuModel.open(R.menu.item_song, item) + is Artist -> listModel.openMenu(R.menu.item_parent, item) + is Song -> listModel.openMenu(R.menu.item_song, item) else -> error("Unexpected datatype: ${item::class.simpleName}") } } @@ -302,19 +300,17 @@ class GenreDetailFragment : } } - private fun handleMenu(pendingMenu: PendingMenu?) { - if (pendingMenu == null) return + private fun handleMenu(menu: Menu?) { + if (menu == null) return val directions = - when (pendingMenu) { - is PendingMenu.ForSong -> - GenreDetailFragmentDirections.openSongMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForArtist -> - GenreDetailFragmentDirections.openArtistMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForAlbum, - is PendingMenu.ForGenre, - is PendingMenu.ForPlaylist -> error("Unexpected menu $pendingMenu") + when (menu) { + is Menu.ForSong -> + GenreDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForArtist -> + GenreDetailFragmentDirections.openArtistMenu(menu.menuRes, menu.music.uid) + is Menu.ForAlbum, + is Menu.ForGenre, + is Menu.ForPlaylist -> error("Unexpected menu $menu") } findNavController().navigateSafe(directions) } 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 28eb68127..a41e31f8b 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt @@ -43,9 +43,8 @@ import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment -import org.oxycblt.auxio.list.menu.MenuViewModel -import org.oxycblt.auxio.list.menu.PendingMenu -import org.oxycblt.auxio.list.selection.SelectionViewModel +import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.list.Menu import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicViewModel @@ -76,8 +75,7 @@ class PlaylistDetailFragment : PlaylistDetailListAdapter.Listener, NavController.OnDestinationChangedListener { private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() // Information about what playlist to display is initially within the navigation arguments @@ -142,8 +140,8 @@ class PlaylistDetailFragment : collectImmediately(detailModel.playlistList, ::updateList) collectImmediately(detailModel.editedPlaylist, ::updateEditedList) collect(detailModel.toShow.flow, ::handleShow) - collect(menuModel.pendingMenu.flow, ::handleMenu) - collectImmediately(selectionModel.selected, ::updateSelection) + collect(listModel.menu.flow, ::handleMenu) + collectImmediately(listModel.selected, ::updateSelection) collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -239,7 +237,7 @@ class PlaylistDetailFragment : } override fun onOpenMenu(item: Song, anchor: View) { - menuModel.open(R.menu.item_playlist_song, item) + listModel.openMenu(R.menu.item_playlist_song, item) } override fun onPlay() { @@ -286,7 +284,7 @@ class PlaylistDetailFragment : private fun updateEditedList(editedPlaylist: List?) { playlistListAdapter.setEditing(editedPlaylist != null) playlistHeaderAdapter.setEditedPlaylist(editedPlaylist) - selectionModel.drop() + listModel.dropSelection() if (editedPlaylist != null) { logD("Updating save button state") @@ -349,17 +347,16 @@ class PlaylistDetailFragment : } } - private fun handleMenu(pendingMenu: PendingMenu?) { - if (pendingMenu == null) return + private fun handleMenu(menu: Menu?) { + if (menu == null) return val directions = - when (pendingMenu) { - is PendingMenu.ForSong -> - PlaylistDetailFragmentDirections.openSongMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForArtist, - is PendingMenu.ForAlbum, - is PendingMenu.ForGenre, - is PendingMenu.ForPlaylist -> error("Unexpected menu $pendingMenu") + when (menu) { + is Menu.ForSong -> + PlaylistDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForArtist, + is Menu.ForAlbum, + is Menu.ForGenre, + is Menu.ForPlaylist -> error("Unexpected menu $menu") } findNavController().navigateSafe(directions) } @@ -421,7 +418,7 @@ class PlaylistDetailFragment : logD("Currently editing playlist, showing edit toolbar") R.id.detail_edit_toolbar } - selectionModel.selected.value.isNotEmpty() -> { + listModel.selected.value.isNotEmpty() -> { logD("Currently selecting, showing selection toolbar") R.id.detail_selection_toolbar } 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 5b6d03413..9026057de 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -55,11 +55,10 @@ import org.oxycblt.auxio.home.list.PlaylistListFragment import org.oxycblt.auxio.home.list.SongListFragment import org.oxycblt.auxio.home.tabs.AdaptiveTabStrategy import org.oxycblt.auxio.home.tabs.Tab +import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.list.Menu +import org.oxycblt.auxio.list.SelectionFragment import org.oxycblt.auxio.list.Sort -import org.oxycblt.auxio.list.menu.MenuViewModel -import org.oxycblt.auxio.list.menu.PendingMenu -import org.oxycblt.auxio.list.selection.SelectionFragment -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.IndexingProgress import org.oxycblt.auxio.music.IndexingState import org.oxycblt.auxio.music.Music @@ -89,8 +88,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull @AndroidEntryPoint class HomeFragment : SelectionFragment(), AppBarLayout.OnOffsetChangedListener { - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels() @@ -104,8 +102,7 @@ class HomeFragment : // Orientation change will wipe whatever transition we were using prior, which will // result in no transition when the user navigates back. Make sure we re-initialize // our transitions. - val id = savedInstanceState.getInt(KEY_LAST_TRANSITION_ID, -2) - when (id) { + when (val id = savedInstanceState.getInt(KEY_LAST_TRANSITION_ID, -2)) { -2 -> {} -1 -> applyFadeTransition() else -> applyAxisTransition(id) @@ -178,8 +175,8 @@ class HomeFragment : collect(homeModel.recreateTabs.flow, ::handleRecreate) collectImmediately(homeModel.currentTabMode, ::updateCurrentTab) collectImmediately(homeModel.songsList, homeModel.isFastScrolling, ::updateFab) - collect(menuModel.pendingMenu.flow, ::handleMenu) - collectImmediately(selectionModel.selected, ::updateSelection) + collect(listModel.menu.flow, ::handleMenu) + collectImmediately(listModel.selected, ::updateSelection) collectImmediately(musicModel.indexingState, ::updateIndexerState) collect(musicModel.playlistDecision.flow, ::handleDecision) collect(detailModel.toShow.flow, ::handleShow) @@ -582,22 +579,19 @@ class HomeFragment : } } - private fun handleMenu(pendingMenu: PendingMenu?) { - if (pendingMenu == null) return + private fun handleMenu(menu: Menu?) { + if (menu == null) return val directions = - when (pendingMenu) { - is PendingMenu.ForSong -> - HomeFragmentDirections.openSongMenu(pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForAlbum -> - HomeFragmentDirections.openAlbumMenu(pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForArtist -> - HomeFragmentDirections.openArtistMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForGenre -> - HomeFragmentDirections.openGenreMenu(pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForPlaylist -> - HomeFragmentDirections.openPlaylistMenu( - pendingMenu.menuRes, pendingMenu.music.uid) + when (menu) { + is Menu.ForSong -> HomeFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForAlbum -> + HomeFragmentDirections.openAlbumMenu(menu.menuRes, menu.music.uid) + is Menu.ForArtist -> + HomeFragmentDirections.openArtistMenu(menu.menuRes, menu.music.uid) + is Menu.ForGenre -> + HomeFragmentDirections.openGenreMenu(menu.menuRes, menu.music.uid) + is Menu.ForPlaylist -> + HomeFragmentDirections.openPlaylistMenu(menu.menuRes, menu.music.uid) } findNavController().navigateSafe(directions) } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt index cf1c494ce..984551733 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt @@ -32,12 +32,11 @@ import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter -import org.oxycblt.auxio.list.menu.MenuViewModel import org.oxycblt.auxio.list.recycler.AlbumViewHolder -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode @@ -61,8 +60,7 @@ class AlbumListFragment : FastScrollRecyclerView.PopupProvider { private val homeModel: HomeViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val albumAdapter = AlbumAdapter(this) @@ -84,7 +82,7 @@ class AlbumListFragment : } collectImmediately(homeModel.albumsList, ::updateAlbums) - collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -144,7 +142,7 @@ class AlbumListFragment : } override fun onOpenMenu(item: Album, anchor: View) { - menuModel.open(R.menu.item_album, item) + listModel.openMenu(R.menu.item_album, item) } private fun updateAlbums(albums: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt index 878cfc3fe..ab9928003 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt @@ -30,12 +30,11 @@ import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter -import org.oxycblt.auxio.list.menu.MenuViewModel import org.oxycblt.auxio.list.recycler.ArtistViewHolder -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode @@ -59,8 +58,7 @@ class ArtistListFragment : FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val artistAdapter = ArtistAdapter(this) @@ -79,7 +77,7 @@ class ArtistListFragment : } collectImmediately(homeModel.artistsList, ::updateArtists) - collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -120,7 +118,7 @@ class ArtistListFragment : } override fun onOpenMenu(item: Artist, anchor: View) { - menuModel.open(R.menu.item_parent, item) + listModel.openMenu(R.menu.item_parent, item) } private fun updateArtists(artists: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt index 75f849c46..2ecd73f90 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt @@ -30,12 +30,11 @@ import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter -import org.oxycblt.auxio.list.menu.MenuViewModel import org.oxycblt.auxio.list.recycler.GenreViewHolder -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode @@ -58,8 +57,7 @@ class GenreListFragment : FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val genreAdapter = GenreAdapter(this) @@ -78,7 +76,7 @@ class GenreListFragment : } collectImmediately(homeModel.genresList, ::updateGenres) - collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -119,7 +117,7 @@ class GenreListFragment : } override fun onOpenMenu(item: Genre, anchor: View) { - menuModel.open(R.menu.item_parent, item) + listModel.openMenu(R.menu.item_parent, item) } private fun updateGenres(genres: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt index 793459b24..299ceb39c 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/PlaylistListFragment.kt @@ -29,12 +29,11 @@ import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter -import org.oxycblt.auxio.list.menu.MenuViewModel import org.oxycblt.auxio.list.recycler.PlaylistViewHolder -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent @@ -56,8 +55,7 @@ class PlaylistListFragment : FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val playlistAdapter = PlaylistAdapter(this) @@ -76,7 +74,7 @@ class PlaylistListFragment : } collectImmediately(homeModel.playlistsList, ::updatePlaylists) - collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -117,7 +115,7 @@ class PlaylistListFragment : } override fun onOpenMenu(item: Playlist, anchor: View) { - menuModel.open(R.menu.item_playlist, item) + listModel.openMenu(R.menu.item_playlist, item) } private fun updatePlaylists(playlists: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt index 2ac91301d..aba66c5e0 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt @@ -31,12 +31,11 @@ import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView import org.oxycblt.auxio.list.ListFragment +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter -import org.oxycblt.auxio.list.menu.MenuViewModel import org.oxycblt.auxio.list.recycler.SongViewHolder -import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent @@ -58,8 +57,7 @@ class SongListFragment : FastScrollRecyclerView.PopupProvider, FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() private val songAdapter = SongAdapter(this) @@ -81,7 +79,7 @@ class SongListFragment : } collectImmediately(homeModel.songsList, ::updateSongs) - collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(listModel.selected, ::updateSelection) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) } @@ -143,7 +141,7 @@ class SongListFragment : } override fun onOpenMenu(item: Song, anchor: View) { - menuModel.open(R.menu.item_song, item) + listModel.openMenu(R.menu.item_song, item) } private fun updateSongs(songs: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt b/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt index 30ea99f61..4d2d45c14 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt @@ -24,7 +24,6 @@ import androidx.appcompat.widget.PopupMenu import androidx.core.view.MenuCompat import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding -import org.oxycblt.auxio.list.selection.SelectionFragment import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.util.logD @@ -52,9 +51,9 @@ abstract class ListFragment : abstract fun onRealClick(item: T) final override fun onClick(item: T, viewHolder: RecyclerView.ViewHolder) { - if (selectionModel.selected.value.isNotEmpty()) { + if (listModel.selected.value.isNotEmpty()) { // Map clicking an item to selecting an item when items are already selected. - selectionModel.select(item) + listModel.select(item) } else { // Delegate to the concrete implementation when we don't select the item. onRealClick(item) @@ -62,7 +61,7 @@ abstract class ListFragment : } final override fun onSelect(item: T) { - selectionModel.select(item) + listModel.select(item) } /** diff --git a/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionViewModel.kt b/app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt similarity index 56% rename from app/src/main/java/org/oxycblt/auxio/list/selection/SelectionViewModel.kt rename to app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt index 3f4efdd0e..71a361d3a 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022 Auxio Project - * SelectionViewModel.kt is part of Auxio. + * Copyright (c) 2023 Auxio Project + * ListViewModel.kt is part of Auxio. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.list.selection +package org.oxycblt.auxio.list +import androidx.annotation.MenuRes import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -32,15 +33,18 @@ import org.oxycblt.auxio.music.MusicRepository import org.oxycblt.auxio.music.MusicSettings import org.oxycblt.auxio.music.Playlist import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.util.Event +import org.oxycblt.auxio.util.MutableEvent import org.oxycblt.auxio.util.logD +import org.oxycblt.auxio.util.logW /** - * A [ViewModel] that manages the current selection. + * A [ViewModel] that orchestrates menu dialogs and selection state. * * @author Alexander Capehart (OxygenCobalt) */ @HiltViewModel -class SelectionViewModel +class ListViewModel @Inject constructor( private val musicRepository: MusicRepository, @@ -51,6 +55,9 @@ constructor( val selected: StateFlow> get() = _selected + private val _Menu = MutableEvent() + val menu: Event = _Menu + init { musicRepository.addUpdateListener(this) } @@ -105,7 +112,7 @@ constructor( * * @return A list of [Song]s collated from each item selected. */ - fun take(): List { + fun takeSelection(): List { logD("Taking selection") return _selected.value .flatMap { @@ -125,8 +132,88 @@ constructor( * * @return true if the prior selection was non-empty, false otherwise. */ - fun drop(): Boolean { + fun dropSelection(): Boolean { logD("Dropping selection [empty=${_selected.value.isEmpty()}]") return _selected.value.isNotEmpty().also { _selected.value = listOf() } } + + /** + * Open a menu for a [Song]. This is not a popup menu, instead actually a dialog of menu options + * with additional information. + * + * @param menuRes The resource of the menu to use. + * @param song The [Song] to show. + */ + fun openMenu(@MenuRes menuRes: Int, song: Song) { + logD("Opening menu for $song") + openImpl(Menu.ForSong(menuRes, song)) + } + + /** + * Open a menu for a [Album]. This is not a popup menu, instead actually a dialog of menu + * options with additional information. + * + * @param menuRes The resource of the menu to use. + * @param album The [Album] to show. + */ + fun openMenu(@MenuRes menuRes: Int, album: Album) { + logD("Opening menu for $album") + openImpl(Menu.ForAlbum(menuRes, album)) + } + + /** + * Open a menu for a [Artist]. This is not a popup menu, instead actually a dialog of menu + * options with additional information. + * + * @param menuRes The resource of the menu to use. + * @param artist The [Artist] to show. + */ + fun openMenu(@MenuRes menuRes: Int, artist: Artist) { + logD("Opening menu for $artist") + openImpl(Menu.ForArtist(menuRes, artist)) + } + + /** + * Open a menu for a [Genre]. This is not a popup menu, instead actually a dialog of menu + * options with additional information. + * + * @param menuRes The resource of the menu to use. + * @param genre The [Genre] to show. + */ + fun openMenu(@MenuRes menuRes: Int, genre: Genre) { + logD("Opening menu for $genre") + openImpl(Menu.ForGenre(menuRes, genre)) + } + + /** + * Open a menu for a [Playlist]. This is not a popup menu, instead actually a dialog of menu + * options with additional information. + * + * @param menuRes The resource of the menu to use. + * @param playlist The [Playlist] to show. + */ + fun openMenu(@MenuRes menuRes: Int, playlist: Playlist) { + logD("Opening menu for $playlist") + openImpl(Menu.ForPlaylist(menuRes, playlist)) + } + + private fun openImpl(menu: Menu) { + val existing = _Menu.flow.value + if (existing != null) { + logW("Already opening $existing, ignoring $menu") + return + } + _Menu.put(menu) + } +} + +sealed interface Menu { + val menuRes: Int + val music: Music + + class ForSong(@MenuRes override val menuRes: Int, override val music: Song) : Menu + class ForAlbum(@MenuRes override val menuRes: Int, override val music: Album) : Menu + class ForArtist(@MenuRes override val menuRes: Int, override val music: Artist) : Menu + class ForGenre(@MenuRes override val menuRes: Int, override val music: Genre) : Menu + class ForPlaylist(@MenuRes override val menuRes: Int, override val music: Playlist) : Menu } diff --git a/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt b/app/src/main/java/org/oxycblt/auxio/list/SelectionFragment.kt similarity index 83% rename from app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt rename to app/src/main/java/org/oxycblt/auxio/list/SelectionFragment.kt index 26d9d1afd..2f810da8a 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/selection/SelectionFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/SelectionFragment.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.list.selection +package org.oxycblt.auxio.list import android.os.Bundle import android.view.MenuItem @@ -36,7 +36,7 @@ import org.oxycblt.auxio.util.showToast */ abstract class SelectionFragment : ViewBindingFragment(), Toolbar.OnMenuItemClickListener { - protected abstract val selectionModel: SelectionViewModel + protected abstract val listModel: ListViewModel protected abstract val musicModel: MusicViewModel protected abstract val playbackModel: PlaybackViewModel @@ -46,7 +46,7 @@ abstract class SelectionFragment : super.onBindingCreated(binding, savedInstanceState) getSelectionToolbar(binding)?.apply { // Add cancel and menu item listeners to manage what occurs with the selection. - setNavigationOnClickListener { selectionModel.drop() } + setNavigationOnClickListener { listModel.dropSelection() } setOnMenuItemClickListener(this@SelectionFragment) } } @@ -59,29 +59,29 @@ abstract class SelectionFragment : override fun onMenuItemClick(item: MenuItem) = when (item.itemId) { R.id.action_selection_play_next -> { - playbackModel.playNext(selectionModel.take()) + playbackModel.playNext(listModel.takeSelection()) requireContext().showToast(R.string.lng_queue_added) true } R.id.action_selection_playlist_add -> { - musicModel.addToPlaylist(selectionModel.take()) + musicModel.addToPlaylist(listModel.takeSelection()) true } R.id.action_selection_queue_add -> { - playbackModel.addToQueue(selectionModel.take()) + playbackModel.addToQueue(listModel.takeSelection()) requireContext().showToast(R.string.lng_queue_added) true } R.id.action_selection_play -> { - playbackModel.play(selectionModel.take()) + playbackModel.play(listModel.takeSelection()) true } R.id.action_selection_shuffle -> { - playbackModel.shuffle(selectionModel.take()) + playbackModel.shuffle(listModel.takeSelection()) true } R.id.action_selection_share -> { - requireContext().share(selectionModel.take()) + requireContext().share(listModel.takeSelection()) true } else -> false diff --git a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt index 6ca9f6c6c..183908fb1 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt @@ -29,6 +29,7 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.DialogMenuBinding import org.oxycblt.auxio.list.ClickableListListener +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.list.adapter.UpdateInstructions import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.ui.ViewBindingBottomSheetDialogFragment @@ -44,6 +45,7 @@ import org.oxycblt.auxio.util.logD abstract class MenuDialogFragment : ViewBindingBottomSheetDialogFragment(), ClickableListListener { protected abstract val menuModel: MenuViewModel + protected abstract val listModel: ListViewModel private val menuAdapter = MenuItemAdapter(@Suppress("LeakingThis") this) abstract val menuRes: Int @@ -66,7 +68,7 @@ abstract class MenuDialogFragment : } // --- VIEWMODEL SETUP --- - menuModel.pendingMenu.consume() + listModel.menu.consume() menuModel.setCurrentMenu(uid) collectImmediately(menuModel.currentMusic, this::updateMusic) } diff --git a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt index e735ddcab..a1f26d448 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt @@ -20,11 +20,13 @@ package org.oxycblt.auxio.list.menu import android.view.MenuItem import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels import androidx.navigation.fragment.navArgs import dagger.hilt.android.AndroidEntryPoint import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogMenuBinding import org.oxycblt.auxio.detail.DetailViewModel +import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre @@ -41,6 +43,7 @@ import org.oxycblt.auxio.util.showToast @AndroidEntryPoint class SongMenuDialogFragment : MenuDialogFragment() { override val menuModel: MenuViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private val musicModel: MusicViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels() @@ -83,7 +86,8 @@ class SongMenuDialogFragment : MenuDialogFragment() { @AndroidEntryPoint class AlbumMenuDialogFragment : MenuDialogFragment() { - override val menuModel: MenuViewModel by activityViewModels() + override val menuModel: MenuViewModel by viewModels() + override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private val musicModel: MusicViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels() @@ -127,7 +131,8 @@ class AlbumMenuDialogFragment : MenuDialogFragment() { @AndroidEntryPoint class ArtistMenuDialogFragment : MenuDialogFragment() { - override val menuModel: MenuViewModel by activityViewModels() + override val menuModel: MenuViewModel by viewModels() + override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private val musicModel: MusicViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels() @@ -189,7 +194,8 @@ class ArtistMenuDialogFragment : MenuDialogFragment() { @AndroidEntryPoint class GenreMenuDialogFragment : MenuDialogFragment() { - override val menuModel: MenuViewModel by activityViewModels() + override val menuModel: MenuViewModel by viewModels() + override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private val musicModel: MusicViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels() @@ -236,7 +242,8 @@ class GenreMenuDialogFragment : MenuDialogFragment() { @AndroidEntryPoint class PlaylistMenuDialogFragment : MenuDialogFragment() { - override val menuModel: MenuViewModel by activityViewModels() + override val menuModel: MenuViewModel by viewModels() + override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() private val musicModel: MusicViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels() diff --git a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuViewModel.kt b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuViewModel.kt index b439a6acf..67c87a5d6 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuViewModel.kt @@ -18,29 +18,18 @@ package org.oxycblt.auxio.list.menu -import androidx.annotation.MenuRes import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicRepository -import org.oxycblt.auxio.music.Playlist -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.util.Event -import org.oxycblt.auxio.util.MutableEvent import org.oxycblt.auxio.util.logW @HiltViewModel class MenuViewModel @Inject constructor(private val musicRepository: MusicRepository) : ViewModel(), MusicRepository.UpdateListener { - private val _pendingMenu = MutableEvent() - val pendingMenu: Event = _pendingMenu - private val _currentMusic = MutableStateFlow(null) val currentMusic: StateFlow = _currentMusic @@ -56,27 +45,6 @@ class MenuViewModel @Inject constructor(private val musicRepository: MusicReposi musicRepository.removeUpdateListener(this) } - fun open(@MenuRes menuRes: Int, song: Song) = openImpl(PendingMenu.ForSong(menuRes, song)) - - fun open(@MenuRes menuRes: Int, album: Album) = openImpl(PendingMenu.ForAlbum(menuRes, album)) - - fun open(@MenuRes menuRes: Int, artist: Artist) = - openImpl(PendingMenu.ForArtist(menuRes, artist)) - - fun open(@MenuRes menuRes: Int, genre: Genre) = openImpl(PendingMenu.ForGenre(menuRes, genre)) - - fun open(@MenuRes menuRes: Int, playlist: Playlist) = - openImpl(PendingMenu.ForPlaylist(menuRes, playlist)) - - private fun openImpl(pendingMenu: PendingMenu) { - val existing = _pendingMenu.flow.value - if (existing != null) { - logW("Already opening $existing, ignoring $pendingMenu") - return - } - _pendingMenu.put(pendingMenu) - } - fun setCurrentMenu(uid: Music.UID) { _currentMusic.value = musicRepository.find(uid) if (_currentMusic.value == null) { @@ -84,15 +52,3 @@ class MenuViewModel @Inject constructor(private val musicRepository: MusicReposi } } } - -sealed interface PendingMenu { - val menuRes: Int - val music: Music - - class ForSong(@MenuRes override val menuRes: Int, override val music: Song) : PendingMenu - class ForAlbum(@MenuRes override val menuRes: Int, override val music: Album) : PendingMenu - class ForArtist(@MenuRes override val menuRes: Int, override val music: Artist) : PendingMenu - class ForGenre(@MenuRes override val menuRes: Int, override val music: Genre) : PendingMenu - class ForPlaylist(@MenuRes override val menuRes: Int, override val music: Playlist) : - PendingMenu -} 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 432581600..cae712f68 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -40,9 +40,8 @@ import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment -import org.oxycblt.auxio.list.menu.MenuViewModel -import org.oxycblt.auxio.list.menu.PendingMenu -import org.oxycblt.auxio.list.selection.SelectionViewModel +import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.list.Menu import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre @@ -74,8 +73,7 @@ import org.oxycblt.auxio.util.setFullWidthLookup class SearchFragment : ListFragment() { private val searchModel: SearchViewModel by viewModels() private val detailModel: DetailViewModel by activityViewModels() - private val menuModel: MenuViewModel by activityViewModels() - override val selectionModel: SelectionViewModel by activityViewModels() + override val listModel: ListViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels() private val searchAdapter = SearchAdapter(this) @@ -141,8 +139,8 @@ class SearchFragment : ListFragment() { // --- VIEWMODEL SETUP --- collectImmediately(searchModel.searchResults, ::updateSearchResults) - collect(menuModel.pendingMenu.flow, ::handleMenu) - collectImmediately(selectionModel.selected, ::updateSelection) + collectImmediately(listModel.selected, ::updateSelection) + collect(listModel.menu.flow, ::handleMenu) collect(musicModel.playlistDecision.flow, ::handleDecision) collectImmediately( playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback) @@ -186,11 +184,11 @@ class SearchFragment : ListFragment() { override fun onOpenMenu(item: Music, anchor: View) { when (item) { - is Song -> menuModel.open(R.menu.item_song, item) - is Album -> menuModel.open(R.menu.item_album, item) - is Artist -> menuModel.open(R.menu.item_parent, item) - is Genre -> menuModel.open(R.menu.item_parent, item) - is Playlist -> menuModel.open(R.menu.item_playlist, item) + is Song -> listModel.openMenu(R.menu.item_song, item) + is Album -> listModel.openMenu(R.menu.item_album, item) + is Artist -> listModel.openMenu(R.menu.item_parent, item) + is Genre -> listModel.openMenu(R.menu.item_parent, item) + is Playlist -> listModel.openMenu(R.menu.item_playlist, item) } } @@ -262,25 +260,20 @@ class SearchFragment : ListFragment() { hideKeyboard() } - private fun handleMenu(pendingMenu: PendingMenu?) { - if (pendingMenu == null) return + private fun handleMenu(menu: Menu?) { + if (menu == null) return val directions = - when (pendingMenu) { - is PendingMenu.ForSong -> - SearchFragmentDirections.openSongMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForAlbum -> - SearchFragmentDirections.openAlbumMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForArtist -> - SearchFragmentDirections.openArtistMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForGenre -> - SearchFragmentDirections.openGenreMenu( - pendingMenu.menuRes, pendingMenu.music.uid) - is PendingMenu.ForPlaylist -> - SearchFragmentDirections.openPlaylistMenu( - pendingMenu.menuRes, pendingMenu.music.uid) + when (menu) { + is Menu.ForSong -> + SearchFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForAlbum -> + SearchFragmentDirections.openAlbumMenu(menu.menuRes, menu.music.uid) + is Menu.ForArtist -> + SearchFragmentDirections.openArtistMenu(menu.menuRes, menu.music.uid) + is Menu.ForGenre -> + SearchFragmentDirections.openGenreMenu(menu.menuRes, menu.music.uid) + is Menu.ForPlaylist -> + SearchFragmentDirections.openPlaylistMenu(menu.menuRes, menu.music.uid) } findNavController().navigateSafe(directions) }