all: use menu everywhere

Use the new menu system in all applicable places.

More consideration is needed right now on whether the toolbars should
also have menu items, so they remain unchanged right now.
This commit is contained in:
Alexander Capehart 2023-07-03 16:52:42 -06:00
parent 0d896c04e3
commit d6a20fedb3
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
16 changed files with 325 additions and 78 deletions

View file

@ -40,6 +40,8 @@ import org.oxycblt.auxio.list.Header
import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.Sort 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.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
@ -72,6 +74,7 @@ class AlbumDetailFragment :
AlbumDetailHeaderAdapter.Listener, AlbumDetailHeaderAdapter.Listener,
DetailListAdapter.Listener<Song> { DetailListAdapter.Listener<Song> {
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
private val menuModel: MenuViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels()
@ -124,6 +127,7 @@ class AlbumDetailFragment :
collectImmediately(detailModel.currentAlbum, ::updateAlbum) collectImmediately(detailModel.currentAlbum, ::updateAlbum)
collectImmediately(detailModel.albumList, ::updateList) collectImmediately(detailModel.albumList, ::updateList)
collect(detailModel.toShow.flow, ::handleShow) collect(detailModel.toShow.flow, ::handleShow)
collect(menuModel.pendingMenu.flow, ::handleMenu)
collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(selectionModel.selected, ::updateSelection)
collect(musicModel.playlistDecision.flow, ::handleDecision) collect(musicModel.playlistDecision.flow, ::handleDecision)
collectImmediately( collectImmediately(
@ -183,7 +187,7 @@ class AlbumDetailFragment :
} }
override fun onOpenMenu(item: Song, anchor: View) { override fun onOpenMenu(item: Song, anchor: View) {
openMusicMenu(anchor, R.menu.item_album_song, item) menuModel.openMenu(R.menu.item_album_song, item)
} }
override fun onPlay() { override fun onPlay() {
@ -300,6 +304,22 @@ class AlbumDetailFragment :
} }
} }
private fun handleMenu(pendingMenu: PendingMenu?) {
if (pendingMenu == 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")
}
findNavController().navigateSafe(directions)
menuModel.pendingMenu.consume()
}
private fun updateSelection(selected: List<Music>) { private fun updateSelection(selected: List<Music>) {
albumListAdapter.setSelected(selected.toSet()) albumListAdapter.setSelected(selected.toSet())

View file

@ -40,6 +40,8 @@ import org.oxycblt.auxio.list.Header
import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.Sort 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.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
@ -70,6 +72,7 @@ class ArtistDetailFragment :
DetailHeaderAdapter.Listener, DetailHeaderAdapter.Listener,
DetailListAdapter.Listener<Music> { DetailListAdapter.Listener<Music> {
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
private val menuModel: MenuViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels()
@ -125,6 +128,7 @@ class ArtistDetailFragment :
collectImmediately(detailModel.currentArtist, ::updateArtist) collectImmediately(detailModel.currentArtist, ::updateArtist)
collectImmediately(detailModel.artistList, ::updateList) collectImmediately(detailModel.artistList, ::updateList)
collect(detailModel.toShow.flow, ::handleShow) collect(detailModel.toShow.flow, ::handleShow)
collect(menuModel.pendingMenu.flow, ::handleMenu)
collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(selectionModel.selected, ::updateSelection)
collect(musicModel.playlistDecision.flow, ::handleDecision) collect(musicModel.playlistDecision.flow, ::handleDecision)
collectImmediately( collectImmediately(
@ -194,8 +198,8 @@ class ArtistDetailFragment :
override fun onOpenMenu(item: Music, anchor: View) { override fun onOpenMenu(item: Music, anchor: View) {
when (item) { when (item) {
is Song -> openMusicMenu(anchor, R.menu.item_artist_song, item) is Song -> menuModel.openMenu(R.menu.item_artist_song, item)
is Album -> openMusicMenu(anchor, R.menu.item_artist_album, item) is Album -> menuModel.openMenu(R.menu.item_artist_album, item)
else -> error("Unexpected datatype: ${item::class.simpleName}") else -> error("Unexpected datatype: ${item::class.simpleName}")
} }
} }
@ -310,6 +314,24 @@ class ArtistDetailFragment :
} }
} }
private fun handleMenu(pendingMenu: PendingMenu?) {
if (pendingMenu == 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")
}
findNavController().navigateSafe(directions)
menuModel.pendingMenu.consume()
}
private fun updateSelection(selected: List<Music>) { private fun updateSelection(selected: List<Music>) {
artistListAdapter.setSelected(selected.toSet()) artistListAdapter.setSelected(selected.toSet())

View file

@ -40,6 +40,8 @@ import org.oxycblt.auxio.list.Header
import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.Sort 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.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
@ -70,6 +72,7 @@ class GenreDetailFragment :
DetailHeaderAdapter.Listener, DetailHeaderAdapter.Listener,
DetailListAdapter.Listener<Music> { DetailListAdapter.Listener<Music> {
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
private val menuModel: MenuViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels()
@ -123,6 +126,7 @@ class GenreDetailFragment :
collectImmediately(detailModel.currentGenre, ::updatePlaylist) collectImmediately(detailModel.currentGenre, ::updatePlaylist)
collectImmediately(detailModel.genreList, ::updateList) collectImmediately(detailModel.genreList, ::updateList)
collect(detailModel.toShow.flow, ::handleShow) collect(detailModel.toShow.flow, ::handleShow)
collect(menuModel.pendingMenu.flow, ::handleMenu)
collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(selectionModel.selected, ::updateSelection)
collect(musicModel.playlistDecision.flow, ::handleDecision) collect(musicModel.playlistDecision.flow, ::handleDecision)
collectImmediately( collectImmediately(
@ -192,8 +196,8 @@ class GenreDetailFragment :
override fun onOpenMenu(item: Music, anchor: View) { override fun onOpenMenu(item: Music, anchor: View) {
when (item) { when (item) {
is Artist -> openMusicMenu(anchor, R.menu.item_parent, item) is Artist -> menuModel.openMenu(R.menu.item_parent, item)
is Song -> openMusicMenu(anchor, R.menu.item_song, item) is Song -> menuModel.openMenu(R.menu.item_song, item)
else -> error("Unexpected datatype: ${item::class.simpleName}") else -> error("Unexpected datatype: ${item::class.simpleName}")
} }
} }
@ -298,6 +302,24 @@ class GenreDetailFragment :
} }
} }
private fun handleMenu(pendingMenu: PendingMenu?) {
if (pendingMenu == 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")
}
findNavController().navigateSafe(directions)
menuModel.pendingMenu.consume()
}
private fun updateSelection(selected: List<Music>) { private fun updateSelection(selected: List<Music>) {
genreListAdapter.setSelected(selected.toSet()) genreListAdapter.setSelected(selected.toSet())

View file

@ -43,6 +43,8 @@ import org.oxycblt.auxio.list.Divider
import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Header
import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.ListFragment 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.selection.SelectionViewModel
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
@ -73,6 +75,7 @@ class PlaylistDetailFragment :
PlaylistDetailListAdapter.Listener, PlaylistDetailListAdapter.Listener,
NavController.OnDestinationChangedListener { NavController.OnDestinationChangedListener {
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
private val menuModel: MenuViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels()
@ -138,6 +141,7 @@ class PlaylistDetailFragment :
collectImmediately(detailModel.playlistList, ::updateList) collectImmediately(detailModel.playlistList, ::updateList)
collectImmediately(detailModel.editedPlaylist, ::updateEditedList) collectImmediately(detailModel.editedPlaylist, ::updateEditedList)
collect(detailModel.toShow.flow, ::handleShow) collect(detailModel.toShow.flow, ::handleShow)
collect(menuModel.pendingMenu.flow, ::handleMenu)
collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(selectionModel.selected, ::updateSelection)
collect(musicModel.playlistDecision.flow, ::handleDecision) collect(musicModel.playlistDecision.flow, ::handleDecision)
collectImmediately( collectImmediately(
@ -235,7 +239,7 @@ class PlaylistDetailFragment :
} }
override fun onOpenMenu(item: Song, anchor: View) { override fun onOpenMenu(item: Song, anchor: View) {
openMusicMenu(anchor, R.menu.item_playlist_song, item) menuModel.openMenu(R.menu.item_playlist_song, item)
} }
override fun onPlay() { override fun onPlay() {
@ -345,6 +349,22 @@ class PlaylistDetailFragment :
} }
} }
private fun handleMenu(pendingMenu: PendingMenu?) {
if (pendingMenu == 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")
}
findNavController().navigateSafe(directions)
menuModel.pendingMenu.consume()
}
private fun updateSelection(selected: List<Music>) { private fun updateSelection(selected: List<Music>) {
playlistListAdapter.setSelected(selected.toSet()) playlistListAdapter.setSelected(selected.toSet())

View file

@ -56,6 +56,8 @@ import org.oxycblt.auxio.home.list.SongListFragment
import org.oxycblt.auxio.home.tabs.AdaptiveTabStrategy import org.oxycblt.auxio.home.tabs.AdaptiveTabStrategy
import org.oxycblt.auxio.home.tabs.Tab import org.oxycblt.auxio.home.tabs.Tab
import org.oxycblt.auxio.list.Sort 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.SelectionFragment
import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.IndexingProgress import org.oxycblt.auxio.music.IndexingProgress
@ -87,6 +89,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : class HomeFragment :
SelectionFragment<FragmentHomeBinding>(), AppBarLayout.OnOffsetChangedListener { SelectionFragment<FragmentHomeBinding>(), AppBarLayout.OnOffsetChangedListener {
private val menuModel: MenuViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels()
@ -175,6 +178,7 @@ class HomeFragment :
collect(homeModel.recreateTabs.flow, ::handleRecreate) collect(homeModel.recreateTabs.flow, ::handleRecreate)
collectImmediately(homeModel.currentTabMode, ::updateCurrentTab) collectImmediately(homeModel.currentTabMode, ::updateCurrentTab)
collectImmediately(homeModel.songsList, homeModel.isFastScrolling, ::updateFab) collectImmediately(homeModel.songsList, homeModel.isFastScrolling, ::updateFab)
collect(menuModel.pendingMenu.flow, ::handleMenu)
collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(selectionModel.selected, ::updateSelection)
collectImmediately(musicModel.indexingState, ::updateIndexerState) collectImmediately(musicModel.indexingState, ::updateIndexerState)
collect(musicModel.playlistDecision.flow, ::handleDecision) collect(musicModel.playlistDecision.flow, ::handleDecision)
@ -584,6 +588,27 @@ class HomeFragment :
} }
} }
private fun handleMenu(pendingMenu: PendingMenu?) {
if (pendingMenu == 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)
}
findNavController().navigateSafe(directions)
menuModel.pendingMenu.consume()
}
private fun updateSelection(selected: List<Music>) { private fun updateSelection(selected: List<Music>) {
val binding = requireBinding() val binding = requireBinding()
if (selected.isNotEmpty()) { if (selected.isNotEmpty()) {

View file

@ -35,6 +35,7 @@ import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.SelectableListListener
import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter 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.recycler.AlbumViewHolder
import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
@ -60,9 +61,10 @@ class AlbumListFragment :
FastScrollRecyclerView.PopupProvider { FastScrollRecyclerView.PopupProvider {
private val homeModel: HomeViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels()
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() private val menuModel: MenuViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels()
private val albumAdapter = AlbumAdapter(this) private val albumAdapter = AlbumAdapter(this)
// Save memory by re-using the same formatter and string builder when creating popup text // Save memory by re-using the same formatter and string builder when creating popup text
private val formatterSb = StringBuilder(64) private val formatterSb = StringBuilder(64)

View file

@ -33,6 +33,7 @@ import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.SelectableListListener
import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter 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.recycler.ArtistViewHolder
import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
@ -58,9 +59,10 @@ class ArtistListFragment :
FastScrollRecyclerView.Listener { FastScrollRecyclerView.Listener {
private val homeModel: HomeViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels()
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() private val menuModel: MenuViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels()
private val artistAdapter = ArtistAdapter(this) private val artistAdapter = ArtistAdapter(this)
override fun onCreateBinding(inflater: LayoutInflater) = override fun onCreateBinding(inflater: LayoutInflater) =
@ -118,7 +120,7 @@ class ArtistListFragment :
} }
override fun onOpenMenu(item: Artist, anchor: View) { override fun onOpenMenu(item: Artist, anchor: View) {
openMusicMenu(anchor, R.menu.item_parent, item) menuModel.openMenu(R.menu.item_parent, item)
} }
private fun updateArtists(artists: List<Artist>) { private fun updateArtists(artists: List<Artist>) {

View file

@ -33,6 +33,7 @@ import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.SelectableListListener
import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter 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.recycler.GenreViewHolder
import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
@ -57,9 +58,10 @@ class GenreListFragment :
FastScrollRecyclerView.Listener { FastScrollRecyclerView.Listener {
private val homeModel: HomeViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels()
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() private val menuModel: MenuViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels()
private val genreAdapter = GenreAdapter(this) private val genreAdapter = GenreAdapter(this)
override fun onCreateBinding(inflater: LayoutInflater) = override fun onCreateBinding(inflater: LayoutInflater) =
@ -117,7 +119,7 @@ class GenreListFragment :
} }
override fun onOpenMenu(item: Genre, anchor: View) { override fun onOpenMenu(item: Genre, anchor: View) {
openMusicMenu(anchor, R.menu.item_parent, item) menuModel.openMenu(R.menu.item_parent, item)
} }
private fun updateGenres(genres: List<Genre>) { private fun updateGenres(genres: List<Genre>) {

View file

@ -32,6 +32,7 @@ import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.SelectableListListener
import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter 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.recycler.PlaylistViewHolder
import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
@ -55,9 +56,10 @@ class PlaylistListFragment :
FastScrollRecyclerView.Listener { FastScrollRecyclerView.Listener {
private val homeModel: HomeViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels()
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() private val menuModel: MenuViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels()
private val playlistAdapter = PlaylistAdapter(this) private val playlistAdapter = PlaylistAdapter(this)
override fun onCreateBinding(inflater: LayoutInflater) = override fun onCreateBinding(inflater: LayoutInflater) =
@ -115,7 +117,7 @@ class PlaylistListFragment :
} }
override fun onOpenMenu(item: Playlist, anchor: View) { override fun onOpenMenu(item: Playlist, anchor: View) {
openMusicMenu(anchor, R.menu.item_playlist, item) menuModel.openMenu(R.menu.item_playlist, item)
} }
private fun updatePlaylists(playlists: List<Playlist>) { private fun updatePlaylists(playlists: List<Playlist>) {

View file

@ -35,6 +35,7 @@ import org.oxycblt.auxio.list.ListFragment
import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.SelectableListListener
import org.oxycblt.auxio.list.Sort import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter 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.recycler.SongViewHolder
import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.list.selection.SelectionViewModel
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
@ -59,9 +60,10 @@ class SongListFragment :
FastScrollRecyclerView.Listener { FastScrollRecyclerView.Listener {
private val homeModel: HomeViewModel by activityViewModels() private val homeModel: HomeViewModel by activityViewModels()
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() private val menuModel: MenuViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels() override val selectionModel: SelectionViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels()
private val songAdapter = SongAdapter(this) private val songAdapter = SongAdapter(this)
// Save memory by re-using the same formatter and string builder when creating popup text // Save memory by re-using the same formatter and string builder when creating popup text
private val formatterSb = StringBuilder(64) private val formatterSb = StringBuilder(64)
@ -143,7 +145,7 @@ class SongListFragment :
} }
override fun onOpenMenu(item: Song, anchor: View) { override fun onOpenMenu(item: Song, anchor: View) {
openMusicMenu(anchor, R.menu.item_song, item) menuModel.openMenu(R.menu.item_song, item)
} }
private fun updateSongs(songs: List<Song>) { private fun updateSongs(songs: List<Song>) {

View file

@ -71,7 +71,7 @@ abstract class MenuDialogFragment<T : Music> :
menuAdapter.update(builder.children.toList(), UpdateInstructions.Diff) menuAdapter.update(builder.children.toList(), UpdateInstructions.Diff)
// --- VIEWMODEL SETUP --- // --- VIEWMODEL SETUP ---
menuModel.setMusic(uid) menuModel.setCurrentMenu(uid)
collectImmediately(menuModel.currentMusic, this::updateMusic) collectImmediately(menuModel.currentMusic, this::updateMusic)
} }

View file

@ -18,7 +18,7 @@
package org.oxycblt.auxio.list.menu package org.oxycblt.auxio.list.menu
import androidx.fragment.app.viewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
@ -34,7 +34,7 @@ import org.oxycblt.auxio.util.getPlural
@AndroidEntryPoint @AndroidEntryPoint
class SongMenuDialogFragment : MenuDialogFragment<Song>() { class SongMenuDialogFragment : MenuDialogFragment<Song>() {
override val menuModel: MenuViewModel by viewModels() override val menuModel: MenuViewModel by activityViewModels()
private val args: SongMenuDialogFragmentArgs by navArgs() private val args: SongMenuDialogFragmentArgs by navArgs()
override val menuRes: Int override val menuRes: Int
@ -55,7 +55,7 @@ class SongMenuDialogFragment : MenuDialogFragment<Song>() {
@AndroidEntryPoint @AndroidEntryPoint
class AlbumMenuDialogFragment : MenuDialogFragment<Album>() { class AlbumMenuDialogFragment : MenuDialogFragment<Album>() {
override val menuModel: MenuViewModel by viewModels() override val menuModel: MenuViewModel by activityViewModels()
private val args: AlbumMenuDialogFragmentArgs by navArgs() private val args: AlbumMenuDialogFragmentArgs by navArgs()
override val menuRes: Int override val menuRes: Int
@ -76,7 +76,7 @@ class AlbumMenuDialogFragment : MenuDialogFragment<Album>() {
@AndroidEntryPoint @AndroidEntryPoint
class ArtistMenuDialogFragment : MenuDialogFragment<Artist>() { class ArtistMenuDialogFragment : MenuDialogFragment<Artist>() {
override val menuModel: MenuViewModel by viewModels() override val menuModel: MenuViewModel by activityViewModels()
private val args: ArtistMenuDialogFragmentArgs by navArgs() private val args: ArtistMenuDialogFragmentArgs by navArgs()
override val menuRes: Int override val menuRes: Int
@ -105,7 +105,7 @@ class ArtistMenuDialogFragment : MenuDialogFragment<Artist>() {
@AndroidEntryPoint @AndroidEntryPoint
class GenreMenuDialogFragment : MenuDialogFragment<Genre>() { class GenreMenuDialogFragment : MenuDialogFragment<Genre>() {
override val menuModel: MenuViewModel by viewModels() override val menuModel: MenuViewModel by activityViewModels()
private val args: GenreMenuDialogFragmentArgs by navArgs() private val args: GenreMenuDialogFragmentArgs by navArgs()
override val menuRes: Int override val menuRes: Int
@ -130,7 +130,7 @@ class GenreMenuDialogFragment : MenuDialogFragment<Genre>() {
@AndroidEntryPoint @AndroidEntryPoint
class PlaylistMenuDialogFragment : MenuDialogFragment<Playlist>() { class PlaylistMenuDialogFragment : MenuDialogFragment<Playlist>() {
override val menuModel: MenuViewModel by viewModels() override val menuModel: MenuViewModel by activityViewModels()
private val args: PlaylistMenuDialogFragmentArgs by navArgs() private val args: PlaylistMenuDialogFragmentArgs by navArgs()
override val menuRes: Int override val menuRes: Int

View file

@ -18,18 +18,29 @@
package org.oxycblt.auxio.list.menu package org.oxycblt.auxio.list.menu
import androidx.annotation.MenuRes
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow 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.Music
import org.oxycblt.auxio.music.MusicRepository 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 import org.oxycblt.auxio.util.logW
@HiltViewModel @HiltViewModel
class MenuViewModel @Inject constructor(private val musicRepository: MusicRepository) : class MenuViewModel @Inject constructor(private val musicRepository: MusicRepository) :
ViewModel(), MusicRepository.UpdateListener { ViewModel(), MusicRepository.UpdateListener {
private val _pendingMenu = MutableEvent<PendingMenu>()
val pendingMenu: Event<PendingMenu> = _pendingMenu
private val _currentMusic = MutableStateFlow<Music?>(null) private val _currentMusic = MutableStateFlow<Music?>(null)
val currentMusic: StateFlow<Music?> = _currentMusic val currentMusic: StateFlow<Music?> = _currentMusic
@ -45,10 +56,46 @@ class MenuViewModel @Inject constructor(private val musicRepository: MusicReposi
musicRepository.removeUpdateListener(this) musicRepository.removeUpdateListener(this)
} }
fun setMusic(uid: Music.UID) { fun openMenu(@MenuRes menuRes: Int, song: Song) =
openMenuImpl(PendingMenu.ForSong(menuRes, song))
fun openMenu(@MenuRes menuRes: Int, album: Album) =
openMenuImpl(PendingMenu.ForAlbum(menuRes, album))
fun openMenu(@MenuRes menuRes: Int, artist: Artist) =
openMenuImpl(PendingMenu.ForArtist(menuRes, artist))
fun openMenu(@MenuRes menuRes: Int, genre: Genre) =
openMenuImpl(PendingMenu.ForGenre(menuRes, genre))
fun openMenu(@MenuRes menuRes: Int, playlist: Playlist) =
openMenuImpl(PendingMenu.ForPlaylist(menuRes, playlist))
private fun openMenuImpl(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) _currentMusic.value = musicRepository.find(uid)
if (_currentMusic.value == null) { if (_currentMusic.value == null) {
logW("Given Music UID to show was invalid") logW("Given Music UID to show was invalid")
} }
} }
} }
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
}

View file

@ -36,11 +36,12 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentSearchBinding import org.oxycblt.auxio.databinding.FragmentSearchBinding
import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.detail.Show import org.oxycblt.auxio.detail.Show
import org.oxycblt.auxio.home.HomeFragmentDirections
import org.oxycblt.auxio.list.Divider import org.oxycblt.auxio.list.Divider
import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Header
import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.ListFragment 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.selection.SelectionViewModel
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
@ -71,9 +72,10 @@ import org.oxycblt.auxio.util.setFullWidthLookup
@AndroidEntryPoint @AndroidEntryPoint
class SearchFragment : ListFragment<Music, FragmentSearchBinding>() { class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
override val detailModel: DetailViewModel by activityViewModels() override val detailModel: DetailViewModel by activityViewModels()
private val menuModel: MenuViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels()
override val playbackModel: PlaybackViewModel by activityViewModels() override val playbackModel: PlaybackViewModel by activityViewModels()
override val musicModel: MusicViewModel by activityViewModels() override val musicModel: MusicViewModel by activityViewModels()
override val selectionModel: SelectionViewModel by activityViewModels()
private val searchModel: SearchViewModel by viewModels() private val searchModel: SearchViewModel by viewModels()
private val searchAdapter = SearchAdapter(this) private val searchAdapter = SearchAdapter(this)
private var imm: InputMethodManager? = null private var imm: InputMethodManager? = null
@ -138,6 +140,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
// --- VIEWMODEL SETUP --- // --- VIEWMODEL SETUP ---
collectImmediately(searchModel.searchResults, ::updateSearchResults) collectImmediately(searchModel.searchResults, ::updateSearchResults)
collect(menuModel.pendingMenu.flow, ::handleMenu)
collectImmediately(selectionModel.selected, ::updateSelection) collectImmediately(selectionModel.selected, ::updateSelection)
collect(musicModel.playlistDecision.flow, ::handleDecision) collect(musicModel.playlistDecision.flow, ::handleDecision)
collectImmediately( collectImmediately(
@ -181,11 +184,11 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
override fun onOpenMenu(item: Music, anchor: View) { override fun onOpenMenu(item: Music, anchor: View) {
when (item) { when (item) {
is Song -> openMusicMenu(anchor, R.menu.item_song, item) is Song -> menuModel.openMenu(R.menu.item_song, item)
is Album -> openMusicMenu(anchor, R.menu.item_album, item) is Album -> menuModel.openMenu(R.menu.item_album, item)
is Artist -> openMusicMenu(anchor, R.menu.item_parent, item) is Artist -> menuModel.openMenu(R.menu.item_parent, item)
is Genre -> openMusicMenu(anchor, R.menu.item_parent, item) is Genre -> menuModel.openMenu(R.menu.item_parent, item)
is Playlist -> openMusicMenu(anchor, R.menu.item_playlist, item) is Playlist -> menuModel.openMenu(R.menu.item_playlist, item)
} }
} }
@ -247,7 +250,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
is Show.PlaylistDetails -> { is Show.PlaylistDetails -> {
logD("Navigating to ${show.playlist}") logD("Navigating to ${show.playlist}")
findNavController() findNavController()
.navigateSafe(SearchFragmentDirections.showGenre(show.playlist.uid)) .navigateSafe(SearchFragmentDirections.showPlaylist(show.playlist.uid))
} }
null -> {} null -> {}
} }
@ -258,32 +261,26 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
private fun handleDecision(decision: PlaylistDecision?) { private fun handleDecision(decision: PlaylistDecision?) {
if (decision == null) return if (decision == null) return
when (decision) { val directions =
is PlaylistDecision.New -> { when (decision) {
logD("Creating new playlist") is PlaylistDecision.Rename -> {
findNavController() logD("Renaming ${decision.playlist}")
.navigateSafe( SearchFragmentDirections.renamePlaylist(decision.playlist.uid)
HomeFragmentDirections.newPlaylist( }
decision.songs.map { it.uid }.toTypedArray())) is PlaylistDecision.Delete -> {
logD("Deleting ${decision.playlist}")
SearchFragmentDirections.deletePlaylist(decision.playlist.uid)
}
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} to a playlist")
SearchFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray())
}
is PlaylistDecision.New -> {
error("Unexpected decision $decision")
}
} }
is PlaylistDecision.Rename -> { findNavController().navigateSafe(directions)
logD("Renaming ${decision.playlist}")
findNavController()
.navigateSafe(HomeFragmentDirections.renamePlaylist(decision.playlist.uid))
}
is PlaylistDecision.Delete -> {
logD("Deleting ${decision.playlist}")
findNavController()
.navigateSafe(SearchFragmentDirections.deletePlaylist(decision.playlist.uid))
}
is PlaylistDecision.Add -> {
logD("Adding ${decision.songs.size} to a playlist")
findNavController()
.navigateSafe(
HomeFragmentDirections.addToPlaylist(
decision.songs.map { it.uid }.toTypedArray()))
}
}
musicModel.playlistDecision.consume() musicModel.playlistDecision.consume()
} }
@ -291,6 +288,30 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
searchAdapter.setPlaying(parent ?: song, isPlaying) searchAdapter.setPlaying(parent ?: song, isPlaying)
} }
private fun handleMenu(pendingMenu: PendingMenu?) {
if (pendingMenu == 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)
}
findNavController().navigateSafe(directions)
menuModel.pendingMenu.consume()
}
private fun updateSelection(selected: List<Music>) { private fun updateSelection(selected: List<Music>) {
searchAdapter.setSelected(selected.toSet()) searchAdapter.setSelected(selected.toSet())
val binding = requireBinding() val binding = requireBinding()

View file

@ -2,26 +2,28 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.Auxio.RecyclerView.Linear"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<org.oxycblt.auxio.image.CoverView <org.oxycblt.auxio.image.CoverView
android:id="@+id/menu_cover" android:id="@+id/menu_cover"
style="@style/Widget.Auxio.Image.MidLarge" style="@style/Widget.Auxio.Image.Full"
android:layout_margin="@dimen/spacing_medium" android:layout_marginVertical="@dimen/spacing_medium"
android:layout_marginStart="@dimen/spacing_medium"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/menu_type" android:id="@+id/menu_type"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Auxio.LabelLarge" android:layout_marginHorizontal="@dimen/spacing_medium"
android:layout_marginTop="@dimen/spacing_small"
android:textAppearance="@style/TextAppearance.Auxio.LabelMedium"
android:textColor="?attr/colorSecondary" android:textColor="?attr/colorSecondary"
android:layout_marginStart="@dimen/spacing_medium"
app:layout_constraintBottom_toTopOf="@+id/menu_name" app:layout_constraintBottom_toTopOf="@+id/menu_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/menu_cover" app:layout_constraintStart_toEndOf="@+id/menu_cover"
app:layout_constraintTop_toTopOf="@+id/menu_cover" app:layout_constraintTop_toTopOf="@+id/menu_cover"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
@ -29,32 +31,42 @@
<TextView <TextView
android:id="@+id/menu_name" android:id="@+id/menu_name"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Auxio.TitleLarge" style="@style/Widget.Auxio.TextView.Primary"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintBottom_toTopOf="@+id/menu_info" app:layout_constraintBottom_toTopOf="@+id/menu_info"
app:layout_constraintEnd_toEndOf="@+id/menu_type"
app:layout_constraintStart_toStartOf="@+id/menu_type" app:layout_constraintStart_toStartOf="@+id/menu_type"
app:layout_constraintTop_toBottomOf="@+id/menu_type" app:layout_constraintTop_toBottomOf="@+id/menu_type"
tools:text="Name" /> tools:text="Name" />
<TextView <TextView
android:id="@+id/menu_info" android:id="@+id/menu_info"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Auxio.TitleMedium" style="@style/Widget.Auxio.TextView.Secondary.Marquee"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="@+id/menu_cover" app:layout_constraintEnd_toEndOf="@+id/menu_type"
app:layout_constraintStart_toStartOf="@+id/menu_name" app:layout_constraintStart_toStartOf="@+id/menu_name"
app:layout_constraintTop_toBottomOf="@+id/menu_name" app:layout_constraintTop_toBottomOf="@+id/menu_name"
app:layout_constraintBottom_toBottomOf="@+id/menu_cover"
android:layout_marginBottom="@dimen/spacing_small"
tools:text="Info A" /> tools:text="Info A" />
<org.oxycblt.auxio.list.recycler.DialogRecyclerView <com.google.android.material.divider.MaterialDivider
android:id="@+id/materialDivider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
app:layout_constraintTop_toBottomOf="@+id/menu_cover" />
<org.oxycblt.auxio.list.recycler.AuxioRecyclerView
android:id="@+id/menu_option_recycler" android:id="@+id/menu_option_recycler"
style="@style/Widget.Auxio.RecyclerView.Linear" style="@style/Widget.Auxio.RecyclerView.Linear"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/menu_cover" android:overScrollMode="never"
app:layout_constraintTop_toBottomOf="@+id/materialDivider"
tools:listitem="@layout/item_menu_option" /> tools:listitem="@layout/item_menu_option" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -33,6 +33,21 @@
<action <action
android:id="@+id/show_playlist" android:id="@+id/show_playlist"
app:destination="@id/playlist_detail_fragment" /> app:destination="@id/playlist_detail_fragment" />
<action
android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" />
<action
android:id="@+id/open_album_menu"
app:destination="@id/album_menu_dialog" />
<action
android:id="@+id/open_artist_menu"
app:destination="@id/artist_menu_dialog" />
<action
android:id="@+id/open_genre_menu"
app:destination="@id/genre_menu_dialog" />
<action
android:id="@+id/open_playlist_menu"
app:destination="@id/playlist_menu_dialog" />
<action <action
android:id="@+id/new_playlist" android:id="@+id/new_playlist"
app:destination="@id/new_playlist_dialog" /> app:destination="@id/new_playlist_dialog" />
@ -86,6 +101,21 @@
<action <action
android:id="@+id/show_playlist" android:id="@+id/show_playlist"
app:destination="@id/playlist_detail_fragment" /> app:destination="@id/playlist_detail_fragment" />
<action
android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" />
<action
android:id="@+id/open_album_menu"
app:destination="@id/album_menu_dialog" />
<action
android:id="@+id/open_artist_menu"
app:destination="@id/artist_menu_dialog" />
<action
android:id="@+id/open_genre_menu"
app:destination="@id/genre_menu_dialog" />
<action
android:id="@+id/open_playlist_menu"
app:destination="@id/playlist_menu_dialog" />
<action <action
android:id="@+id/rename_playlist" android:id="@+id/rename_playlist"
app:destination="@id/rename_playlist_dialog" /> app:destination="@id/rename_playlist_dialog" />
@ -123,12 +153,15 @@
<action <action
android:id="@+id/show_artist" android:id="@+id/show_artist"
app:destination="@id/artist_detail_fragment" /> app:destination="@id/artist_detail_fragment" />
<action
android:id="@+id/add_to_playlist"
app:destination="@id/add_to_playlist_dialog" />
<action <action
android:id="@+id/show_artists" android:id="@+id/show_artists"
app:destination="@id/show_artists_dialog" /> app:destination="@id/show_artists_dialog" />
<action
android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" />
<action
android:id="@+id/add_to_playlist"
app:destination="@id/add_to_playlist_dialog" />
<action <action
android:id="@+id/play_from_artist" android:id="@+id/play_from_artist"
app:destination="@id/play_from_artist_dialog" /> app:destination="@id/play_from_artist_dialog" />
@ -154,6 +187,12 @@
<action <action
android:id="@+id/show_artist" android:id="@+id/show_artist"
app:destination="@id/artist_detail_fragment" /> app:destination="@id/artist_detail_fragment" />
<action
android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" />
<action
android:id="@+id/open_album_menu"
app:destination="@id/album_menu_dialog" />
<action <action
android:id="@+id/add_to_playlist" android:id="@+id/add_to_playlist"
app:destination="@id/add_to_playlist_dialog" /> app:destination="@id/add_to_playlist_dialog" />
@ -182,6 +221,12 @@
<action <action
android:id="@+id/show_artists" android:id="@+id/show_artists"
app:destination="@id/show_artists_dialog" /> app:destination="@id/show_artists_dialog" />
<action
android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" />
<action
android:id="@+id/open_artist_menu"
app:destination="@id/artist_menu_dialog" />
<action <action
android:id="@+id/add_to_playlist" android:id="@+id/add_to_playlist"
app:destination="@id/add_to_playlist_dialog" /> app:destination="@id/add_to_playlist_dialog" />
@ -210,6 +255,9 @@
<action <action
android:id="@+id/show_artists" android:id="@+id/show_artists"
app:destination="@id/show_artists_dialog" /> app:destination="@id/show_artists_dialog" />
<action
android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" />
<action <action
android:id="@+id/rename_playlist" android:id="@+id/rename_playlist"
app:destination="@id/rename_playlist_dialog" /> app:destination="@id/rename_playlist_dialog" />