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 1d3d4f9f3..d94592b23 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -29,7 +29,6 @@ import com.google.android.material.transition.MaterialSharedAxis import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.AlbumDetailAdapter -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist @@ -39,18 +38,14 @@ import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.settings.Settings -import org.oxycblt.auxio.util.canScroll -import org.oxycblt.auxio.util.collect -import org.oxycblt.auxio.util.collectImmediately -import org.oxycblt.auxio.util.logD -import org.oxycblt.auxio.util.showToast -import org.oxycblt.auxio.util.unlikelyToBeNull +import org.oxycblt.auxio.util.* /** * A [ListFragment] that shows information about an [Album]. * @author Alexander Capehart (OxygenCobalt) */ -class AlbumDetailFragment : ListFragment(), AlbumDetailAdapter.Listener { +class AlbumDetailFragment : + ListFragment(), AlbumDetailAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() // Information about what album to display is initially within the navigation arguments // as a UID, as that is the only safe way to parcel an album. @@ -126,20 +121,20 @@ class AlbumDetailFragment : ListFragment(), AlbumDetailAd } } - override fun onRealClick(music: Music) { - check(music is Song) { "Unexpected datatype: ${music::class.java}" } + override fun onRealClick(item: Music) { + val song = requireIs(item) when (Settings(requireContext()).detailPlaybackMode) { // "Play from shown item" and "Play from album" functionally have the same // behavior since a song can only have one album. null, - MusicMode.ALBUMS -> playbackModel.playFromAlbum(music) - MusicMode.SONGS -> playbackModel.playFromAll(music) - MusicMode.ARTISTS -> playbackModel.playFromArtist(music) - MusicMode.GENRES -> playbackModel.playFromGenre(music) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(song) + MusicMode.SONGS -> playbackModel.playFromAll(song) + MusicMode.ARTISTS -> playbackModel.playFromArtist(song) + MusicMode.GENRES -> playbackModel.playFromGenre(song) } } - override fun onOpenMenu(item: Item, anchor: View) { + override fun onOpenMenu(item: Music, anchor: View) { check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } openMusicMenu(anchor, R.menu.menu_album_song_actions, item) } 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 e1d103861..f87f9ab56 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -29,7 +29,6 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.ArtistDetailAdapter import org.oxycblt.auxio.detail.recycler.DetailAdapter -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist @@ -49,7 +48,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * A [ListFragment] that shows information about an [Artist]. * @author Alexander Capehart (OxygenCobalt) */ -class ArtistDetailFragment : ListFragment(), DetailAdapter.Listener { +class ArtistDetailFragment : ListFragment(), DetailAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() // Information about what artist to display is initially within the navigation arguments // as a UID, as that is the only safe way to parcel an artist. @@ -121,27 +120,27 @@ class ArtistDetailFragment : ListFragment(), DetailAdapte } } - override fun onRealClick(music: Music) { - when (music) { + override fun onRealClick(item: Music) { + when (item) { is Song -> { when (Settings(requireContext()).detailPlaybackMode) { // When configured to play from the selected item, we already have an Artist // to play from. null -> playbackModel.playFromArtist( - music, unlikelyToBeNull(detailModel.currentArtist.value)) - MusicMode.SONGS -> playbackModel.playFromAll(music) - MusicMode.ALBUMS -> playbackModel.playFromAlbum(music) - MusicMode.ARTISTS -> playbackModel.playFromArtist(music) - MusicMode.GENRES -> playbackModel.playFromGenre(music) + item, unlikelyToBeNull(detailModel.currentArtist.value)) + MusicMode.SONGS -> playbackModel.playFromAll(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> playbackModel.playFromGenre(item) } } - is Album -> navModel.exploreNavigateTo(music) - else -> error("Unexpected datatype: ${music::class.simpleName}") + is Album -> navModel.exploreNavigateTo(item) + else -> error("Unexpected datatype: ${item::class.simpleName}") } } - override fun onOpenMenu(item: Item, anchor: View) { + override fun onOpenMenu(item: Music, anchor: View) { when (item) { is Song -> openMusicMenu(anchor, R.menu.menu_artist_song_actions, item) is Album -> openMusicMenu(anchor, R.menu.menu_artist_album_actions, item) 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 bfeca52c3..302d3abfb 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -29,7 +29,6 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.DetailAdapter import org.oxycblt.auxio.detail.recycler.GenreDetailAdapter -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist @@ -50,7 +49,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * A [ListFragment] that shows information for a particular [Genre]. * @author Alexander Capehart (OxygenCobalt) */ -class GenreDetailFragment : ListFragment(), DetailAdapter.Listener { +class GenreDetailFragment : ListFragment(), DetailAdapter.Listener { private val detailModel: DetailViewModel by activityViewModels() // Information about what genre to display is initially within the navigation arguments // as a UID, as that is the only safe way to parcel an genre. @@ -120,26 +119,26 @@ class GenreDetailFragment : ListFragment(), DetailAdapter } } - override fun onRealClick(music: Music) { - when (music) { - is Artist -> navModel.exploreNavigateTo(music) + override fun onRealClick(item: Music) { + when (item) { + is Artist -> navModel.exploreNavigateTo(item) is Song -> when (Settings(requireContext()).detailPlaybackMode) { // When configured to play from the selected item, we already have a Genre // to play from. null -> playbackModel.playFromGenre( - music, unlikelyToBeNull(detailModel.currentGenre.value)) - MusicMode.SONGS -> playbackModel.playFromAll(music) - MusicMode.ALBUMS -> playbackModel.playFromAlbum(music) - MusicMode.ARTISTS -> playbackModel.playFromArtist(music) - MusicMode.GENRES -> playbackModel.playFromGenre(music) + item, unlikelyToBeNull(detailModel.currentGenre.value)) + MusicMode.SONGS -> playbackModel.playFromAll(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> playbackModel.playFromGenre(item) } - else -> error("Unexpected datatype: ${music::class.simpleName}") + else -> error("Unexpected datatype: ${item::class.simpleName}") } } - override fun onOpenMenu(item: Item, anchor: View) { + override fun onOpenMenu(item: Music, anchor: View) { when (item) { is Artist -> openMusicMenu(anchor, R.menu.menu_artist_actions, item) is Song -> openMusicMenu(anchor, R.menu.menu_song_actions, item) @@ -184,17 +183,15 @@ class GenreDetailFragment : ListFragment(), DetailAdapter } private fun updatePlayback(song: Song?, parent: MusicParent?, isPlaying: Boolean) { - var item: Item? = null - + var playingMusic: Music? = null if (parent is Artist) { - item = parent + playingMusic = parent } - + // Prefer songs that might be playing from this genre. if (parent is Genre && parent.uid == unlikelyToBeNull(detailModel.currentGenre.value).uid) { - item = song + playingMusic = song } - - detailAdapter.setPlayingItem(item, isPlaying) + detailAdapter.setPlayingItem(playingMusic, isPlaying) } private fun handleNavigation(item: Music?) { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt index 8cc214b14..fb80c5ba5 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt @@ -226,7 +226,7 @@ private class AlbumSongViewHolder private constructor(private val binding: ItemA * @param song The new [Song] to bind. * @param listener A [SelectableListListener] to bind interactions to. */ - fun bind(song: Song, listener: SelectableListListener) { + fun bind(song: Song, listener: SelectableListListener) { listener.bind(song, this, menuButton = binding.songMenu) binding.songTrack.apply { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt index 84aedabfb..ddcc5ceb7 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt @@ -183,7 +183,7 @@ private class ArtistAlbumViewHolder private constructor(private val binding: Ite * @param album The new [Album] to bind. * @param listener An [SelectableListListener] to bind interactions to. */ - fun bind(album: Album, listener: SelectableListListener) { + fun bind(album: Album, listener: SelectableListListener) { listener.bind(album, this, menuButton = binding.parentMenu) binding.parentImage.bind(album) binding.parentName.text = album.resolveName(binding.context) @@ -235,7 +235,7 @@ private class ArtistSongViewHolder private constructor(private val binding: Item * @param song The new [Song] to bind. * @param listener An [SelectableListListener] to bind interactions to. */ - fun bind(song: Song, listener: SelectableListListener) { + fun bind(song: Song, listener: SelectableListListener) { listener.bind(song, this, menuButton = binding.songMenu) binding.songAlbumCover.bind(song) binding.songName.text = song.resolveName(binding.context) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt index 8775f4b9b..1bc9d25ad 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt @@ -30,6 +30,7 @@ import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.recycler.* +import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.inflater @@ -88,7 +89,7 @@ abstract class DetailAdapter( } /** An extended [SelectableListListener] for [DetailAdapter] implementations. */ - interface Listener : SelectableListListener { + interface Listener : SelectableListListener { // TODO: Split off into sub-listeners if a collapsing toolbar is implemented. /** * Called when the play button in a detail header is pressed, requesting that the current diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt index ad91fdade..175ac2706 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt @@ -33,11 +33,7 @@ import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.recycler.AlbumViewHolder import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter import org.oxycblt.auxio.list.recycler.SyncListDiffer -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Music -import org.oxycblt.auxio.music.MusicMode -import org.oxycblt.auxio.music.MusicParent -import org.oxycblt.auxio.music.Sort +import org.oxycblt.auxio.music.* import org.oxycblt.auxio.playback.formatDurationMs import org.oxycblt.auxio.playback.secsToMs import org.oxycblt.auxio.util.collectImmediately @@ -47,7 +43,7 @@ import org.oxycblt.auxio.util.collectImmediately * @author Alexander Capehart (OxygenCobalt) */ class AlbumListFragment : - ListFragment(), + ListFragment(), FastScrollRecyclerView.Listener, FastScrollRecyclerView.PopupProvider { private val homeModel: HomeViewModel by activityViewModels() @@ -125,13 +121,11 @@ class AlbumListFragment : homeModel.setFastScrolling(isFastScrolling) } - override fun onRealClick(music: Music) { - check(music is Album) { "Unexpected datatype: ${music::class.java}" } - navModel.exploreNavigateTo(music) + override fun onRealClick(item: Album) { + navModel.exploreNavigateTo(item) } - override fun onOpenMenu(item: Item, anchor: View) { - check(item is Album) { "Unexpected datatype: ${item::class.java}" } + override fun onOpenMenu(item: Album, anchor: View) { openMusicMenu(anchor, R.menu.menu_album_actions, item) } @@ -144,7 +138,7 @@ class AlbumListFragment : * A [SelectionIndicatorAdapter] that shows a list of [Album]s using [AlbumViewHolder]. * @param listener An [SelectableListListener] to bind interactions to. */ - private class AlbumAdapter(private val listener: SelectableListListener) : + private class AlbumAdapter(private val listener: SelectableListListener) : SelectionIndicatorAdapter() { private val differ = SyncListDiffer(this, AlbumViewHolder.DIFF_CALLBACK) 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 2dd51edf6..f87a1a458 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 @@ -32,7 +32,6 @@ import org.oxycblt.auxio.list.recycler.ArtistViewHolder import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter import org.oxycblt.auxio.list.recycler.SyncListDiffer import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Sort @@ -45,7 +44,7 @@ import org.oxycblt.auxio.util.nonZeroOrNull * @author Alexander Capehart (OxygenCobalt) */ class ArtistListFragment : - ListFragment(), + ListFragment(), FastScrollRecyclerView.PopupProvider, FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() @@ -100,13 +99,11 @@ class ArtistListFragment : homeModel.setFastScrolling(isFastScrolling) } - override fun onRealClick(music: Music) { - check(music is Artist) { "Unexpected datatype: ${music::class.java}" } - navModel.exploreNavigateTo(music) + override fun onRealClick(item: Artist) { + navModel.exploreNavigateTo(item) } - override fun onOpenMenu(item: Item, anchor: View) { - check(item is Artist) { "Unexpected datatype: ${item::class.java}" } + override fun onOpenMenu(item: Artist, anchor: View) { openMusicMenu(anchor, R.menu.menu_artist_actions, item) } @@ -119,7 +116,7 @@ class ArtistListFragment : * A [SelectionIndicatorAdapter] that shows a list of [Artist]s using [ArtistViewHolder]. * @param listener An [SelectableListListener] to bind interactions to. */ - private class ArtistAdapter(private val listener: SelectableListListener) : + private class ArtistAdapter(private val listener: SelectableListListener) : SelectionIndicatorAdapter() { private val differ = SyncListDiffer(this, ArtistViewHolder.DIFF_CALLBACK) 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 fa3484d90..50ed0fc04 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 @@ -32,7 +32,6 @@ import org.oxycblt.auxio.list.recycler.GenreViewHolder import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter import org.oxycblt.auxio.list.recycler.SyncListDiffer import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Sort @@ -44,7 +43,7 @@ import org.oxycblt.auxio.util.collectImmediately * @author Alexander Capehart (OxygenCobalt) */ class GenreListFragment : - ListFragment(), + ListFragment(), FastScrollRecyclerView.PopupProvider, FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() @@ -99,13 +98,11 @@ class GenreListFragment : homeModel.setFastScrolling(isFastScrolling) } - override fun onRealClick(music: Music) { - check(music is Genre) { "Unexpected datatype: ${music::class.java}" } - navModel.exploreNavigateTo(music) + override fun onRealClick(item: Genre) { + navModel.exploreNavigateTo(item) } - override fun onOpenMenu(item: Item, anchor: View) { - check(item is Genre) { "Unexpected datatype: ${item::class.java}" } + override fun onOpenMenu(item: Genre, anchor: View) { openMusicMenu(anchor, R.menu.menu_artist_actions, item) } @@ -118,7 +115,7 @@ class GenreListFragment : * A [SelectionIndicatorAdapter] that shows a list of [Genre]s using [GenreViewHolder]. * @param listener An [SelectableListListener] to bind interactions to. */ - private class GenreAdapter(private val listener: SelectableListListener) : + private class GenreAdapter(private val listener: SelectableListListener) : SelectionIndicatorAdapter() { private val differ = SyncListDiffer(this, GenreViewHolder.DIFF_CALLBACK) 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 0b85bcb5f..8b9db0d83 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 @@ -33,7 +33,6 @@ import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.recycler.SelectionIndicatorAdapter import org.oxycblt.auxio.list.recycler.SongViewHolder import org.oxycblt.auxio.list.recycler.SyncListDiffer -import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song @@ -48,7 +47,7 @@ import org.oxycblt.auxio.util.collectImmediately * @author Alexander Capehart (OxygenCobalt) */ class SongListFragment : - ListFragment(), + ListFragment(), FastScrollRecyclerView.PopupProvider, FastScrollRecyclerView.Listener { private val homeModel: HomeViewModel by activityViewModels() @@ -130,18 +129,16 @@ class SongListFragment : homeModel.setFastScrolling(isFastScrolling) } - override fun onRealClick(music: Music) { - check(music is Song) { "Unexpected datatype: ${music::class.java}" } + override fun onRealClick(item: Song) { when (Settings(requireContext()).libPlaybackMode) { - MusicMode.SONGS -> playbackModel.playFromAll(music) - MusicMode.ALBUMS -> playbackModel.playFromAlbum(music) - MusicMode.ARTISTS -> playbackModel.playFromArtist(music) - MusicMode.GENRES -> playbackModel.playFromGenre(music) + MusicMode.SONGS -> playbackModel.playFromAll(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> playbackModel.playFromGenre(item) } } - override fun onOpenMenu(item: Item, anchor: View) { - check(item is Song) { "Unexpected datatype: ${item::class.java}" } + override fun onOpenMenu(item: Song, anchor: View) { openMusicMenu(anchor, R.menu.menu_song_actions, item) } @@ -158,7 +155,7 @@ class SongListFragment : * A [SelectionIndicatorAdapter] that shows a list of [Song]s using [SongViewHolder]. * @param listener An [SelectableListListener] to bind interactions to. */ - private class SongAdapter(private val listener: SelectableListListener) : + private class SongAdapter(private val listener: SelectableListListener) : SelectionIndicatorAdapter() { private val differ = SyncListDiffer(this, SongViewHolder.DIFF_CALLBACK) diff --git a/app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt index 1e74ad396..76f7cf95d 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/Tab.kt @@ -17,7 +17,6 @@ package org.oxycblt.auxio.home.tabs -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.util.logE @@ -26,7 +25,7 @@ import org.oxycblt.auxio.util.logE * @param mode The type of list in the home view this instance corresponds to. * @author Alexander Capehart (OxygenCobalt) */ -sealed class Tab(open val mode: MusicMode) : Item { +sealed class Tab(open val mode: MusicMode) { /** * A visible tab. This will be visible in the home and tab configuration views. * @param mode The type of list in the home view this instance corresponds to. diff --git a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt index 756f8fea1..c60084cf9 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabAdapter.kt @@ -32,7 +32,7 @@ import org.oxycblt.auxio.util.inflater * A [RecyclerView.Adapter] that displays an array of [Tab]s open for configuration. * @param listener A [EditableListListener] for tab interactions. */ -class TabAdapter(private val listener: EditableListListener) : +class TabAdapter(private val listener: EditableListListener) : RecyclerView.Adapter() { /** The current array of [Tab]s. */ var tabs = arrayOf() @@ -93,7 +93,7 @@ class TabViewHolder private constructor(private val binding: ItemTabBinding) : * @param listener A [EditableListListener] to bind interactions to. */ @SuppressLint("ClickableViewAccessibility") - fun bind(tab: Tab, listener: EditableListListener) { + fun bind(tab: Tab, listener: EditableListListener) { listener.bind(tab, this, dragHandle = binding.tabDragHandle) binding.tabCheckBox.apply { // Update the CheckBox name to align with the mode diff --git a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt index 6c9706762..393a4e182 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt @@ -26,7 +26,6 @@ import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogTabsBinding import org.oxycblt.auxio.list.EditableListListener -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.ViewBindingDialogFragment import org.oxycblt.auxio.util.logD @@ -35,7 +34,8 @@ import org.oxycblt.auxio.util.logD * A [ViewBindingDialogFragment] that allows the user to modify the home [Tab] configuration. * @author Alexander Capehart (OxygenCobalt) */ -class TabCustomizeDialog : ViewBindingDialogFragment(), EditableListListener { +class TabCustomizeDialog : + ViewBindingDialogFragment(), EditableListListener { private val tabAdapter = TabAdapter(this) private var touchHelper: ItemTouchHelper? = null @@ -81,8 +81,7 @@ class TabCustomizeDialog : ViewBindingDialogFragment(), Edita binding.tabRecycler.adapter = null } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { - check(item is Tab) { "Unexpected datatype: ${item::class.java}" } + override fun onClick(item: Tab, viewHolder: RecyclerView.ViewHolder) { // We will need the exact index of the tab to update on in order to // notify the adapter of the change. val index = tabAdapter.tabs.indexOfFirst { it.mode == item.mode } diff --git a/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt b/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt index 250992d04..dee519263 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/ListFragment.kt @@ -37,7 +37,8 @@ import org.oxycblt.auxio.util.showToast * A Fragment containing a selectable list. * @author Alexander Capehart (OxygenCobalt) */ -abstract class ListFragment : SelectionFragment(), SelectableListListener { +abstract class ListFragment : + SelectionFragment(), SelectableListListener { protected val navModel: NavigationViewModel by activityViewModels() private var currentMenu: PopupMenu? = null @@ -50,12 +51,11 @@ abstract class ListFragment : SelectionFragment(), Selecta /** * Called when [onClick] is called, but does not result in the item being selected. This more or * less corresponds to an [onClick] implementation in a non-[ListFragment]. - * @param music The [Music] item that was clicked. + * @param item The [T] data of the item that was clicked. */ - abstract fun onRealClick(music: Music) + abstract fun onRealClick(item: T) - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { - check(item is Music) { "Unexpected datatype: ${item::class.simpleName}" } + override fun onClick(item: T, viewHolder: RecyclerView.ViewHolder) { if (selectionModel.selected.value.isNotEmpty()) { // Map clicking an item to selecting an item when items are already selected. selectionModel.select(item) @@ -65,8 +65,7 @@ abstract class ListFragment : SelectionFragment(), Selecta } } - override fun onSelect(item: Item) { - check(item is Music) { "Unexpected datatype: ${item::class.simpleName}" } + override fun onSelect(item: T) { selectionModel.select(item) } diff --git a/app/src/main/java/org/oxycblt/auxio/list/Listeners.kt b/app/src/main/java/org/oxycblt/auxio/list/Listeners.kt index c8f9ebb6d..1afa340c3 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/Listeners.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/Listeners.kt @@ -25,26 +25,22 @@ import androidx.recyclerview.widget.RecyclerView * A basic listener for list interactions. * @author Alexander Capehart (OxygenCobalt) */ -interface ClickableListListener { +interface ClickableListListener { /** - * Called when an [Item] in the list is clicked. - * @param item The [Item] that was clicked. + * Called when an item in the list is clicked. + * @param item The [T] item that was clicked. * @param viewHolder The [RecyclerView.ViewHolder] of the item that was clicked. */ - fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) + fun onClick(item: T, viewHolder: RecyclerView.ViewHolder) /** * Binds this instance to a list item. - * @param item The [Item] that this list entry is bound to. + * @param item The [T] to bind this item to. * @param viewHolder The [RecyclerView.ViewHolder] of the item that was clicked. * @param bodyView The [View] containing the main body of the list item. Any click events on * this [View] are routed to the listener. Defaults to the root view. */ - fun bind( - item: Item, - viewHolder: RecyclerView.ViewHolder, - bodyView: View = viewHolder.itemView - ) { + fun bind(item: T, viewHolder: RecyclerView.ViewHolder, bodyView: View = viewHolder.itemView) { bodyView.setOnClickListener { onClick(item, viewHolder) } } } @@ -53,7 +49,7 @@ interface ClickableListListener { * An extension of [ClickableListListener] that enables list editing functionality. * @author Alexander Capehart (OxygenCobalt) */ -interface EditableListListener : ClickableListListener { +interface EditableListListener : ClickableListListener { /** * Called when a [RecyclerView.ViewHolder] requests that it should be dragged. * @param viewHolder The [RecyclerView.ViewHolder] that should start being dragged. @@ -62,14 +58,14 @@ interface EditableListListener : ClickableListListener { /** * Binds this instance to a list item. - * @param item The [Item] that this list entry is bound to. + * @param item The [T] to bind this item to. * @param viewHolder The [RecyclerView.ViewHolder] to bind. * @param bodyView The [View] containing the main body of the list item. Any click events on * this [View] are routed to the listener. Defaults to the root view. * @param dragHandle A touchable [View]. Any drag on this view will start a drag event. */ fun bind( - item: Item, + item: T, viewHolder: RecyclerView.ViewHolder, bodyView: View = viewHolder.itemView, dragHandle: View @@ -89,30 +85,30 @@ interface EditableListListener : ClickableListListener { * An extension of [ClickableListListener] that enables menu and selection functionality. * @author Alexander Capehart (OxygenCobalt) */ -interface SelectableListListener : ClickableListListener { +interface SelectableListListener : ClickableListListener { /** - * Called when an [Item] in the list requests that a menu related to it should be opened. - * @param item The [Item] to show a menu for. + * Called when an item in the list requests that a menu related to it should be opened. + * @param item The [T] item to open a menu for. * @param anchor The [View] to anchor the menu to. */ - fun onOpenMenu(item: Item, anchor: View) + fun onOpenMenu(item: T, anchor: View) /** - * Called when an [Item] in the list requests that it be selected. - * @param item The [Item] to select. + * Called when an item in the list requests that it be selected. + * @param item The [T] item to select. */ - fun onSelect(item: Item) + fun onSelect(item: T) /** * Binds this instance to a list item. - * @param item The [Item] that this list entry is bound to. + * @param item The [T] to bind this item to. * @param viewHolder The [RecyclerView.ViewHolder] to bind. * @param bodyView The [View] containing the main body of the list item. Any click events on * this [View] are routed to the listener. Defaults to the root view. * @param menuButton A clickable [View]. Any click events on this [View] will open a menu. */ fun bind( - item: Item, + item: T, viewHolder: RecyclerView.ViewHolder, bodyView: View = viewHolder.itemView, menuButton: View diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt index ceb1fbf0b..9b07c339f 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/PlayingIndicatorAdapter.kt @@ -20,6 +20,7 @@ package org.oxycblt.auxio.list.recycler import android.view.View import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.list.Item +import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.util.logD /** @@ -31,7 +32,7 @@ abstract class PlayingIndicatorAdapter : RecyclerV // - The currently playing item, which is usually marked as "selected" and becomes accented. // - Whether playback is ongoing, which corresponds to whether the item's ImageGroup is // marked as "playing" or not. - private var currentItem: Item? = null + private var currentMusic: Music? = null private var isPlaying = false /** @@ -44,7 +45,7 @@ abstract class PlayingIndicatorAdapter : RecyclerV override fun onBindViewHolder(holder: VH, position: Int, payloads: List) { // Only try to update the playing indicator if the ViewHolder supports it if (holder is ViewHolder) { - holder.updatePlayingIndicator(currentList[position] == currentItem, isPlaying) + holder.updatePlayingIndicator(currentList[position] == currentMusic, isPlaying) } if (payloads.isEmpty()) { @@ -55,14 +56,14 @@ abstract class PlayingIndicatorAdapter : RecyclerV } /** * Update the currently playing item in the list. - * @param item The item currently being played, or null if it is not being played. + * @param music The [Music] currently being played, or null if it is not being played. * @param isPlaying Whether playback is ongoing or paused. */ - fun setPlayingItem(item: Item?, isPlaying: Boolean) { + fun setPlayingItem(music: Music?, isPlaying: Boolean) { var updatedItem = false - if (currentItem != item) { - val oldItem = currentItem - currentItem = item + if (currentMusic != music) { + val oldItem = currentMusic + currentMusic = music // Remove the playing indicator from the old item if (oldItem != null) { @@ -75,8 +76,8 @@ abstract class PlayingIndicatorAdapter : RecyclerV } // Enable the playing indicator on the new item - if (item != null) { - val pos = currentList.indexOfFirst { it == item } + if (music != null) { + val pos = currentList.indexOfFirst { it == music } if (pos > -1) { notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED) } else { @@ -93,8 +94,8 @@ abstract class PlayingIndicatorAdapter : RecyclerV // We may have already called notifyItemChanged before when checking // if the item was being played, so in that case we don't need to // update again here. - if (!updatedItem && item != null) { - val pos = currentList.indexOfFirst { it == item } + if (!updatedItem && music != null) { + val pos = currentList.indexOfFirst { it == music } if (pos > -1) { notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED) } else { diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt index 15628c41c..3aaac0609 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt @@ -26,10 +26,7 @@ import org.oxycblt.auxio.databinding.ItemParentBinding import org.oxycblt.auxio.databinding.ItemSongBinding import org.oxycblt.auxio.list.Header import org.oxycblt.auxio.list.SelectableListListener -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.music.* import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.getPlural import org.oxycblt.auxio.util.inflater @@ -45,7 +42,7 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) : * @param song The new [Song] to bind. * @param listener An [SelectableListListener] to bind interactions to. */ - fun bind(song: Song, listener: SelectableListListener) { + fun bind(song: Song, listener: SelectableListListener) { listener.bind(song, this, menuButton = binding.songMenu) binding.songAlbumCover.bind(song) binding.songName.text = song.resolveName(binding.context) @@ -92,7 +89,7 @@ class AlbumViewHolder private constructor(private val binding: ItemParentBinding * @param album The new [Album] to bind. * @param listener An [SelectableListListener] to bind interactions to. */ - fun bind(album: Album, listener: SelectableListListener) { + fun bind(album: Album, listener: SelectableListListener) { listener.bind(album, this, menuButton = binding.parentMenu) binding.parentImage.bind(album) binding.parentName.text = album.resolveName(binding.context) @@ -141,7 +138,7 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin * @param artist The new [Artist] to bind. * @param listener An [SelectableListListener] to bind interactions to. */ - fun bind(artist: Artist, listener: SelectableListListener) { + fun bind(artist: Artist, listener: SelectableListListener) { listener.bind(artist, this, menuButton = binding.parentMenu) binding.parentImage.bind(artist) binding.parentName.text = artist.resolveName(binding.context) @@ -200,7 +197,7 @@ class GenreViewHolder private constructor(private val binding: ItemParentBinding * @param genre The new [Genre] to bind. * @param listener An [SelectableListListener] to bind interactions to. */ - fun bind(genre: Genre, listener: SelectableListListener) { + fun bind(genre: Genre, listener: SelectableListListener) { listener.bind(genre, this, menuButton = binding.parentMenu) binding.parentImage.bind(genre) binding.parentName.text = genre.resolveName(binding.context) diff --git a/app/src/main/java/org/oxycblt/auxio/music/filesystem/MusicDirsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/filesystem/MusicDirsDialog.kt index e294b7915..4b297b7b0 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/filesystem/MusicDirsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/filesystem/MusicDirsDialog.kt @@ -85,9 +85,10 @@ class MusicDirsDialog : val dialog = it as AlertDialog dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.setOnClickListener { logD("Opening launcher") - val launcher = requireNotNull(openDocumentTreeLauncher) { - "Document tree launcher was not available" - } + val launcher = + requireNotNull(openDocumentTreeLauncher) { + "Document tree launcher was not available" + } try { launcher.launch(null) diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistChoiceAdapter.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistChoiceAdapter.kt index 71bdc09b4..857a55a1e 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistChoiceAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistChoiceAdapter.kt @@ -32,7 +32,7 @@ import org.oxycblt.auxio.util.inflater * @param listener A [ClickableListListener] to bind interactions to. * @author OxygenCobalt. */ -class ArtistChoiceAdapter(private val listener: ClickableListListener) : +class ArtistChoiceAdapter(private val listener: ClickableListListener) : RecyclerView.Adapter() { private var artists = listOf() @@ -67,7 +67,7 @@ class ArtistChoiceViewHolder(private val binding: ItemPickerChoiceBinding) : * @param artist The new [Artist] to bind. * @param listener A [ClickableListListener] to bind interactions to. */ - fun bind(artist: Artist, listener: ClickableListListener) { + fun bind(artist: Artist, listener: ClickableListListener) { listener.bind(artist, this) binding.pickerImage.bind(artist) binding.pickerName.text = artist.resolveName(binding.context) diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistNavigationPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistNavigationPickerDialog.kt index bebfd66da..99be53312 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistNavigationPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistNavigationPickerDialog.kt @@ -22,7 +22,6 @@ import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.DialogMusicPickerBinding -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.ui.NavigationViewModel @@ -41,9 +40,8 @@ class ArtistNavigationPickerDialog : ArtistPickerDialog() { super.onBindingCreated(binding, savedInstanceState) } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { + override fun onClick(item: Artist, viewHolder: RecyclerView.ViewHolder) { super.onClick(item, viewHolder) - check(item is Artist) { "Unexpected datatype: ${item::class.simpleName}" } // User made a choice, navigate to it. navModel.exploreNavigateTo(item) } diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPickerDialog.kt index 0bf780537..0e537e3ea 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPickerDialog.kt @@ -26,7 +26,6 @@ import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogMusicPickerBinding import org.oxycblt.auxio.list.ClickableListListener -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.ui.ViewBindingDialogFragment import org.oxycblt.auxio.util.collectImmediately @@ -38,7 +37,7 @@ import org.oxycblt.auxio.util.collectImmediately * @author Alexander Capehart (OxygenCobalt) */ abstract class ArtistPickerDialog : - ViewBindingDialogFragment(), ClickableListListener { + ViewBindingDialogFragment(), ClickableListListener { protected val pickerModel: PickerViewModel by viewModels() // Okay to leak this since the Listener will not be called until after initialization. private val artistAdapter = ArtistChoiceAdapter(@Suppress("LeakingThis") this) @@ -68,7 +67,7 @@ abstract class ArtistPickerDialog : binding.pickerRecycler.adapter = null } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { + override fun onClick(item: Artist, viewHolder: RecyclerView.ViewHolder) { findNavController().navigateUp() } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPlaybackPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPlaybackPickerDialog.kt index 24ed8af43..186404a9d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPlaybackPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/ArtistPlaybackPickerDialog.kt @@ -21,11 +21,12 @@ import android.os.Bundle import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.DialogMusicPickerBinding -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.util.androidActivityViewModels +import org.oxycblt.auxio.util.requireIs +import org.oxycblt.auxio.util.unlikelyToBeNull /** * An [ArtistPickerDialog] intended for when [Artist] playback is ambiguous. @@ -42,12 +43,10 @@ class ArtistPlaybackPickerDialog : ArtistPickerDialog() { super.onBindingCreated(binding, savedInstanceState) } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { + override fun onClick(item: Artist, viewHolder: RecyclerView.ViewHolder) { super.onClick(item, viewHolder) // User made a choice, play the given song from that artist. - check(item is Artist) { "Unexpected datatype: ${item::class.simpleName}" } - val song = pickerModel.currentItem.value - check(song is Song) { "Unexpected datatype: ${item::class.simpleName}" } + val song = requireIs(unlikelyToBeNull(pickerModel.currentItem.value)) playbackModel.playFromArtist(song, item) } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/GenreChoiceAdapter.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/GenreChoiceAdapter.kt index 49b5c758a..b2ddef425 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/GenreChoiceAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/GenreChoiceAdapter.kt @@ -32,7 +32,7 @@ import org.oxycblt.auxio.util.inflater * @param listener A [ClickableListListener] to bind interactions to. * @author OxygenCobalt. */ -class GenreChoiceAdapter(private val listener: ClickableListListener) : +class GenreChoiceAdapter(private val listener: ClickableListListener) : RecyclerView.Adapter() { private var genres = listOf() @@ -67,7 +67,7 @@ class GenreChoiceViewHolder(private val binding: ItemPickerChoiceBinding) : * @param genre The new [Genre] to bind. * @param listener A [ClickableListListener] to bind interactions to. */ - fun bind(genre: Genre, listener: ClickableListListener) { + fun bind(genre: Genre, listener: ClickableListListener) { listener.bind(genre, this) binding.pickerImage.bind(genre) binding.pickerName.text = genre.resolveName(binding.context) diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePlaybackPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePlaybackPickerDialog.kt index 0a197ab0e..dc7b3d6af 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePlaybackPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePlaybackPickerDialog.kt @@ -27,20 +27,21 @@ import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogMusicPickerBinding import org.oxycblt.auxio.list.ClickableListListener -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.ViewBindingDialogFragment import org.oxycblt.auxio.util.androidActivityViewModels import org.oxycblt.auxio.util.collectImmediately +import org.oxycblt.auxio.util.requireIs +import org.oxycblt.auxio.util.unlikelyToBeNull /** * A picker [ViewBindingDialogFragment] intended for when [Genre] playback is ambiguous. * @author Alexander Capehart (OxygenCobalt) */ class GenrePlaybackPickerDialog : - ViewBindingDialogFragment(), ClickableListListener { + ViewBindingDialogFragment(), ClickableListListener { private val pickerModel: PickerViewModel by viewModels() private val playbackModel: PlaybackViewModel by androidActivityViewModels() // Information about what Song to show choices for is initially within the navigation arguments @@ -75,11 +76,9 @@ class GenrePlaybackPickerDialog : binding.pickerRecycler.adapter = null } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { + override fun onClick(item: Genre, viewHolder: RecyclerView.ViewHolder) { // User made a choice, play the given song from that genre. - check(item is Genre) { "Unexpected datatype: ${item::class.simpleName}" } - val song = pickerModel.currentItem.value - check(song is Song) { "Unexpected datatype: ${item::class.simpleName}" } + val song = requireIs(unlikelyToBeNull(pickerModel.currentItem.value)) playbackModel.playFromGenre(song, item) } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index baa4aa76c..cb4ca8a58 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -41,7 +41,7 @@ import org.oxycblt.auxio.util.inflater * @param listener A [EditableListListener] to bind interactions to. * @author Alexander Capehart (OxygenCobalt) */ -class QueueAdapter(private val listener: EditableListListener) : +class QueueAdapter(private val listener: EditableListListener) : RecyclerView.Adapter() { private var differ = SyncListDiffer(this, QueueSongViewHolder.DIFF_CALLBACK) // Since PlayingIndicator adapter relies on an item value, we cannot use it for this @@ -178,7 +178,7 @@ class QueueSongViewHolder private constructor(private val binding: ItemQueueSong * @param listener A [EditableListListener] to bind interactions to. */ @SuppressLint("ClickableViewAccessibility") - fun bind(song: Song, listener: EditableListListener) { + fun bind(song: Song, listener: EditableListListener) { listener.bind(song, this, bodyView, binding.songDragHandle) binding.songAlbumCover.bind(song) binding.songName.text = song.resolveName(binding.context) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index 826d04270..50326e156 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -27,7 +27,6 @@ import androidx.recyclerview.widget.RecyclerView import kotlin.math.min import org.oxycblt.auxio.databinding.FragmentQueueBinding import org.oxycblt.auxio.list.EditableListListener -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.ViewBindingFragment @@ -39,7 +38,7 @@ import org.oxycblt.auxio.util.logD * A [ViewBindingFragment] that displays an editable queue. * @author Alexander Capehart (OxygenCobalt) */ -class QueueFragment : ViewBindingFragment(), EditableListListener { +class QueueFragment : ViewBindingFragment(), EditableListListener { private val queueModel: QueueViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by androidActivityViewModels() private val queueAdapter = QueueAdapter(this) @@ -81,7 +80,7 @@ class QueueFragment : ViewBindingFragment(), EditableListL binding.queueRecycler.adapter = null } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { + override fun onClick(item: Song, viewHolder: RecyclerView.ViewHolder) { queueModel.goto(viewHolder.bindingAdapterPosition) } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt index 7346ac7eb..79d403233 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt @@ -127,11 +127,9 @@ class ReplayGainAudioProcessor(private val context: Context) : // User wants track gain to be preferred. Default to album gain only if // there is no track gain. ReplayGainMode.TRACK -> gain.track == 0f - // User wants album gain to be preferred. Default to track gain only if // here is no album gain. ReplayGainMode.ALBUM -> gain.album != 0f - // User wants album gain to be used when in an album, track gain otherwise. ReplayGainMode.DYNAMIC -> playbackManager.parent is Album && diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt index a1260859b..6653b8e24 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchAdapter.kt @@ -22,17 +22,14 @@ import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.list.* import org.oxycblt.auxio.list.recycler.* -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.music.* /** * An adapter that displays search results. * @param listener An [SelectableListListener] to bind interactions to. * @author Alexander Capehart (OxygenCobalt) */ -class SearchAdapter(private val listener: SelectableListListener) : +class SearchAdapter(private val listener: SelectableListListener) : SelectionIndicatorAdapter(), AuxioRecyclerView.SpanSizeLookup { private val differ = AsyncListDiffer(this, DIFF_CALLBACK) 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 f9055e96d..59f622cf5 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -50,7 +50,7 @@ import org.oxycblt.auxio.util.* * * @author Alexander Capehart (OxygenCobalt) */ -class SearchFragment : ListFragment() { +class SearchFragment : ListFragment() { private val searchModel: SearchViewModel by androidViewModels() private val searchAdapter = SearchAdapter(this) private var imm: InputMethodManager? = null @@ -134,26 +134,25 @@ class SearchFragment : ListFragment() { return false } - override fun onRealClick(music: Music) { - when (music) { + override fun onRealClick(item: Music) { + when (item) { is Song -> when (Settings(requireContext()).libPlaybackMode) { - MusicMode.SONGS -> playbackModel.playFromAll(music) - MusicMode.ALBUMS -> playbackModel.playFromAlbum(music) - MusicMode.ARTISTS -> playbackModel.playFromArtist(music) - MusicMode.GENRES -> playbackModel.playFromGenre(music) + MusicMode.SONGS -> playbackModel.playFromAll(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> playbackModel.playFromGenre(item) } - is MusicParent -> navModel.exploreNavigateTo(music) + is MusicParent -> navModel.exploreNavigateTo(item) } } - override fun onOpenMenu(item: Item, anchor: View) { + override fun onOpenMenu(item: Music, anchor: View) { when (item) { is Song -> openMusicMenu(anchor, R.menu.menu_song_actions, item) is Album -> openMusicMenu(anchor, R.menu.menu_album_actions, item) is Artist -> openMusicMenu(anchor, R.menu.menu_artist_actions, item) is Genre -> openMusicMenu(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/NavigationViewModel.kt b/app/src/main/java/org/oxycblt/auxio/ui/NavigationViewModel.kt index 2ea31a0c4..becc077ad 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/NavigationViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/NavigationViewModel.kt @@ -79,15 +79,15 @@ class NavigationViewModel : ViewModel() { /** * Navigate to a given [Music] item. Will do nothing if already navigating. - * @param item The [Music] to navigate to. + * @param music The [Music] to navigate to. */ - fun exploreNavigateTo(item: Music) { + fun exploreNavigateTo(music: Music) { if (_exploreNavigationItem.value != null) { logD("Already navigating, not doing explore action") return } - logD("Navigating to ${item.rawName}") - _exploreNavigationItem.value = item + logD("Navigating to ${music.rawName}") + _exploreNavigationItem.value = music } /** diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt index 1be63d5df..cfa6525bd 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/Accent.kt @@ -19,7 +19,6 @@ package org.oxycblt.auxio.ui.accent import android.os.Build import org.oxycblt.auxio.R -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.util.logW private val ACCENT_NAMES = @@ -112,7 +111,7 @@ private val ACCENT_PRIMARY_COLORS = * @param index The unique number for this particular accent. * @author Alexander Capehart (OxygenCobalt) */ -class Accent private constructor(val index: Int) : Item { +class Accent private constructor(val index: Int) { /** The name of this [Accent]. */ val name: Int get() = ACCENT_NAMES[index] diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt index a4c1e6015..46e7e66fc 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt @@ -33,7 +33,7 @@ import org.oxycblt.auxio.util.inflater * @param listener A [ClickableListListener] to bind interactions to. * @author Alexander Capehart (OxygenCobalt) */ -class AccentAdapter(private val listener: ClickableListListener) : +class AccentAdapter(private val listener: ClickableListListener) : RecyclerView.Adapter() { /** The currently selected [Accent]. */ var selectedAccent: Accent? = null @@ -93,7 +93,7 @@ class AccentViewHolder private constructor(private val binding: ItemAccentBindin * @param accent The new [Accent] to bind. * @param listener A [ClickableListListener] to bind interactions to. */ - fun bind(accent: Accent, listener: ClickableListListener) { + fun bind(accent: Accent, listener: ClickableListListener) { listener.bind(accent, this, binding.accent) binding.accent.apply { // Add a Tooltip based on the content description so that the purpose of this diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt index 2cb3c93d4..f4d6237cc 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt @@ -25,7 +25,6 @@ import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogAccentBinding import org.oxycblt.auxio.list.ClickableListListener -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.ViewBindingDialogFragment import org.oxycblt.auxio.util.logD @@ -36,7 +35,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull * @author Alexander Capehart (OxygenCobalt) */ class AccentCustomizeDialog : - ViewBindingDialogFragment(), ClickableListListener { + ViewBindingDialogFragment(), ClickableListListener { private var accentAdapter = AccentAdapter(this) override fun onCreateBinding(inflater: LayoutInflater) = DialogAccentBinding.inflate(inflater) @@ -80,8 +79,7 @@ class AccentCustomizeDialog : binding.accentRecycler.adapter = null } - override fun onClick(item: Item, viewHolder: RecyclerView.ViewHolder) { - check(item is Accent) { "Unexpected datatype: ${item::class.java}" } + override fun onClick(item: Accent, viewHolder: RecyclerView.ViewHolder) { accentAdapter.setSelectedAccent(item) } diff --git a/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt index dd386e770..dfaca9127 100644 --- a/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt @@ -33,6 +33,17 @@ fun unlikelyToBeNull(value: T?) = value!! } +/** + * Require that the given data is a specific type [T]. + * @param data The data to check. + * @return A data casted to [T]. + * @throws IllegalStateException If the data cannot be casted to [T]. + */ +inline fun requireIs(data: Any): T { + check(data is T) { "Unexpected datatype: ${data::class.simpleName}" } + return data +} + /** * Aliases a check to ensure that the given number is non-zero. * @return The given number if it's non-zero, null otherwise.