list: open menu dialogs from toolbars

Make it so that toolbars now open menu dialogs as items do.

This excludes the selection menu currently since there's no dialog for
such.
This commit is contained in:
Alexander Capehart 2023-07-28 08:44:31 -06:00
parent 507bc516ce
commit 6d342325ea
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
18 changed files with 222 additions and 309 deletions

View file

@ -20,7 +20,6 @@ package org.oxycblt.auxio.detail
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@ -53,11 +52,9 @@ import org.oxycblt.auxio.util.canScroll
import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.overrideOnOverflowMenuClick
import org.oxycblt.auxio.util.setFullWidthLookup import org.oxycblt.auxio.util.setFullWidthLookup
import org.oxycblt.auxio.util.share
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -101,9 +98,11 @@ class AlbumDetailFragment :
// --- UI SETUP -- // --- UI SETUP --
binding.detailNormalToolbar.apply { binding.detailNormalToolbar.apply {
inflateMenu(R.menu.toolbar_album)
setNavigationOnClickListener { findNavController().navigateUp() } setNavigationOnClickListener { findNavController().navigateUp() }
setOnMenuItemClickListener(this@AlbumDetailFragment) overrideOnOverflowMenuClick {
listModel.openMenu(
R.menu.item_detail_album, unlikelyToBeNull(detailModel.currentAlbum.value))
}
} }
binding.detailRecycler.apply { binding.detailRecycler.apply {
@ -141,42 +140,6 @@ class AlbumDetailFragment :
detailModel.albumSongInstructions.consume() detailModel.albumSongInstructions.consume()
} }
override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onMenuItemClick(item)) {
return true
}
val currentAlbum = unlikelyToBeNull(detailModel.currentAlbum.value)
return when (item.itemId) {
R.id.action_play_next -> {
playbackModel.playNext(currentAlbum)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_queue_add -> {
playbackModel.addToQueue(currentAlbum)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_artist_details -> {
onNavigateToParentArtist()
true
}
R.id.action_playlist_add -> {
musicModel.addToPlaylist(currentAlbum)
true
}
R.id.action_share -> {
requireContext().share(currentAlbum)
true
}
else -> {
logW("Unexpected menu item selected")
false
}
}
}
override fun onRealClick(item: Song) { override fun onRealClick(item: Song) {
playbackModel.play(item, detailModel.playInAlbumWith) playbackModel.play(item, detailModel.playInAlbumWith)
} }
@ -279,7 +242,7 @@ class AlbumDetailFragment :
val directions = val directions =
when (menu) { when (menu) {
is Menu.ForSong -> AlbumDetailFragmentDirections.openSongMenu(menu.parcel) is Menu.ForSong -> AlbumDetailFragmentDirections.openSongMenu(menu.parcel)
is Menu.ForAlbum, is Menu.ForAlbum -> AlbumDetailFragmentDirections.openAlbumMenu(menu.parcel)
is Menu.ForArtist, is Menu.ForArtist,
is Menu.ForGenre, is Menu.ForGenre,
is Menu.ForPlaylist -> error("Unexpected menu $menu") is Menu.ForPlaylist -> error("Unexpected menu $menu")

View file

@ -20,7 +20,6 @@ package org.oxycblt.auxio.detail
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@ -52,11 +51,9 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.overrideOnOverflowMenuClick
import org.oxycblt.auxio.util.setFullWidthLookup import org.oxycblt.auxio.util.setFullWidthLookup
import org.oxycblt.auxio.util.share
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -99,9 +96,12 @@ class ArtistDetailFragment :
// --- UI SETUP --- // --- UI SETUP ---
binding.detailNormalToolbar.apply { binding.detailNormalToolbar.apply {
inflateMenu(R.menu.toolbar_parent)
setNavigationOnClickListener { findNavController().navigateUp() } setNavigationOnClickListener { findNavController().navigateUp() }
setOnMenuItemClickListener(this@ArtistDetailFragment) setOnMenuItemClickListener(this@ArtistDetailFragment)
overrideOnOverflowMenuClick {
listModel.openMenu(
R.menu.item_detail_parent, unlikelyToBeNull(detailModel.currentArtist.value))
}
} }
binding.detailRecycler.apply { binding.detailRecycler.apply {
@ -142,38 +142,6 @@ class ArtistDetailFragment :
detailModel.artistSongInstructions.consume() detailModel.artistSongInstructions.consume()
} }
override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onMenuItemClick(item)) {
return true
}
val currentArtist = unlikelyToBeNull(detailModel.currentArtist.value)
return when (item.itemId) {
R.id.action_play_next -> {
playbackModel.playNext(currentArtist)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_queue_add -> {
playbackModel.addToQueue(currentArtist)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_playlist_add -> {
musicModel.addToPlaylist(currentArtist)
true
}
R.id.action_share -> {
requireContext().share(currentArtist)
true
}
else -> {
logW("Unexpected menu item selected")
false
}
}
}
override fun onRealClick(item: Music) { override fun onRealClick(item: Music) {
when (item) { when (item) {
is Album -> detailModel.showAlbum(item) is Album -> detailModel.showAlbum(item)
@ -209,19 +177,7 @@ class ArtistDetailFragment :
findNavController().navigateUp() findNavController().navigateUp()
return return
} }
requireBinding().detailNormalToolbar.apply { requireBinding().detailNormalToolbar.title = artist.name.resolve(requireContext())
title = artist.name.resolve(requireContext())
// Disable options that make no sense with an empty artist
val playable = artist.songs.isNotEmpty()
if (!playable) {
logD("Artist is empty, disabling playback/playlist/share options")
}
menu.findItem(R.id.action_play_next).isEnabled = playable
menu.findItem(R.id.action_queue_add).isEnabled = playable
menu.findItem(R.id.action_playlist_add).isEnabled = playable
menu.findItem(R.id.action_share).isEnabled = playable
}
artistHeaderAdapter.setParent(artist) artistHeaderAdapter.setParent(artist)
} }
@ -282,7 +238,7 @@ class ArtistDetailFragment :
when (menu) { when (menu) {
is Menu.ForSong -> ArtistDetailFragmentDirections.openSongMenu(menu.parcel) is Menu.ForSong -> ArtistDetailFragmentDirections.openSongMenu(menu.parcel)
is Menu.ForAlbum -> ArtistDetailFragmentDirections.openAlbumMenu(menu.parcel) is Menu.ForAlbum -> ArtistDetailFragmentDirections.openAlbumMenu(menu.parcel)
is Menu.ForArtist, is Menu.ForArtist -> ArtistDetailFragmentDirections.openArtistMenu(menu.parcel)
is Menu.ForGenre, is Menu.ForGenre,
is Menu.ForPlaylist -> error("Unexpected menu $menu") is Menu.ForPlaylist -> error("Unexpected menu $menu")
} }

View file

@ -20,7 +20,6 @@ package org.oxycblt.auxio.detail
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
@ -52,11 +51,9 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.overrideOnOverflowMenuClick
import org.oxycblt.auxio.util.setFullWidthLookup import org.oxycblt.auxio.util.setFullWidthLookup
import org.oxycblt.auxio.util.share
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -97,9 +94,12 @@ class GenreDetailFragment :
// --- UI SETUP --- // --- UI SETUP ---
binding.detailNormalToolbar.apply { binding.detailNormalToolbar.apply {
inflateMenu(R.menu.toolbar_parent)
setNavigationOnClickListener { findNavController().navigateUp() } setNavigationOnClickListener { findNavController().navigateUp() }
setOnMenuItemClickListener(this@GenreDetailFragment) setOnMenuItemClickListener(this@GenreDetailFragment)
overrideOnOverflowMenuClick {
listModel.openMenu(
R.menu.item_detail_parent, unlikelyToBeNull(detailModel.currentGenre.value))
}
} }
binding.detailRecycler.apply { binding.detailRecycler.apply {
@ -140,38 +140,6 @@ class GenreDetailFragment :
detailModel.genreSongInstructions.consume() detailModel.genreSongInstructions.consume()
} }
override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onMenuItemClick(item)) {
return true
}
val currentGenre = unlikelyToBeNull(detailModel.currentGenre.value)
return when (item.itemId) {
R.id.action_play_next -> {
playbackModel.playNext(currentGenre)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_queue_add -> {
playbackModel.addToQueue(currentGenre)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_playlist_add -> {
musicModel.addToPlaylist(currentGenre)
true
}
R.id.action_share -> {
requireContext().share(currentGenre)
true
}
else -> {
logW("Unexpected menu item selected")
false
}
}
}
override fun onRealClick(item: Music) { override fun onRealClick(item: Music) {
when (item) { when (item) {
is Artist -> detailModel.showArtist(item) is Artist -> detailModel.showArtist(item)
@ -271,8 +239,8 @@ class GenreDetailFragment :
when (menu) { when (menu) {
is Menu.ForSong -> GenreDetailFragmentDirections.openSongMenu(menu.parcel) is Menu.ForSong -> GenreDetailFragmentDirections.openSongMenu(menu.parcel)
is Menu.ForArtist -> GenreDetailFragmentDirections.openArtistMenu(menu.parcel) is Menu.ForArtist -> GenreDetailFragmentDirections.openArtistMenu(menu.parcel)
is Menu.ForGenre -> GenreDetailFragmentDirections.openGenreMenu(menu.parcel)
is Menu.ForAlbum, is Menu.ForAlbum,
is Menu.ForGenre,
is Menu.ForPlaylist -> error("Unexpected menu $menu") is Menu.ForPlaylist -> error("Unexpected menu $menu")
} }
findNavController().navigateSafe(directions) findNavController().navigateSafe(directions)

View file

@ -20,7 +20,6 @@ package org.oxycblt.auxio.detail
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
@ -55,11 +54,9 @@ import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
import org.oxycblt.auxio.util.navigateSafe import org.oxycblt.auxio.util.navigateSafe
import org.oxycblt.auxio.util.overrideOnOverflowMenuClick
import org.oxycblt.auxio.util.setFullWidthLookup import org.oxycblt.auxio.util.setFullWidthLookup
import org.oxycblt.auxio.util.share
import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
@ -103,9 +100,13 @@ class PlaylistDetailFragment :
// --- UI SETUP --- // --- UI SETUP ---
binding.detailNormalToolbar.apply { binding.detailNormalToolbar.apply {
inflateMenu(R.menu.toolbar_playlist)
setNavigationOnClickListener { findNavController().navigateUp() } setNavigationOnClickListener { findNavController().navigateUp() }
setOnMenuItemClickListener(this@PlaylistDetailFragment) setOnMenuItemClickListener(this@PlaylistDetailFragment)
overrideOnOverflowMenuClick {
listModel.openMenu(
R.menu.item_detail_playlist,
unlikelyToBeNull(detailModel.currentPlaylist.value))
}
} }
binding.detailEditToolbar.apply { binding.detailEditToolbar.apply {
@ -190,46 +191,6 @@ class PlaylistDetailFragment :
} }
} }
override fun onMenuItemClick(item: MenuItem): Boolean {
if (super.onMenuItemClick(item)) {
return true
}
val currentPlaylist = unlikelyToBeNull(detailModel.currentPlaylist.value)
return when (item.itemId) {
R.id.action_play_next -> {
playbackModel.playNext(currentPlaylist)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_queue_add -> {
playbackModel.addToQueue(currentPlaylist)
requireContext().showToast(R.string.lng_queue_added)
true
}
R.id.action_rename -> {
musicModel.renamePlaylist(currentPlaylist)
true
}
R.id.action_delete -> {
musicModel.deletePlaylist(currentPlaylist)
true
}
R.id.action_share -> {
requireContext().share(currentPlaylist)
true
}
R.id.action_save -> {
detailModel.savePlaylistEdit()
true
}
else -> {
logW("Unexpected menu item selected")
false
}
}
}
override fun onRealClick(item: Song) { override fun onRealClick(item: Song) {
playbackModel.play(item, detailModel.playInPlaylistWith) playbackModel.play(item, detailModel.playInPlaylistWith)
} }
@ -265,17 +226,7 @@ class PlaylistDetailFragment :
return return
} }
val binding = requireBinding() val binding = requireBinding()
binding.detailNormalToolbar.apply { binding.detailNormalToolbar.title = playlist.name.resolve(requireContext())
title = playlist.name.resolve(requireContext())
// Disable options that make no sense with an empty playlist
val playable = playlist.songs.isNotEmpty()
if (!playable) {
logD("Playlist is empty, disabling playback/share options")
}
menu.findItem(R.id.action_play_next).isEnabled = playable
menu.findItem(R.id.action_queue_add).isEnabled = playable
menu.findItem(R.id.action_share).isEnabled = playable
}
binding.detailEditToolbar.title = binding.detailEditToolbar.title =
getString(R.string.fmt_editing, playlist.name.resolve(requireContext())) getString(R.string.fmt_editing, playlist.name.resolve(requireContext()))
playlistHeaderAdapter.setParent(playlist) playlistHeaderAdapter.setParent(playlist)
@ -349,10 +300,11 @@ class PlaylistDetailFragment :
val directions = val directions =
when (menu) { when (menu) {
is Menu.ForSong -> PlaylistDetailFragmentDirections.openSongMenu(menu.parcel) is Menu.ForSong -> PlaylistDetailFragmentDirections.openSongMenu(menu.parcel)
is Menu.ForPlaylist ->
PlaylistDetailFragmentDirections.openPlaylistMenu(menu.parcel)
is Menu.ForArtist, is Menu.ForArtist,
is Menu.ForAlbum, is Menu.ForAlbum,
is Menu.ForGenre, is Menu.ForGenre -> error("Unexpected menu $menu")
is Menu.ForPlaylist -> error("Unexpected menu $menu")
} }
findNavController().navigateSafe(directions) findNavController().navigateSafe(directions)
} }

View file

@ -34,8 +34,8 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
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.list.ListViewModel
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.music.resolveNames
import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.playback.state.RepeatMode
@ -44,7 +44,7 @@ import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collect
import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.collectImmediately
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.share import org.oxycblt.auxio.util.overrideOnOverflowMenuClick
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
@ -62,8 +62,8 @@ class PlaybackPanelFragment :
Toolbar.OnMenuItemClickListener, Toolbar.OnMenuItemClickListener,
StyledSeekBar.Listener { StyledSeekBar.Listener {
private val playbackModel: PlaybackViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels()
private val musicModel: MusicViewModel by activityViewModels()
private val detailModel: DetailViewModel by activityViewModels() private val detailModel: DetailViewModel by activityViewModels()
private val listModel: ListViewModel by activityViewModels()
private var equalizerLauncher: ActivityResultLauncher<Intent>? = null private var equalizerLauncher: ActivityResultLauncher<Intent>? = null
override fun onCreateBinding(inflater: LayoutInflater) = override fun onCreateBinding(inflater: LayoutInflater) =
@ -92,6 +92,13 @@ class PlaybackPanelFragment :
binding.playbackToolbar.apply { binding.playbackToolbar.apply {
setNavigationOnClickListener { playbackModel.openMain() } setNavigationOnClickListener { playbackModel.openMain() }
setOnMenuItemClickListener(this@PlaybackPanelFragment) setOnMenuItemClickListener(this@PlaybackPanelFragment)
overrideOnOverflowMenuClick {
playbackModel.song.value?.let {
// No playback options are actually available in the menu, so use a junk
// PlaySong option.
listModel.openMenu(R.menu.item_playback_song, it, PlaySong.ByItself)
}
}
} }
// Set up marquee on song information, alongside click handlers that navigate to each // Set up marquee on song information, alongside click handlers that navigate to each
@ -143,53 +150,30 @@ class PlaybackPanelFragment :
binding.playbackAlbum.isSelected = false binding.playbackAlbum.isSelected = false
} }
override fun onMenuItemClick(item: MenuItem) = override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) { if (item.itemId == R.id.action_open_equalizer) {
R.id.action_open_equalizer -> { // Launch the system equalizer app, if possible.
// Launch the system equalizer app, if possible. logD("Launching equalizer")
logD("Launching equalizer") val equalizerIntent =
val equalizerIntent = Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL)
Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL) // Provide audio session ID so the equalizer can show options for this app
// Provide audio session ID so the equalizer can show options for this app // in particular.
// in particular. .putExtra(AudioEffect.EXTRA_AUDIO_SESSION, playbackModel.currentAudioSessionId)
.putExtra( // Signal music type so that the equalizer settings are appropriate for
AudioEffect.EXTRA_AUDIO_SESSION, playbackModel.currentAudioSessionId) // music playback.
// Signal music type so that the equalizer settings are appropriate for .putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC)
// music playback. try {
.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC) requireNotNull(equalizerLauncher) { "Equalizer panel launcher was not available" }
try { .launch(equalizerIntent)
requireNotNull(equalizerLauncher) { } catch (e: ActivityNotFoundException) {
"Equalizer panel launcher was not available" requireContext().showToast(R.string.err_no_app)
}
.launch(equalizerIntent)
} catch (e: ActivityNotFoundException) {
requireContext().showToast(R.string.err_no_app)
}
true
} }
R.id.action_artist_details -> { return true
navigateToCurrentArtist()
true
}
R.id.action_album_details -> {
navigateToCurrentAlbum()
true
}
R.id.action_playlist_add -> {
playbackModel.song.value?.let(musicModel::addToPlaylist)
true
}
R.id.action_detail -> {
playbackModel.song.value?.let(detailModel::showSong)
true
}
R.id.action_share -> {
playbackModel.song.value?.let { requireContext().share(it) }
true
}
else -> false
} }
return false
}
override fun onSeekConfirmed(positionDs: Long) { override fun onSeekConfirmed(positionDs: Long) {
playbackModel.seekTo(positionDs) playbackModel.seekTo(positionDs)
} }

