diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b39161f..f2e4c8bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ #### What's Fixed - Fixed issue where the scroll popup would not display correctly in landscape mode [#230] -- Fixed issue where the playback progress would continue in the notification even if +- Fixed issue where the playback progress would continue in the notification when audio focus was lost - Fixed issue where the app would crash if a song menu in the genre UI was opened - Fixed issue where the artist name would not be shown in the OS audio switcher menu 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 7b574222c..66b79e929 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -43,7 +43,7 @@ import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.picker.PickerMode import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.MainNavigationAction -import org.oxycblt.auxio.ui.fragment.MenuFragment +import org.oxycblt.auxio.ui.fragment.MusicFragment import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.util.canScroll import org.oxycblt.auxio.util.collect @@ -58,7 +58,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * @author OxygenCobalt */ class AlbumDetailFragment : - MenuFragment(), + MusicFragment(), Toolbar.OnMenuItemClickListener, AlbumDetailAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() @@ -132,17 +132,7 @@ class AlbumDetailFragment : when (settings.detailPlaybackMode) { null, MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) MusicMode.SONGS -> playbackModel.playFromAll(item) - MusicMode.ARTISTS -> { - if (item.artists.size == 1) { - playbackModel.playFromArtist(item, item.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(item.uid, PickerMode.PLAY) - ) - ) - } - } + MusicMode.ARTISTS -> doArtistDependentAction(item, PickerMode.PLAY) else -> error("Unexpected playback mode: ${settings.detailPlaybackMode}") } } @@ -179,16 +169,7 @@ class AlbumDetailFragment : } override fun onNavigateToArtist() { - val album = unlikelyToBeNull(detailModel.currentAlbum.value) - if (album.artists.size == 1) { - navModel.exploreNavigateTo(album.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(album.uid, PickerMode.SHOW) - ) - ) - } + navigateToArtist(unlikelyToBeNull(detailModel.currentAlbum.value)) } private fun handleItemChange(album: Album?) { 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 7a3ccf8ed..381ce5395 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -41,7 +41,7 @@ import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.picker.PickerMode import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.MainNavigationAction -import org.oxycblt.auxio.ui.fragment.MenuFragment +import org.oxycblt.auxio.ui.fragment.MusicFragment import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collectImmediately @@ -55,7 +55,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * @author OxygenCobalt */ class ArtistDetailFragment : - MenuFragment(), Toolbar.OnMenuItemClickListener, DetailAdapter.Listener { + MusicFragment(), Toolbar.OnMenuItemClickListener, DetailAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() private val args: ArtistDetailFragmentArgs by navArgs() @@ -125,17 +125,7 @@ class ArtistDetailFragment : null -> playbackModel.playFromArtist(item, unlikelyToBeNull(detailModel.currentArtist.value)) MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) - MusicMode.ARTISTS -> { - if (item.artists.size == 1) { - playbackModel.playFromArtist(item, item.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(item.uid, PickerMode.PLAY) - ) - ) - } - } + MusicMode.ARTISTS -> doArtistDependentAction(item, PickerMode.PLAY) else -> error("Unexpected playback mode: ${settings.detailPlaybackMode}") } } 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 08fb959e9..0f1ecfbed 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -42,7 +42,7 @@ import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.picker.PickerMode import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.MainNavigationAction -import org.oxycblt.auxio.ui.fragment.MenuFragment +import org.oxycblt.auxio.ui.fragment.MusicFragment import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collectImmediately @@ -56,7 +56,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * @author OxygenCobalt */ class GenreDetailFragment : - MenuFragment(), Toolbar.OnMenuItemClickListener, DetailAdapter.Listener { + MusicFragment(), Toolbar.OnMenuItemClickListener, DetailAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() private val args: GenreDetailFragmentArgs by navArgs() @@ -120,29 +120,27 @@ class GenreDetailFragment : } override fun onItemClick(item: Item) { - check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } - when (settings.detailPlaybackMode) { - null -> playbackModel.playFromGenre(item, unlikelyToBeNull(detailModel.currentGenre.value)) - MusicMode.SONGS -> playbackModel.playFromAll(item) - MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) - MusicMode.ARTISTS -> { - if (item.artists.size == 1) { - playbackModel.playFromArtist(item, item.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(item.uid, PickerMode.PLAY) - ) - ) - } + when (item) { + is Artist -> navModel.exploreNavigateTo(item) + + is Song -> when (settings.detailPlaybackMode) { + null -> playbackModel.playFromGenre(item, unlikelyToBeNull(detailModel.currentGenre.value)) + MusicMode.SONGS -> playbackModel.playFromAll(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> doArtistDependentAction(item, PickerMode.PLAY) + else -> error("Unexpected playback mode: ${settings.detailPlaybackMode}") } - else -> error("Unexpected playback mode: ${settings.detailPlaybackMode}") + + else -> error("Unexpected datatype: ${item::class.simpleName}") } } override fun onOpenMenu(item: Item, anchor: View) { - check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } - musicMenu(anchor, R.menu.menu_song_actions, item) + when (item) { + is Artist -> musicMenu(anchor, R.menu.menu_artist_actions, item) + is Song -> musicMenu(anchor, R.menu.menu_song_actions, item) + else -> error("Unexpected datatype: ${item::class.simpleName}") + } } override fun onPlayParent() { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt index 75074a82d..41128e168 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt @@ -87,6 +87,8 @@ class GenreDetailAdapter(private val listener: Listener) : return when { oldItem is Genre && newItem is Genre -> GenreDetailViewHolder.DIFFER.areContentsTheSame(oldItem, newItem) + oldItem is Artist && newItem is Artist -> + ArtistViewHolder.DIFFER.areContentsTheSame(oldItem, newItem) oldItem is Song && newItem is Song -> SongViewHolder.DIFFER.areContentsTheSame(oldItem, newItem) else -> DetailAdapter.DIFFER.areContentsTheSame(oldItem, newItem) diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt index 819e9028d..067c15913 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt @@ -80,7 +80,7 @@ class ArtistListFragment : HomeListFragment() { override fun onOpenMenu(item: Item, anchor: View) { check(item is Artist) { "Unexpected datatype: ${item::class.java}" } - musicMenu(anchor, R.menu.menu_genre_artist_actions, item) + musicMenu(anchor, R.menu.menu_artist_actions, item) } private fun handleParent(parent: MusicParent?, isPlaying: Boolean) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt index 1ef2d0023..0a01bb24e 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt @@ -79,7 +79,7 @@ class GenreListFragment : HomeListFragment() { override fun onOpenMenu(item: Item, anchor: View) { check(item is Genre) { "Unexpected datatype: ${item::class.java}" } - musicMenu(anchor, R.menu.menu_genre_artist_actions, item) + musicMenu(anchor, R.menu.menu_artist_actions, item) } private fun handlePlayback(parent: MusicParent?, isPlaying: Boolean) { diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt index c95ccfed2..f952d72cc 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/HomeListFragment.kt @@ -23,7 +23,7 @@ import androidx.fragment.app.Fragment import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.home.HomeViewModel import org.oxycblt.auxio.ui.fastscroll.FastScrollRecyclerView -import org.oxycblt.auxio.ui.fragment.MenuFragment +import org.oxycblt.auxio.ui.fragment.MusicFragment import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener import org.oxycblt.auxio.util.androidActivityViewModels @@ -33,7 +33,7 @@ import org.oxycblt.auxio.util.androidActivityViewModels * @author OxygenCobalt */ abstract class HomeListFragment : - MenuFragment(), + MusicFragment(), MenuItemListener, FastScrollRecyclerView.PopupProvider, FastScrollRecyclerView.OnFastScrollListener { 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 be98371a5..8a72da962 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 @@ -115,17 +115,7 @@ class SongListFragment : HomeListFragment() { when (settings.libPlaybackMode) { MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) - MusicMode.ARTISTS -> { - if (item.artists.size == 1) { - playbackModel.playFromArtist(item, item.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(item.uid, PickerMode.PLAY) - ) - ) - } - } + MusicMode.ARTISTS -> doArtistDependentAction(item, PickerMode.PLAY) else -> error("Unexpected playback mode: ${settings.libPlaybackMode}") } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt index 20fefd44a..7ad50fc01 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt @@ -52,7 +52,7 @@ import org.oxycblt.auxio.util.logW * (and hacky garbage) in order to produce the best possible experience. It is split into three * distinct steps: * - * 1. Creating the chain of layers to extract metadata with + * 1. Creating the chain of extractors to extract metadata with * 2. Running the chain process * 3. Using the songs to build the library, which primarily involves linking up all data objects * with their corresponding parents/children. diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt index b5ce1dc3f..2df693198 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt @@ -36,7 +36,7 @@ import org.oxycblt.auxio.music.picker.PickerMode import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.playback.ui.StyledSeekBar import org.oxycblt.auxio.ui.MainNavigationAction -import org.oxycblt.auxio.ui.fragment.MenuFragment +import org.oxycblt.auxio.ui.fragment.MusicFragment import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.systemBarInsetsCompat @@ -49,7 +49,7 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat * TODO: Make seek thumb grow when selected */ class PlaybackPanelFragment : - MenuFragment(), + MusicFragment(), StyledSeekBar.Callback, Toolbar.OnMenuItemClickListener { // AudioEffect expects you to use startActivityForResult with the panel intent. Use @@ -215,15 +215,7 @@ class PlaybackPanelFragment : private fun showCurrentArtist() { val song = playbackModel.song.value ?: return - if (song.artists.size == 1) { - navModel.exploreNavigateTo(song.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(song.uid, PickerMode.SHOW) - ) - ) - } + doArtistDependentAction(song, PickerMode.SHOW) } private fun showCurrentAlbum() { val song = playbackModel.song.value ?: return 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 4eb03b6a2..799428971 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -29,7 +29,6 @@ import androidx.core.widget.addTextChangedListener import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.google.android.material.transition.MaterialSharedAxis -import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentSearchBinding import org.oxycblt.auxio.music.Album @@ -41,8 +40,7 @@ import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.picker.PickerMode import org.oxycblt.auxio.settings.Settings -import org.oxycblt.auxio.ui.MainNavigationAction -import org.oxycblt.auxio.ui.fragment.MenuFragment +import org.oxycblt.auxio.ui.fragment.MusicFragment import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener import org.oxycblt.auxio.util.androidViewModels @@ -57,7 +55,7 @@ import org.oxycblt.auxio.util.logW * @author OxygenCobalt */ class SearchFragment : - MenuFragment(), MenuItemListener, Toolbar.OnMenuItemClickListener { + MusicFragment(), MenuItemListener, Toolbar.OnMenuItemClickListener { // SearchViewModel is only scoped to this Fragment private val searchModel: SearchViewModel by androidViewModels() @@ -153,17 +151,7 @@ class SearchFragment : is Song -> when (settings.libPlaybackMode) { MusicMode.SONGS -> playbackModel.playFromAll(item) MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) - MusicMode.ARTISTS -> { - if (item.artists.size == 1) { - playbackModel.playFromArtist(item, item.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(item.uid, PickerMode.PLAY) - ) - ) - } - } + MusicMode.ARTISTS -> doArtistDependentAction(item, PickerMode.PLAY) else -> error("Unexpected playback mode: ${settings.libPlaybackMode}") } is MusicParent -> navModel.exploreNavigateTo(item) @@ -174,8 +162,8 @@ class SearchFragment : when (item) { is Song -> musicMenu(anchor, R.menu.menu_song_actions, item) is Album -> musicMenu(anchor, R.menu.menu_album_actions, item) - is Artist -> musicMenu(anchor, R.menu.menu_genre_artist_actions, item) - is Genre -> musicMenu(anchor, R.menu.menu_genre_artist_actions, item) + is Artist -> musicMenu(anchor, R.menu.menu_artist_actions, item) + is Genre -> musicMenu(anchor, R.menu.menu_artist_actions, item) else -> logW("Unexpected datatype when opening menu: ${item::class.java}") } } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt b/app/src/main/java/org/oxycblt/auxio/ui/fragment/MusicFragment.kt similarity index 85% rename from app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt rename to app/src/main/java/org/oxycblt/auxio/ui/fragment/MusicFragment.kt index 01b4eb301..b6d633240 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/fragment/MenuFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/fragment/MusicFragment.kt @@ -42,12 +42,46 @@ import org.oxycblt.auxio.util.showToast * preventing UI issues and memory leaks. * @author OxygenCobalt */ -abstract class MenuFragment : ViewBindingFragment() { +abstract class MusicFragment : ViewBindingFragment() { private var currentMenu: PopupMenu? = null protected val playbackModel: PlaybackViewModel by androidActivityViewModels() protected val navModel: NavigationViewModel by activityViewModels() + /** + * Run the UI flow to perform a specific [PickerMode] action with a particular + * artist from [song]. + */ + fun doArtistDependentAction(song: Song, mode: PickerMode) { + if (song.artists.size == 1) { + when (mode) { + PickerMode.PLAY -> playbackModel.playFromArtist(song, song.artists[0]) + PickerMode.SHOW -> navModel.exploreNavigateTo(song.artists[0]) + } + } else { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.actionPickArtist(song.uid, mode) + ) + ) + } + } + + /** + * Run the UI flow to navigate to a particular artist from [album]. + */ + fun navigateToArtist(album: Album) { + if (album.artists.size == 1) { + navModel.exploreNavigateTo(album.artists[0]) + } else { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.actionPickArtist(album.uid, PickerMode.SHOW) + ) + ) + } + } + /** * Opens the given menu in context of [song]. Assumes that the menu is only composed of common * [Song] options. @@ -66,15 +100,7 @@ abstract class MenuFragment : ViewBindingFragment() { requireContext().showToast(R.string.lng_queue_added) } R.id.action_go_artist -> { - if (song.artists.size == 1) { - navModel.exploreNavigateTo(song.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(song.uid, PickerMode.SHOW) - ) - ) - } + doArtistDependentAction(song, PickerMode.SHOW) } R.id.action_go_album -> { navModel.exploreNavigateTo(song.album) @@ -119,15 +145,7 @@ abstract class MenuFragment : ViewBindingFragment() { requireContext().showToast(R.string.lng_queue_added) } R.id.action_go_artist -> { - if (album.artists.size == 1) { - navModel.exploreNavigateTo(album.artists[0]) - } else { - navModel.mainNavigateTo( - MainNavigationAction.Directions( - MainFragmentDirections.actionPickArtist(album.uid, PickerMode.SHOW) - ) - ) - } + navigateToArtist(album) } else -> { error("Unexpected menu item selected") diff --git a/app/src/main/res/menu/menu_genre_artist_actions.xml b/app/src/main/res/menu/menu_artist_actions.xml similarity index 100% rename from app/src/main/res/menu/menu_genre_artist_actions.xml rename to app/src/main/res/menu/menu_artist_actions.xml