music: try to deduplicate multi-artist code
Try to move multi-artist playback/navigation into a single function. This function is really bad and is tacked onto the most convienent location without much thought. I really wish to move this into the ViewModel flow eventually, but I have no idea how to architecture that. Oh well.
This commit is contained in:
parent
3a236bdaf4
commit
aa805e351c
14 changed files with 79 additions and 120 deletions
|
@ -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
|
||||
|
|
|
@ -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<FragmentDetailBinding>(),
|
||||
MusicFragment<FragmentDetailBinding>(),
|
||||
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?) {
|
||||
|
|
|
@ -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<FragmentDetailBinding>(), Toolbar.OnMenuItemClickListener, DetailAdapter.Listener {
|
||||
MusicFragment<FragmentDetailBinding>(), 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}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<FragmentDetailBinding>(), Toolbar.OnMenuItemClickListener, DetailAdapter.Listener {
|
||||
MusicFragment<FragmentDetailBinding>(), 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() {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -80,7 +80,7 @@ class ArtistListFragment : HomeListFragment<Artist>() {
|
|||
|
||||
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) {
|
||||
|
|
|
@ -79,7 +79,7 @@ class GenreListFragment : HomeListFragment<Genre>() {
|
|||
|
||||
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) {
|
||||
|
|
|
@ -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<T : Item> :
|
||||
MenuFragment<FragmentHomeListBinding>(),
|
||||
MusicFragment<FragmentHomeListBinding>(),
|
||||
MenuItemListener,
|
||||
FastScrollRecyclerView.PopupProvider,
|
||||
FastScrollRecyclerView.OnFastScrollListener {
|
||||
|
|
|
@ -115,17 +115,7 @@ class SongListFragment : HomeListFragment<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}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<FragmentPlaybackPanelBinding>(),
|
||||
MusicFragment<FragmentPlaybackPanelBinding>(),
|
||||
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
|
||||
|
|
|
@ -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<FragmentSearchBinding>(), MenuItemListener, Toolbar.OnMenuItemClickListener {
|
||||
MusicFragment<FragmentSearchBinding>(), 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}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,12 +42,46 @@ import org.oxycblt.auxio.util.showToast
|
|||
* preventing UI issues and memory leaks.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
abstract class MenuFragment<T : ViewBinding> : ViewBindingFragment<T>() {
|
||||
abstract class MusicFragment<T : ViewBinding> : ViewBindingFragment<T>() {
|
||||
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<T : ViewBinding> : ViewBindingFragment<T>() {
|
|||
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<T : ViewBinding> : ViewBindingFragment<T>() {
|
|||
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")
|
Loading…
Reference in a new issue