View file

@ -1,4 +0,0 @@
package org.oxycblt.auxio.ui
class IconToolbar {
}

View file

@ -25,16 +25,20 @@ import android.os.Build
import android.view.View import android.view.View
import android.view.WindowInsets import android.view.WindowInsets
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.appcompat.widget.ActionMenuView
import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.AppCompatButton
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.ShareCompat import androidx.core.app.ShareCompat
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.graphics.drawable.DrawableCompat import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.children
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDirections import androidx.navigation.NavDirections
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.google.android.material.appbar.MaterialToolbar
import java.lang.IllegalArgumentException import java.lang.IllegalArgumentException
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
@ -103,6 +107,25 @@ val Drawable.isRtl: Boolean
val ViewBinding.context: Context val ViewBinding.context: Context
get() = root.context get() = root.context
/**
* Override the behavior of a [MaterialToolbar]'s overflow menu to do something else. This is
* extremely dumb, but required to hook overflow menus to bottom sheet menus.
*/
fun MaterialToolbar.overrideOnOverflowMenuClick(block: (View) -> Unit) {
for (toolbarChild in children) {
if (toolbarChild is ActionMenuView) {
for (menuChild in toolbarChild.children) {
// The overflow menu's view implementation is package-private, so test for the
// first child that isn't a plain action button.
if (menuChild !is ActionMenuItemView) {
menuChild.setOnClickListener(block)
return
}
}
}
}
}
/** /**
* Compute if this [RecyclerView] can scroll through their items, or if the items can all fit on one * Compute if this [RecyclerView] can scroll through their items, or if the items can all fit on one
* screen. * screen.

View file

@ -24,6 +24,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
app:menu="@menu/toolbar_detail"
app:navigationIcon="@drawable/ic_back_24" /> app:navigationIcon="@drawable/ic_back_24" />
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_play"
android:title="@string/lbl_play"
android:icon="@drawable/ic_play_24" />
<item
android:id="@+id/action_shuffle"
android:title="@string/lbl_shuffle"
android:icon="@drawable/ic_shuffle_off_24"/>
<item
android:id="@+id/action_play_next"
android:title="@string/lbl_play_next"
android:icon="@drawable/ic_play_next_24"/>
<item
android:id="@+id/action_queue_add"
android:title="@string/lbl_queue_add"
android:icon="@drawable/ic_queue_add_24"/>
<item
android:id="@+id/action_playlist_add"
android:title="@string/lbl_playlist_add"
android:icon="@drawable/ic_playlist_add_24"/>
<item
android:id="@+id/action_artist_details"
android:title="@string/lbl_artist_details"
android:icon="@drawable/ic_artist_24" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share"
android:icon="@drawable/ic_share_24"/>
</menu>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_play"
android:title="@string/lbl_play"
android:icon="@drawable/ic_play_24" />
<item
android:id="@+id/action_shuffle"
android:title="@string/lbl_shuffle"
android:icon="@drawable/ic_shuffle_off_24"/>
<item
android:id="@+id/action_play_next"
android:title="@string/lbl_play_next"
android:icon="@drawable/ic_play_next_24"/>
<item
android:id="@+id/action_queue_add"
android:title="@string/lbl_queue_add"
android:icon="@drawable/ic_queue_add_24"/>
<item
android:id="@+id/action_playlist_add"
android:title="@string/lbl_playlist_add"
android:icon="@drawable/ic_playlist_add_24" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share"
android:icon="@drawable/ic_share_24"/>
</menu>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_play"
android:title="@string/lbl_play"
android:icon="@drawable/ic_play_24" />
<item
android:id="@+id/action_shuffle"
android:title="@string/lbl_shuffle"
android:icon="@drawable/ic_shuffle_off_24"/>
<item
android:id="@+id/action_play_next"
android:title="@string/lbl_play_next"
android:icon="@drawable/ic_play_next_24"/>
<item
android:id="@+id/action_queue_add"
android:title="@string/lbl_queue_add"
android:icon="@drawable/ic_queue_add_24"/>
<item
android:id="@+id/action_rename"
android:title="@string/lbl_rename"
android:icon="@drawable/ic_edit_24"/>
<item
android:id="@+id/action_delete"
android:title="@string/lbl_delete"
android:icon="@drawable/ic_delete_24"/>
<item
android:id="@+id/action_share"
android:title="@string/lbl_share"
android:icon="@drawable/ic_share_24"/>
</menu>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_playlist_add"
android:icon="@drawable/ic_playlist_add_24"
android:title="@string/lbl_playlist_add" />
<item
android:id="@+id/action_artist_details"
android:title="@string/lbl_artist_details"
android:icon="@drawable/ic_artist_24" />
<item
android:id="@+id/action_album_details"
android:title="@string/lbl_album_details"
android:icon="@drawable/ic_album_24"
app:showAsAction="never" />
<item
android:id="@+id/action_detail"
android:title="@string/lbl_song_detail"
android:icon="@drawable/ic_details_24"
app:showAsAction="never" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share"
android:icon="@drawable/ic_share_24" />
</menu>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_play_next"
android:title="@string/lbl_play_next" />
<item
android:id="@+id/action_queue_add"
android:title="@string/lbl_queue_add" />
<item
android:id="@+id/action_artist_details"
android:title="@string/lbl_artist_details" />
<item
android:id="@+id/action_playlist_add"
android:title="@string/lbl_playlist_add" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share" />
</menu>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/placeholder"
android:title=""
app:showAsAction="never" />
</menu>

View file

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_play_next"
android:title="@string/lbl_play_next" />
<item
android:id="@+id/action_queue_add"
android:title="@string/lbl_queue_add" />
<item
android:id="@+id/action_playlist_add"
android:title="@string/lbl_playlist_add" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share" />
</menu>

View file

@ -5,23 +5,9 @@
android:id="@+id/action_open_equalizer" android:id="@+id/action_open_equalizer"
android:icon="@drawable/ic_config_24" android:icon="@drawable/ic_config_24"
android:title="@string/lbl_equalizer" android:title="@string/lbl_equalizer"
app:showAsAction="ifRoom" /> app:showAsAction="always" />
<item <item
android:id="@+id/action_artist_details" android:id="@+id/placeholder"
android:title="@string/lbl_artist_details" android:title=""
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_album_details"
android:title="@string/lbl_album_details"
app:showAsAction="never" />
<item
android:id="@+id/action_playlist_add"
android:title="@string/lbl_playlist_add" />
<item
android:id="@+id/action_detail"
android:title="@string/lbl_song_detail"
app:showAsAction="never" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share" />
</menu> </menu>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_play_next"
android:title="@string/lbl_play_next" />
<item
android:id="@+id/action_queue_add"
android:title="@string/lbl_queue_add" />
<item
android:id="@+id/action_rename"
android:title="@string/lbl_rename" />
<item
android:id="@+id/action_delete"
android:title="@string/lbl_delete" />
<item
android:id="@+id/action_share"
android:title="@string/lbl_share" />
</menu>

View file

@ -201,6 +201,9 @@
<action <action
android:id="@+id/open_song_menu" android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" /> 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" />
@ -244,6 +247,9 @@
<action <action
android:id="@+id/open_album_menu" android:id="@+id/open_album_menu"
app:destination="@id/album_menu_dialog" /> app:destination="@id/album_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" />
@ -287,6 +293,9 @@
<action <action
android:id="@+id/open_artist_menu" android:id="@+id/open_artist_menu"
app:destination="@id/artist_menu_dialog" /> app:destination="@id/artist_menu_dialog" />
<action
android:id="@+id/open_genre_menu"
app:destination="@id/genre_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" />
@ -327,6 +336,9 @@
<action <action
android:id="@+id/open_song_menu" android:id="@+id/open_song_menu"
app:destination="@id/song_menu_dialog" /> app:destination="@id/song_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" />