diff --git a/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt b/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt index 68240c781..54d59eb50 100644 --- a/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt +++ b/app/src/main/java/org/oxycblt/auxio/IntegerTable.kt @@ -121,16 +121,16 @@ object IntegerTable { const val COVER_MODE_MEDIA_STORE = 0xA11D /** CoverMode.Quality */ const val COVER_MODE_QUALITY = 0xA11E - /** PlaySong.ByItself */ - const val PLAY_SONG_BY_ITSELF = 0xA11F /** PlaySong.FromAll */ - const val PLAY_SONG_FROM_ALL = 0xA120 + const val PLAY_SONG_FROM_ALL = 0xA11F /** PlaySong.FromAlbum */ - const val PLAY_SONG_FROM_ALBUM = 0xA121 + const val PLAY_SONG_FROM_ALBUM = 0xA120 /** PlaySong.FromArtist */ - const val PLAY_SONG_FROM_ARTIST = 0xA122 + const val PLAY_SONG_FROM_ARTIST = 0xA121 /** PlaySong.FromGenre */ - const val PLAY_SONG_FROM_GENRE = 0xA123 + const val PLAY_SONG_FROM_GENRE = 0xA122 /** PlaySong.FromPlaylist */ - const val PLAY_SONG_FROM_PLAYLIST = 0xA124 + const val PLAY_SONG_FROM_PLAYLIST = 0xA123 + /** PlaySong.ByItself */ + const val PLAY_SONG_BY_ITSELF = 0xA124 } 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 61ac27fef..9fb0b25ed 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -183,7 +183,7 @@ class AlbumDetailFragment : } override fun onOpenMenu(item: Song, anchor: View) { - listModel.openMenu(R.menu.item_album_song, item) + listModel.openMenu(R.menu.item_album_song, item, detailModel.playInAlbumWith) } override fun onPlay() { @@ -302,8 +302,7 @@ class AlbumDetailFragment : if (menu == null) return val directions = when (menu) { - is Menu.ForSong -> - AlbumDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForSong -> AlbumDetailFragmentDirections.openSongMenu(menu.parcel) is Menu.ForAlbum, is Menu.ForArtist, is Menu.ForGenre, 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 1673da9de..9997496b6 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -186,7 +186,8 @@ class ArtistDetailFragment : override fun onOpenMenu(item: Music, anchor: View) { when (item) { - is Song -> listModel.openMenu(R.menu.item_artist_song, item) + is Song -> + listModel.openMenu(R.menu.item_artist_song, item, detailModel.playInArtistWith) is Album -> listModel.openMenu(R.menu.item_artist_album, item) else -> error("Unexpected datatype: ${item::class.simpleName}") } @@ -306,10 +307,8 @@ class ArtistDetailFragment : if (menu == null) return val directions = when (menu) { - is Menu.ForSong -> - ArtistDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) - is Menu.ForAlbum -> - ArtistDetailFragmentDirections.openAlbumMenu(menu.menuRes, menu.music.uid) + is Menu.ForSong -> ArtistDetailFragmentDirections.openSongMenu(menu.parcel) + is Menu.ForAlbum -> ArtistDetailFragmentDirections.openAlbumMenu(menu.parcel) is Menu.ForArtist, is Menu.ForGenre, is Menu.ForPlaylist -> error("Unexpected menu $menu") 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 4a62f16a8..dfb9adc29 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -185,7 +185,7 @@ class GenreDetailFragment : override fun onOpenMenu(item: Music, anchor: View) { when (item) { is Artist -> listModel.openMenu(R.menu.item_parent, item) - is Song -> listModel.openMenu(R.menu.item_song, item) + is Song -> listModel.openMenu(R.menu.item_song, item, detailModel.playInGenreWith) else -> error("Unexpected datatype: ${item::class.simpleName}") } } @@ -294,10 +294,8 @@ class GenreDetailFragment : if (menu == null) return val directions = when (menu) { - is Menu.ForSong -> - GenreDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) - is Menu.ForArtist -> - GenreDetailFragmentDirections.openArtistMenu(menu.menuRes, menu.music.uid) + is Menu.ForSong -> GenreDetailFragmentDirections.openSongMenu(menu.parcel) + is Menu.ForArtist -> GenreDetailFragmentDirections.openArtistMenu(menu.parcel) is Menu.ForAlbum, is Menu.ForGenre, is Menu.ForPlaylist -> error("Unexpected menu $menu") 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 5365e9fba..4f25b96f8 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/PlaylistDetailFragment.kt @@ -237,7 +237,7 @@ class PlaylistDetailFragment : } override fun onOpenMenu(item: Song, anchor: View) { - listModel.openMenu(R.menu.item_playlist_song, item) + listModel.openMenu(R.menu.item_playlist_song, item, detailModel.playInPlaylistWith) } override fun onPlay() { @@ -344,8 +344,7 @@ class PlaylistDetailFragment : if (menu == null) return val directions = when (menu) { - is Menu.ForSong -> - PlaylistDetailFragmentDirections.openSongMenu(menu.menuRes, menu.music.uid) + is Menu.ForSong -> PlaylistDetailFragmentDirections.openSongMenu(menu.parcel) is Menu.ForArtist, is Menu.ForAlbum, is Menu.ForGenre, 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 12991e916..73a122006 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -577,15 +577,11 @@ class HomeFragment : if (menu == null) return val directions = 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) + is Menu.ForSong -> HomeFragmentDirections.openSongMenu(menu.parcel) + is Menu.ForAlbum -> HomeFragmentDirections.openAlbumMenu(menu.parcel) + is Menu.ForArtist -> HomeFragmentDirections.openArtistMenu(menu.parcel) + is Menu.ForGenre -> HomeFragmentDirections.openGenreMenu(menu.parcel) + is Menu.ForPlaylist -> HomeFragmentDirections.openPlaylistMenu(menu.parcel) } findNavController().navigateSafe(directions) } 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 3b2782525..26b9282ea 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 @@ -141,7 +141,7 @@ class SongListFragment : } override fun onOpenMenu(item: Song, anchor: View) { - listModel.openMenu(R.menu.item_song, item) + listModel.openMenu(R.menu.item_song, item, homeModel.playWith) } private fun updateSongs(songs: List) { diff --git a/app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt b/app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt index 217865df7..a32b8a0f5 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/ListViewModel.kt @@ -18,12 +18,14 @@ package org.oxycblt.auxio.list +import android.os.Parcelable 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 kotlinx.parcelize.Parcelize import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre @@ -33,6 +35,7 @@ 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.playback.PlaySong import org.oxycblt.auxio.util.Event import org.oxycblt.auxio.util.MutableEvent import org.oxycblt.auxio.util.logD @@ -146,10 +149,12 @@ constructor( * * @param menuRes The resource of the menu to use. * @param song The [Song] to show. + * @param playWith A [PlaySong] command to give context to what "Play" and "Shuffle" actions + * should do. */ - fun openMenu(@MenuRes menuRes: Int, song: Song) { + fun openMenu(@MenuRes menuRes: Int, song: Song, playWith: PlaySong) { logD("Opening menu for $song") - openImpl(Menu.ForSong(menuRes, song)) + openImpl(Menu.ForSong(menuRes, song, playWith)) } /** @@ -216,19 +221,63 @@ constructor( * @author Alexander Capehart (OxygenCobalt) */ sealed interface Menu { - /** The android resource ID of the menu options to display in the dialog. */ - val menuRes: Int - /** The [Music] that the menu should act on. */ - val music: Music + /** The menu resource to inflate in the menu dialog. */ + @get:MenuRes val res: Int + /** A [Parcel] version of this instance that can be used as a navigation argument. */ + val parcel: Parcel + sealed interface Parcel : Parcelable /** Navigate to a [Song] menu dialog. */ - class ForSong(@MenuRes override val menuRes: Int, override val music: Song) : Menu + class ForSong(@MenuRes override val res: Int, val song: Song, val playWith: PlaySong) : Menu { + override val parcel: Parcel + get() { + val playWithUid = + when (playWith) { + is PlaySong.FromArtist -> playWith.which?.uid + is PlaySong.FromGenre -> playWith.which?.uid + is PlaySong.FromPlaylist -> playWith.which.uid + is PlaySong.FromAll, + is PlaySong.FromAlbum, + is PlaySong.ByItself -> null + } + + return Parcel(res, song.uid, playWith.intCode, playWithUid) + } + + @Parcelize + data class Parcel( + val res: Int, + val songUid: Music.UID, + val playWithCode: Int, + val playWithUid: Music.UID? + ) : Menu.Parcel + } + /** Navigate to a [Album] menu dialog. */ - class ForAlbum(@MenuRes override val menuRes: Int, override val music: Album) : Menu + class ForAlbum(@MenuRes override val res: Int, val album: Album) : Menu { + override val parcel + get() = Parcel(res, album.uid) + @Parcelize data class Parcel(val res: Int, val albumUid: Music.UID) : Menu.Parcel + } + /** Navigate to a [Artist] menu dialog. */ - class ForArtist(@MenuRes override val menuRes: Int, override val music: Artist) : Menu + class ForArtist(@MenuRes override val res: Int, val artist: Artist) : Menu { + override val parcel + get() = Parcel(res, artist.uid) + @Parcelize data class Parcel(val res: Int, val artistUid: Music.UID) : Menu.Parcel + } + /** Navigate to a [Genre] menu dialog. */ - class ForGenre(@MenuRes override val menuRes: Int, override val music: Genre) : Menu + class ForGenre(@MenuRes override val res: Int, val genre: Genre) : Menu { + override val parcel + get() = Parcel(res, genre.uid) + @Parcelize data class Parcel(val res: Int, val genreUid: Music.UID) : Menu.Parcel + } + /** Navigate to a [Playlist] menu dialog. */ - class ForPlaylist(@MenuRes override val menuRes: Int, override val music: Playlist) : Menu + class ForPlaylist(@MenuRes override val res: Int, val playlist: Playlist) : Menu { + override val parcel + get() = Parcel(res, playlist.uid) + @Parcelize data class Parcel(val res: Int, val playlistUid: Music.UID) : Menu.Parcel + } } 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 305234449..a65f993bc 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 @@ -30,8 +30,8 @@ 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.Menu import org.oxycblt.auxio.list.adapter.UpdateInstructions -import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.ui.ViewBindingBottomSheetDialogFragment import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.logD @@ -44,40 +44,36 @@ import org.oxycblt.auxio.util.logD * * TODO: Extend the amount of music info shown in the dialog */ -abstract class MenuDialogFragment : +abstract class MenuDialogFragment : ViewBindingBottomSheetDialogFragment(), ClickableListListener { protected abstract val menuModel: MenuViewModel protected abstract val listModel: ListViewModel private val menuAdapter = MenuItemAdapter(@Suppress("LeakingThis") this) - /** The android resource ID of the menu options to display in the dialog. */ - abstract val menuRes: Int - - /** The [Music.UID] of the [T] to display menu options for. */ - abstract val uid: Music.UID + abstract val parcel: Menu.Parcel /** - * Get the options to disable in the context of the currently shown [T]. + * Get the options to disable in the context of the currently shown [M]. * - * @param music The currently-shown music [T]. + * @param menu The currently-shown menu [M]. */ - abstract fun getDisabledItemIds(music: T): Set + abstract fun getDisabledItemIds(menu: M): Set /** - * Update the displayed information about the currently shown [T]. + * Update the displayed information about the currently shown [M]. * * @param binding The [DialogMenuBinding] to bind information to. - * @param music The currently-shown music [T]. + * @param menu The currently-shown menu [M]. */ - abstract fun updateMusic(binding: DialogMenuBinding, music: T) + abstract fun updateMenu(binding: DialogMenuBinding, menu: M) /** * Forward the clicked [MenuItem] to it's corresponding handler in another module. * * @param item The [MenuItem] that was clicked. - * @param music The currently-shown music [T]. + * @param menu The currently-shown menu [M]. */ - abstract fun onClick(item: MenuItem, music: T) + abstract fun onClick(item: MenuItem, menu: M) override fun onCreateBinding(inflater: LayoutInflater) = DialogMenuBinding.inflate(inflater) @@ -94,8 +90,8 @@ abstract class MenuDialogFragment : // --- VIEWMODEL SETUP --- listModel.menu.consume() - menuModel.setMusic(uid) - collectImmediately(menuModel.currentMusic, this::updateMusic) + menuModel.setMenu(parcel) + collectImmediately(menuModel.currentMenu, this::updateMenu) } override fun onDestroyBinding(binding: DialogMenuBinding) { @@ -105,23 +101,25 @@ abstract class MenuDialogFragment : binding.menuOptionRecycler.adapter = null } - private fun updateMusic(music: Music?) { - if (music == null) { - logD("No music to show, navigating away") + private fun updateMenu(menu: Menu?) { + if (menu == null) { + logD("No menu to show, navigating away") findNavController().navigateUp() + return } - @Suppress("UNCHECKED_CAST") val castedMusic = music as T + @Suppress("UNCHECKED_CAST") val casted = menu as? M + check(casted != null) { "Unexpected menu instance ${menu::class.simpleName}" } - // We need to inflate the menu on every music update since it might have changed + // We need to inflate the menu on every menu update since it might have changed // what options are available (ex. if an artist with no songs has had new songs added). // Since we don't have (and don't want) a dummy view to inflate this menu, just // depend on the AndroidX Toolbar internal API and hope for the best. @SuppressLint("RestrictedApi") val builder = MenuBuilder(requireContext()) - MenuInflater(requireContext()).inflate(menuRes, builder) + MenuInflater(requireContext()).inflate(casted.res, builder) // Disable any menu options as specified by the impl - val disabledIds = getDisabledItemIds(castedMusic) + val disabledIds = getDisabledItemIds(casted) val visible = builder.children.mapTo(mutableListOf()) { it.isEnabled = !disabledIds.contains(it.itemId) @@ -130,7 +128,7 @@ abstract class MenuDialogFragment : menuAdapter.update(visible, UpdateInstructions.Diff) // Delegate to impl how to show music - updateMusic(requireBinding(), castedMusic) + updateMenu(requireBinding(), casted) } final override fun onClick(item: MenuItem, viewHolder: RecyclerView.ViewHolder) { @@ -138,6 +136,6 @@ abstract class MenuDialogFragment : // TODO: This should change if the app is 100% migrated to menu dialogs findNavController().navigateUp() // Delegate to impl on how to handle items - @Suppress("UNCHECKED_CAST") onClick(item, menuModel.currentMusic.value as T) + @Suppress("UNCHECKED_CAST") onClick(item, menuModel.currentMenu.value as M) } } 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 4aad05948..ac768b627 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 @@ -27,10 +27,9 @@ 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.list.Menu import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.Playlist import org.oxycblt.auxio.music.Song @@ -46,7 +45,7 @@ import org.oxycblt.auxio.util.showToast * @author Alexander Capehart (OxygenCobalt) */ @AndroidEntryPoint -class SongMenuDialogFragment : MenuDialogFragment() { +class SongMenuDialogFragment : MenuDialogFragment() { override val menuModel: MenuViewModel by activityViewModels() override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() @@ -54,38 +53,37 @@ class SongMenuDialogFragment : MenuDialogFragment() { private val playbackModel: PlaybackViewModel by activityViewModels() private val args: SongMenuDialogFragmentArgs by navArgs() - override val menuRes: Int - get() = args.menuRes - override val uid: Music.UID - get() = args.songUid + override val parcel + get() = args.parcel // Nothing to disable in song menus. - override fun getDisabledItemIds(music: Song) = setOf() + override fun getDisabledItemIds(menu: Menu.ForSong) = setOf() - override fun updateMusic(binding: DialogMenuBinding, music: Song) { + override fun updateMenu(binding: DialogMenuBinding, menu: Menu.ForSong) { val context = requireContext() - binding.menuCover.bind(music) + binding.menuCover.bind(menu.song) binding.menuType.text = getString(R.string.lbl_song) - binding.menuName.text = music.name.resolve(context) - binding.menuInfo.text = music.artists.resolveNames(context) + binding.menuName.text = menu.song.name.resolve(context) + binding.menuInfo.text = menu.song.artists.resolveNames(context) } - override fun onClick(item: MenuItem, music: Song) { + override fun onClick(item: MenuItem, menu: Menu.ForSong) { when (item.itemId) { - // TODO: Song play and shuffle as soon as PlaybackMode is refactored + R.id.action_play -> playbackModel.playExplicit(menu.song, menu.playWith) + R.id.action_shuffle -> playbackModel.shuffleExplicit(menu.song, menu.playWith) R.id.action_play_next -> { - playbackModel.playNext(music) + playbackModel.playNext(menu.song) requireContext().showToast(R.string.lng_queue_added) } R.id.action_queue_add -> { - playbackModel.addToQueue(music) + playbackModel.addToQueue(menu.song) requireContext().showToast(R.string.lng_queue_added) } - R.id.action_artist_details -> detailModel.showArtist(music) - R.id.action_album_details -> detailModel.showAlbum(music) - R.id.action_share -> requireContext().share(music) - R.id.action_playlist_add -> musicModel.addToPlaylist(music) - R.id.action_detail -> detailModel.showSong(music) + R.id.action_artist_details -> detailModel.showArtist(menu.song) + R.id.action_album_details -> detailModel.showAlbum(menu.song) + R.id.action_share -> requireContext().share(menu.song) + R.id.action_playlist_add -> musicModel.addToPlaylist(menu.song) + R.id.action_detail -> detailModel.showSong(menu.song) else -> error("Unexpected menu item selected $item") } } @@ -97,7 +95,7 @@ class SongMenuDialogFragment : MenuDialogFragment() { * @author Alexander Capehart (OxygenCobalt) */ @AndroidEntryPoint -class AlbumMenuDialogFragment : MenuDialogFragment() { +class AlbumMenuDialogFragment : MenuDialogFragment() { override val menuModel: MenuViewModel by viewModels() override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() @@ -105,38 +103,36 @@ class AlbumMenuDialogFragment : MenuDialogFragment() { private val playbackModel: PlaybackViewModel by activityViewModels() private val args: AlbumMenuDialogFragmentArgs by navArgs() - override val menuRes: Int - get() = args.menuRes - override val uid: Music.UID - get() = args.albumUid + override val parcel + get() = args.parcel // Nothing to disable in album menus. - override fun getDisabledItemIds(music: Album) = setOf() + override fun getDisabledItemIds(menu: Menu.ForAlbum) = setOf() - override fun updateMusic(binding: DialogMenuBinding, music: Album) { + override fun updateMenu(binding: DialogMenuBinding, menu: Menu.ForAlbum) { val context = requireContext() - binding.menuCover.bind(music) - binding.menuType.text = getString(music.releaseType.stringRes) - binding.menuName.text = music.name.resolve(context) - binding.menuInfo.text = music.artists.resolveNames(context) + binding.menuCover.bind(menu.album) + binding.menuType.text = getString(menu.album.releaseType.stringRes) + binding.menuName.text = menu.album.name.resolve(context) + binding.menuInfo.text = menu.album.artists.resolveNames(context) } - override fun onClick(item: MenuItem, music: Album) { + override fun onClick(item: MenuItem, menu: Menu.ForAlbum) { when (item.itemId) { - R.id.action_play -> playbackModel.play(music) - R.id.action_shuffle -> playbackModel.shuffle(music) - R.id.action_detail -> detailModel.showAlbum(music) + R.id.action_play -> playbackModel.play(menu.album) + R.id.action_shuffle -> playbackModel.shuffle(menu.album) + R.id.action_detail -> detailModel.showAlbum(menu.album) R.id.action_play_next -> { - playbackModel.playNext(music) + playbackModel.playNext(menu.album) requireContext().showToast(R.string.lng_queue_added) } R.id.action_queue_add -> { - playbackModel.addToQueue(music) + playbackModel.addToQueue(menu.album) requireContext().showToast(R.string.lng_queue_added) } - R.id.action_artist_details -> detailModel.showArtist(music) - R.id.action_playlist_add -> musicModel.addToPlaylist(music) - R.id.action_share -> requireContext().share(music) + R.id.action_artist_details -> detailModel.showArtist(menu.album) + R.id.action_playlist_add -> musicModel.addToPlaylist(menu.album) + R.id.action_share -> requireContext().share(menu.album) else -> error("Unexpected menu item selected $item") } } @@ -148,7 +144,7 @@ class AlbumMenuDialogFragment : MenuDialogFragment() { * @author Alexander Capehart (OxygenCobalt) */ @AndroidEntryPoint -class ArtistMenuDialogFragment : MenuDialogFragment() { +class ArtistMenuDialogFragment : MenuDialogFragment() { override val menuModel: MenuViewModel by viewModels() override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() @@ -156,13 +152,11 @@ class ArtistMenuDialogFragment : MenuDialogFragment() { private val playbackModel: PlaybackViewModel by activityViewModels() private val args: ArtistMenuDialogFragmentArgs by navArgs() - override val menuRes: Int - get() = args.menuRes - override val uid: Music.UID - get() = args.artistUid + override val parcel + get() = args.parcel - override fun getDisabledItemIds(music: Artist) = - if (music.songs.isEmpty()) { + override fun getDisabledItemIds(menu: Menu.ForArtist) = + if (menu.artist.songs.isEmpty()) { // Disable any operations that require some kind of songs to work with, as there won't // be any in an empty artist. setOf( @@ -176,37 +170,37 @@ class ArtistMenuDialogFragment : MenuDialogFragment() { setOf() } - override fun updateMusic(binding: DialogMenuBinding, music: Artist) { + override fun updateMenu(binding: DialogMenuBinding, menu: Menu.ForArtist) { val context = requireContext() - binding.menuCover.bind(music) + binding.menuCover.bind(menu.artist) binding.menuType.text = getString(R.string.lbl_artist) - binding.menuName.text = music.name.resolve(context) + binding.menuName.text = menu.artist.name.resolve(context) binding.menuInfo.text = getString( R.string.fmt_two, - context.getPlural(R.plurals.fmt_album_count, music.albums.size), - if (music.songs.isNotEmpty()) { - context.getPlural(R.plurals.fmt_song_count, music.songs.size) + context.getPlural(R.plurals.fmt_album_count, menu.artist.albums.size), + if (menu.artist.songs.isNotEmpty()) { + context.getPlural(R.plurals.fmt_song_count, menu.artist.songs.size) } else { getString(R.string.def_song_count) }) } - override fun onClick(item: MenuItem, music: Artist) { + override fun onClick(item: MenuItem, menu: Menu.ForArtist) { when (item.itemId) { - R.id.action_play -> playbackModel.play(music) - R.id.action_shuffle -> playbackModel.shuffle(music) - R.id.action_detail -> detailModel.showArtist(music) + R.id.action_play -> playbackModel.play(menu.artist) + R.id.action_shuffle -> playbackModel.shuffle(menu.artist) + R.id.action_detail -> detailModel.showArtist(menu.artist) R.id.action_play_next -> { - playbackModel.playNext(music) + playbackModel.playNext(menu.artist) requireContext().showToast(R.string.lng_queue_added) } R.id.action_queue_add -> { - playbackModel.addToQueue(music) + playbackModel.addToQueue(menu.artist) requireContext().showToast(R.string.lng_queue_added) } - R.id.action_playlist_add -> musicModel.addToPlaylist(music) - R.id.action_share -> requireContext().share(music) + R.id.action_playlist_add -> musicModel.addToPlaylist(menu.artist) + R.id.action_share -> requireContext().share(menu.artist) else -> error("Unexpected menu item $item") } } @@ -218,7 +212,7 @@ class ArtistMenuDialogFragment : MenuDialogFragment() { * @author Alexander Capehart (OxygenCobalt) */ @AndroidEntryPoint -class GenreMenuDialogFragment : MenuDialogFragment() { +class GenreMenuDialogFragment : MenuDialogFragment() { override val menuModel: MenuViewModel by viewModels() override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() @@ -226,40 +220,38 @@ class GenreMenuDialogFragment : MenuDialogFragment() { private val playbackModel: PlaybackViewModel by activityViewModels() private val args: GenreMenuDialogFragmentArgs by navArgs() - override val menuRes: Int - get() = args.menuRes - override val uid: Music.UID - get() = args.genreUid + override val parcel + get() = args.parcel - override fun getDisabledItemIds(music: Genre) = setOf() + override fun getDisabledItemIds(menu: Menu.ForGenre) = setOf() - override fun updateMusic(binding: DialogMenuBinding, music: Genre) { + override fun updateMenu(binding: DialogMenuBinding, menu: Menu.ForGenre) { val context = requireContext() - binding.menuCover.bind(music) + binding.menuCover.bind(menu.genre) binding.menuType.text = getString(R.string.lbl_genre) - binding.menuName.text = music.name.resolve(context) + binding.menuName.text = menu.genre.name.resolve(context) binding.menuInfo.text = getString( R.string.fmt_two, - context.getPlural(R.plurals.fmt_artist_count, music.artists.size), - context.getPlural(R.plurals.fmt_song_count, music.songs.size)) + context.getPlural(R.plurals.fmt_artist_count, menu.genre.artists.size), + context.getPlural(R.plurals.fmt_song_count, menu.genre.songs.size)) } - override fun onClick(item: MenuItem, music: Genre) { + override fun onClick(item: MenuItem, menu: Menu.ForGenre) { when (item.itemId) { - R.id.action_play -> playbackModel.play(music) - R.id.action_shuffle -> playbackModel.shuffle(music) - R.id.action_detail -> detailModel.showGenre(music) + R.id.action_play -> playbackModel.play(menu.genre) + R.id.action_shuffle -> playbackModel.shuffle(menu.genre) + R.id.action_detail -> detailModel.showGenre(menu.genre) R.id.action_play_next -> { - playbackModel.playNext(music) + playbackModel.playNext(menu.genre) requireContext().showToast(R.string.lng_queue_added) } R.id.action_queue_add -> { - playbackModel.addToQueue(music) + playbackModel.addToQueue(menu.genre) requireContext().showToast(R.string.lng_queue_added) } - R.id.action_playlist_add -> musicModel.addToPlaylist(music) - R.id.action_share -> requireContext().share(music) + R.id.action_playlist_add -> musicModel.addToPlaylist(menu.genre) + R.id.action_share -> requireContext().share(menu.genre) else -> error("Unexpected menu item $item") } } @@ -271,7 +263,7 @@ class GenreMenuDialogFragment : MenuDialogFragment() { * @author Alexander Capehart (OxygenCobalt) */ @AndroidEntryPoint -class PlaylistMenuDialogFragment : MenuDialogFragment() { +class PlaylistMenuDialogFragment : MenuDialogFragment() { override val menuModel: MenuViewModel by viewModels() override val listModel: ListViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels() @@ -279,13 +271,11 @@ class PlaylistMenuDialogFragment : MenuDialogFragment() { private val playbackModel: PlaybackViewModel by activityViewModels() private val args: PlaylistMenuDialogFragmentArgs by navArgs() - override val menuRes: Int - get() = args.menuRes - override val uid: Music.UID - get() = args.playlistUid + override val parcel + get() = args.parcel - override fun getDisabledItemIds(music: Playlist) = - if (music.songs.isEmpty()) { + override fun getDisabledItemIds(menu: Menu.ForPlaylist) = + if (menu.playlist.songs.isEmpty()) { // Disable any operations that require some kind of songs to work with, as there won't // be any in an empty playlist. setOf( @@ -299,35 +289,35 @@ class PlaylistMenuDialogFragment : MenuDialogFragment() { setOf() } - override fun updateMusic(binding: DialogMenuBinding, music: Playlist) { + override fun updateMenu(binding: DialogMenuBinding, menu: Menu.ForPlaylist) { val context = requireContext() - binding.menuCover.bind(music) + binding.menuCover.bind(menu.playlist) binding.menuType.text = getString(R.string.lbl_playlist) - binding.menuName.text = music.name.resolve(context) + binding.menuName.text = menu.playlist.name.resolve(context) binding.menuInfo.text = - if (music.songs.isNotEmpty()) { - context.getPlural(R.plurals.fmt_song_count, music.songs.size) + if (menu.playlist.songs.isNotEmpty()) { + context.getPlural(R.plurals.fmt_song_count, menu.playlist.songs.size) } else { getString(R.string.def_song_count) } } - override fun onClick(item: MenuItem, music: Playlist) { + override fun onClick(item: MenuItem, menu: Menu.ForPlaylist) { when (item.itemId) { - R.id.action_play -> playbackModel.play(music) - R.id.action_shuffle -> playbackModel.shuffle(music) - R.id.action_detail -> detailModel.showPlaylist(music) + R.id.action_play -> playbackModel.play(menu.playlist) + R.id.action_shuffle -> playbackModel.shuffle(menu.playlist) + R.id.action_detail -> detailModel.showPlaylist(menu.playlist) R.id.action_play_next -> { - playbackModel.playNext(music) + playbackModel.playNext(menu.playlist) requireContext().showToast(R.string.lng_queue_added) } R.id.action_queue_add -> { - playbackModel.addToQueue(music) + playbackModel.addToQueue(menu.playlist) requireContext().showToast(R.string.lng_queue_added) } - R.id.action_rename -> musicModel.renamePlaylist(music) - R.id.action_delete -> musicModel.deletePlaylist(music) - R.id.action_share -> requireContext().share(music) + R.id.action_rename -> musicModel.renamePlaylist(menu.playlist) + R.id.action_delete -> musicModel.deletePlaylist(menu.playlist) + R.id.action_share -> requireContext().share(menu.playlist) else -> error("Unexpected menu item $item") } } 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 3e34c1a52..577fe0e48 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 @@ -23,8 +23,10 @@ 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.Music +import org.oxycblt.auxio.list.Menu +import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicRepository +import org.oxycblt.auxio.playback.PlaySong import org.oxycblt.auxio.util.logW /** @@ -35,32 +37,62 @@ import org.oxycblt.auxio.util.logW @HiltViewModel class MenuViewModel @Inject constructor(private val musicRepository: MusicRepository) : ViewModel(), MusicRepository.UpdateListener { - private val _currentMusic = MutableStateFlow(null) - /** The current [Music] information being shown in a menu dialog. */ - val currentMusic: StateFlow = _currentMusic + private val _currentMenu = MutableStateFlow(null) + /** The current [Menu] information being shown in a dialog. */ + val currentMenu: StateFlow = _currentMenu init { musicRepository.addUpdateListener(this) } override fun onMusicChanges(changes: MusicRepository.Changes) { - _currentMusic.value = _currentMusic.value?.let { musicRepository.find(it.uid) } + _currentMenu.value = _currentMenu.value?.let { unpackParcel(it.parcel) } } override fun onCleared() { musicRepository.removeUpdateListener(this) } - /** - * Set a new [currentMusic] from it's [Music.UID]. [currentMusic] will be updated to align with - * the new album. - * - * @param uid The [Music.UID] of the [Music] to update [currentMusic] to. Must be valid. - */ - fun setMusic(uid: Music.UID) { - _currentMusic.value = musicRepository.find(uid) - if (_currentMusic.value == null) { - logW("Given Music UID to show was invalid") + fun setMenu(parcel: Menu.Parcel) { + _currentMenu.value = unpackParcel(parcel) + if (_currentMenu.value == null) { + logW("Given menu parcel $parcel was invalid") } } + + private fun unpackParcel(parcel: Menu.Parcel) = + when (parcel) { + is Menu.ForSong.Parcel -> unpackSongParcel(parcel) + is Menu.ForAlbum.Parcel -> unpackAlbumParcel(parcel) + is Menu.ForArtist.Parcel -> unpackArtistParcel(parcel) + is Menu.ForGenre.Parcel -> unpackGenreParcel(parcel) + is Menu.ForPlaylist.Parcel -> unpackPlaylistParcel(parcel) + } + + private fun unpackSongParcel(parcel: Menu.ForSong.Parcel): Menu.ForSong? { + val song = musicRepository.deviceLibrary?.findSong(parcel.songUid) ?: return null + val parent = parcel.playWithUid?.let(musicRepository::find) as MusicParent? + val playWith = PlaySong.fromIntCode(parcel.playWithCode, parent) ?: return null + return Menu.ForSong(parcel.res, song, playWith) + } + + private fun unpackAlbumParcel(parcel: Menu.ForAlbum.Parcel): Menu.ForAlbum? { + val album = musicRepository.deviceLibrary?.findAlbum(parcel.albumUid) ?: return null + return Menu.ForAlbum(parcel.res, album) + } + + private fun unpackArtistParcel(parcel: Menu.ForArtist.Parcel): Menu.ForArtist? { + val artist = musicRepository.deviceLibrary?.findArtist(parcel.artistUid) ?: return null + return Menu.ForArtist(parcel.res, artist) + } + + private fun unpackGenreParcel(parcel: Menu.ForGenre.Parcel): Menu.ForGenre? { + val genre = musicRepository.deviceLibrary?.findGenre(parcel.genreUid) ?: return null + return Menu.ForGenre(parcel.res, genre) + } + + private fun unpackPlaylistParcel(parcel: Menu.ForPlaylist.Parcel): Menu.ForPlaylist? { + val playlist = musicRepository.userLibrary?.findPlaylist(parcel.playlistUid) ?: return null + return Menu.ForPlaylist(parcel.res, playlist) + } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt index 8032c46d7..622fd8652 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt @@ -75,7 +75,7 @@ interface DeviceLibrary { * Find a [Album] instance corresponding to the given [Music.UID]. * * @param uid The [Music.UID] to search for. - * @return The corresponding [Song], or null if one was not found. + * @return The corresponding [Album], or null if one was not found. */ fun findAlbum(uid: Music.UID): Album? @@ -83,7 +83,7 @@ interface DeviceLibrary { * Find a [Artist] instance corresponding to the given [Music.UID]. * * @param uid The [Music.UID] to search for. - * @return The corresponding [Song], or null if one was not found. + * @return The corresponding [Artist], or null if one was not found. */ fun findArtist(uid: Music.UID): Artist? @@ -91,7 +91,7 @@ interface DeviceLibrary { * Find a [Genre] instance corresponding to the given [Music.UID]. * * @param uid The [Music.UID] to search for. - * @return The corresponding [Song], or null if one was not found. + * @return The corresponding [Genre], or null if one was not found. */ fun findGenre(uid: Music.UID): Genre? diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaySong.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaySong.kt index a4983f97b..6497e9c87 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaySong.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaySong.kt @@ -21,56 +21,103 @@ package org.oxycblt.auxio.playback import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Playlist +/** + * Configuration to play a song in a desired way. + * + * Since songs are not [MusicParent]s, the way the queue is generated around them has a lot more + * flexibility. The particular strategy used can be configured the user, but it also needs to be + * transferred between views at points (such as menus). [PlaySong] provides both of these, being a + * enum-like datatype when configuration is needed, and an algebraic datatype when data transfer is + * needed. + * + * @author Alexander Capehart (OxygenCobalt) + */ sealed interface PlaySong { + /** + * The integer representation of this instance. + * + * @see fromIntCode + */ val intCode: Int + /** Play a Song from the entire library of songs. */ object FromAll : PlaySong { override val intCode = IntegerTable.PLAY_SONG_FROM_ALL } + /** Play a song from it's album. */ object FromAlbum : PlaySong { override val intCode = IntegerTable.PLAY_SONG_FROM_ALBUM } + /** + * Play a song from (possibly) one of it's [Artist]s. + * + * @param which The [Artist] to specifically play from. If null, the user will be prompted for + * an [Artist] to choose of the song has multiple. Otherwise, the only [Artist] will be used. + */ data class FromArtist(val which: Artist?) : PlaySong { override val intCode = IntegerTable.PLAY_SONG_FROM_ARTIST } + /** + * Play a song from (possibly) one of it's [Genre]s. + * + * @param which The [Genre] to specifically play from. If null, the user will be prompted for a + * [Genre] to choose of the song has multiple. Otherwise, the only [Genre] will be used. + */ data class FromGenre(val which: Genre?) : PlaySong { override val intCode = IntegerTable.PLAY_SONG_FROM_GENRE } + /** + * Play a song from one of it's [Playlist]s. + * + * @param which The [Playlist] to specifically play from. This must be provided. + */ data class FromPlaylist(val which: Playlist) : PlaySong { override val intCode = IntegerTable.PLAY_SONG_FROM_PLAYLIST } + /** Only play the given song, include nothing else in the queue. */ object ByItself : PlaySong { override val intCode = IntegerTable.PLAY_SONG_BY_ITSELF } companion object { - fun fromIntCode(intCode: Int, inner: Music?): PlaySong? = + /** + * Convert a [PlaySong] integer representation into an instance. + * + * @param intCode An integer representation of a [PlaySong] + * @param which Optional [MusicParent] to automatically populate a [FromArtist], + * [FromGenre], or [FromPlaylist] instance. If the type of the [MusicParent] does not + * match, it will be considered invalid and null will be returned. + * @return The corresponding [PlaySong], or null if the [PlaySong] is invalid. + * @see PlaySong.intCode + */ + fun fromIntCode(intCode: Int, which: MusicParent? = null): PlaySong? = when (intCode) { IntegerTable.PLAY_SONG_BY_ITSELF -> ByItself + IntegerTable.PLAY_SONG_FROM_ALL -> FromAll IntegerTable.PLAY_SONG_FROM_ALBUM -> FromAlbum IntegerTable.PLAY_SONG_FROM_ARTIST -> - if (inner is Artist?) { - FromArtist(inner) + if (which is Artist?) { + FromArtist(which) } else { null } IntegerTable.PLAY_SONG_FROM_GENRE -> - if (inner is Genre?) { - FromGenre(inner) + if (which is Genre?) { + FromGenre(which) } else { null } IntegerTable.PLAY_SONG_FROM_PLAYLIST -> - if (inner is Playlist) { - FromPlaylist(inner) + if (which is Playlist) { + FromPlaylist(which) } else { null } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt index 82a5c656b..a270c5c07 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt @@ -75,17 +75,14 @@ class PlaybackSettingsImpl @Inject constructor(@ApplicationContext context: Cont get() = PlaySong.fromIntCode( sharedPreferences.getInt( - getString(R.string.set_key_play_in_list_with), Int.MIN_VALUE), - null) + getString(R.string.set_key_play_in_list_with), Int.MIN_VALUE)) ?: PlaySong.FromAll override val inParentPlaybackMode: PlaySong? get() = PlaySong.fromIntCode( - sharedPreferences - .getInt(getString(R.string.set_key_play_in_parent_with), Int.MIN_VALUE) - .also { logD(it) }, - null) + sharedPreferences.getInt( + getString(R.string.set_key_play_in_parent_with), Int.MIN_VALUE)) override val barAction: ActionMode get() = diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt index d0472e556..cebba2850 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt @@ -184,13 +184,13 @@ constructor( playWithImpl(song, with, isImplicitlyShuffled()) } - // fun playExplicit(song: Song, with: PlaySong) { - // playWithImpl(song, with, false) - // } - // - // fun shuffleExplicit(song: Song, with: PlaySong) { - // playWithImpl(song, with, true) - // } + fun playExplicit(song: Song, with: PlaySong) { + playWithImpl(song, with, false) + } + + fun shuffleExplicit(song: Song, with: PlaySong) { + playWithImpl(song, with, true) + } /** Shuffle all songs in the music library. */ fun shuffleAll() { 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 3a7a71233..27abdeab1 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -184,7 +184,7 @@ class SearchFragment : ListFragment() { override fun onOpenMenu(item: Music, anchor: View) { when (item) { - is Song -> listModel.openMenu(R.menu.item_song, item) + is Song -> listModel.openMenu(R.menu.item_song, item, searchModel.playWith) 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) @@ -256,16 +256,11 @@ class SearchFragment : ListFragment() { if (menu == null) return val directions = 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) + is Menu.ForSong -> SearchFragmentDirections.openSongMenu(menu.parcel) + is Menu.ForAlbum -> SearchFragmentDirections.openAlbumMenu(menu.parcel) + is Menu.ForArtist -> SearchFragmentDirections.openArtistMenu(menu.parcel) + is Menu.ForGenre -> SearchFragmentDirections.openGenreMenu(menu.parcel) + is Menu.ForPlaylist -> SearchFragmentDirections.openPlaylistMenu(menu.parcel) } findNavController().navigateSafe(directions) // Keyboard is no longer needed. diff --git a/app/src/main/res/menu/item_album_song.xml b/app/src/main/res/menu/item_album_song.xml index e31ea20b7..fdbc3fc5f 100644 --- a/app/src/main/res/menu/item_album_song.xml +++ b/app/src/main/res/menu/item_album_song.xml @@ -1,13 +1,13 @@ - - - - - - - - + + - - - - - - - - + + - - - - - - - - + + + + - + android:name="parcel" + app:argType="org.oxycblt.auxio.list.Menu$ForSong$Parcel" /> - + android:name="parcel" + app:argType="org.oxycblt.auxio.list.Menu$ForAlbum$Parcel" /> - + android:name="parcel" + app:argType="org.oxycblt.auxio.list.Menu$ForArtist$Parcel" /> - + android:name="parcel" + app:argType="org.oxycblt.auxio.list.Menu$ForGenre$Parcel" /> - + android:name="parcel" + app:argType="org.oxycblt.auxio.list.Menu$ForPlaylist$Parcel" /> @string/set_play_song_from_all - @string/set_play_song_from_artist @string/set_play_song_from_album + @string/set_play_song_from_artist @string/set_play_song_from_genre @string/set_play_song_by_itself @@ -119,14 +119,14 @@ @integer/play_song_from_album @integer/play_song_from_artist @integer/play_song_from_genre - @integer/play_song_itself + @integer/play_song_by_itself @string/set_play_song_none @string/set_play_song_from_all - @string/set_play_song_from_artist @string/set_play_song_from_album + @string/set_play_song_from_artist @string/set_play_song_from_genre @string/set_play_song_by_itself @@ -137,7 +137,7 @@ @integer/play_song_from_album @integer/play_song_from_artist @integer/play_song_from_genre - @integer/play_song_itself + @integer/play_song_by_itself @@ -157,11 +157,12 @@ 2 -2147483648 - 0xA11F - 0xA120 - 0xA121 - 0xA122 - 0xA123 + 0xA11F + 0xA120 + 0xA121 + 0xA122 + 0xA123 + 0xA124 0xA111 0xA112