From 717f49fc20946ab5ea87b27361f57396302b72f4 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Wed, 14 Sep 2022 19:48:39 -0600 Subject: [PATCH] music: add picker dialog Add a dialog for picking a genre from several choices. This basically completes multi-genre support in Auxio, save more internal reworks. Note that it is extremely likely that the "Play from genre" setting will be removed soon. This feature has made me realize that such does not many any real sense, as genres are more semantically similar to playlists than artists or albums. This implementation only exists to make multi-artist support an easy plug-and-play operation. Resolves #201 --- .../auxio/detail/AlbumDetailFragment.kt | 24 +++-- .../auxio/detail/ArtistDetailFragment.kt | 24 +++-- .../oxycblt/auxio/detail/DetailViewModel.kt | 2 +- .../auxio/detail/GenreDetailFragment.kt | 25 +++-- .../oxycblt/auxio/home/AdaptiveTabStrategy.kt | 2 +- .../org/oxycblt/auxio/home/HomeFragment.kt | 4 +- .../org/oxycblt/auxio/home/HomeViewModel.kt | 4 +- .../auxio/home/list/AlbumListFragment.kt | 4 +- .../auxio/home/list/ArtistListFragment.kt | 4 +- .../auxio/home/list/GenreListFragment.kt | 4 +- .../auxio/home/list/SongListFragment.kt | 22 ++++- .../java/org/oxycblt/auxio/home/tabs/Tab.kt | 2 +- .../org/oxycblt/auxio/home/tabs/TabAdapter.kt | 2 +- .../auxio/home/tabs/TabCustomizeDialog.kt | 2 +- .../auxio/image/extractor/Components.kt | 2 +- .../java/org/oxycblt/auxio/music/Music.kt | 43 ++++----- .../oxycblt/auxio/music/{ui => }/MusicMode.kt | 2 +- .../java/org/oxycblt/auxio/music/MusicUtil.kt | 1 - .../org/oxycblt/auxio/music/{ui => }/Sort.kt | 10 +- .../{settings => dirs}/MusicDirAdapter.kt | 2 +- .../music/{settings => dirs}/MusicDirs.kt | 2 +- .../{settings => dirs}/MusicDirsDialog.kt | 2 +- .../auxio/music/picker/GenreChoiceAdapter.kt | 71 ++++++++++++++ .../auxio/music/picker/GenrePickerDialog.kt | 95 +++++++++++++++++++ .../oxycblt/auxio/music/picker/PickerMode.kt | 26 +++++ .../auxio/music/picker/PickerViewModel.kt | 52 ++++++++++ .../SeparatorsDialog.kt | 3 +- .../org/oxycblt/auxio/music/system/Indexer.kt | 2 +- .../auxio/playback/PlaybackViewModel.kt | 17 +--- .../replaygain/PreAmpCustomizeDialog.kt | 1 - .../oxycblt/auxio/search/SearchFragment.kt | 20 +++- .../oxycblt/auxio/search/SearchViewModel.kt | 4 +- .../org/oxycblt/auxio/settings/Settings.kt | 6 +- .../main/res/layout/dialog_music_picker.xml | 9 ++ .../main/res/layout/item_picker_choice.xml | 35 +++++++ app/src/main/res/navigation/nav_main.xml | 20 +++- app/src/main/res/values/strings.xml | 7 +- 37 files changed, 451 insertions(+), 106 deletions(-) rename app/src/main/java/org/oxycblt/auxio/music/{ui => }/MusicMode.kt (97%) rename app/src/main/java/org/oxycblt/auxio/music/{ui => }/Sort.kt (98%) rename app/src/main/java/org/oxycblt/auxio/music/{settings => dirs}/MusicDirAdapter.kt (98%) rename app/src/main/java/org/oxycblt/auxio/music/{settings => dirs}/MusicDirs.kt (95%) rename app/src/main/java/org/oxycblt/auxio/music/{settings => dirs}/MusicDirsDialog.kt (99%) create mode 100644 app/src/main/java/org/oxycblt/auxio/music/picker/GenreChoiceAdapter.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/music/picker/GenrePickerDialog.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/music/picker/PickerMode.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/music/picker/PickerViewModel.kt rename app/src/main/java/org/oxycblt/auxio/music/{settings => separators}/SeparatorsDialog.kt (97%) create mode 100644 app/src/main/res/layout/dialog_music_picker.xml create mode 100644 app/src/main/res/layout/item_picker_choice.xml 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 9a1cf78a4..06af21820 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -29,16 +29,20 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearSmoothScroller import com.google.android.material.transition.MaterialSharedAxis +import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.AlbumDetailAdapter import org.oxycblt.auxio.music.Album 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.Song -import org.oxycblt.auxio.music.ui.Sort +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.recycler.Item import org.oxycblt.auxio.util.canScroll @@ -125,11 +129,19 @@ class AlbumDetailFragment : override fun onItemClick(item: Item) { check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } - val playbackMode = settings.detailPlaybackMode - if (playbackMode != null) { - playbackModel.play(item, playbackMode) - } else { - playbackModel.playFromAlbum(item) + when (settings.detailPlaybackMode) { + null, MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.SONGS -> playbackModel.play(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> if (item.genres.size > 1) { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.showGenrePickerDialog(item.uid, PickerMode.PLAY) + ) + ) + } else { + playbackModel.playFromGenre(item, item.genres[0]) + } } } 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 93361c660..5f9e920cb 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -26,6 +26,7 @@ import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.transition.MaterialSharedAxis +import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.ArtistDetailAdapter @@ -33,10 +34,13 @@ import org.oxycblt.auxio.detail.recycler.DetailAdapter import org.oxycblt.auxio.music.Album 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.Song -import org.oxycblt.auxio.music.ui.Sort +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.recycler.Item import org.oxycblt.auxio.util.collect @@ -117,11 +121,19 @@ class ArtistDetailFragment : override fun onItemClick(item: Item) { when (item) { is Song -> { - val playbackMode = settings.detailPlaybackMode - if (playbackMode != null) { - playbackModel.play(item, playbackMode) - } else { - playbackModel.playFromArtist(item) + when (settings.detailPlaybackMode) { + null, MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.SONGS -> playbackModel.play(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.GENRES -> if (item.genres.size > 1) { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.showGenrePickerDialog(item.uid, PickerMode.PLAY) + ) + ) + } else { + playbackModel.playFromGenre(item, item.genres[0]) + } } } is Album -> navModel.exploreNavigateTo(item) diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt index 7dbdc7e02..60e00d535 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -38,7 +38,7 @@ import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.ReleaseType import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.ui.Sort +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.recycler.Header import org.oxycblt.auxio.ui.recycler.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 ee9f0319b..e2f11d58d 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -26,6 +26,7 @@ import androidx.fragment.app.activityViewModels import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.transition.MaterialSharedAxis +import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentDetailBinding import org.oxycblt.auxio.detail.recycler.DetailAdapter @@ -34,10 +35,13 @@ import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.ui.Sort +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.recycler.Item import org.oxycblt.auxio.util.collect @@ -117,11 +121,20 @@ class GenreDetailFragment : override fun onItemClick(item: Item) { check(item is Song) { "Unexpected datatype: ${item::class.simpleName}" } - val playbackMode = settings.detailPlaybackMode - if (playbackMode != null) { - playbackModel.play(item, playbackMode) - } else { - playbackModel.playFromGenre(item, unlikelyToBeNull(detailModel.currentGenre.value)) + when (settings.detailPlaybackMode) { + null -> playbackModel.playFromGenre(item, unlikelyToBeNull(detailModel.currentGenre.value)) + MusicMode.SONGS -> playbackModel.play(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> if (item.genres.size > 1) { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.showGenrePickerDialog(item.uid, PickerMode.PLAY) + ) + ) + } else { + playbackModel.playFromGenre(item, item.genres[0]) + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/home/AdaptiveTabStrategy.kt b/app/src/main/java/org/oxycblt/auxio/home/AdaptiveTabStrategy.kt index d5e9d6e26..148d37e89 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/AdaptiveTabStrategy.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/AdaptiveTabStrategy.kt @@ -21,7 +21,7 @@ import android.content.Context import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import org.oxycblt.auxio.R -import org.oxycblt.auxio.music.ui.MusicMode +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.util.logD /** diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index 237949314..d46d9db4c 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -48,11 +48,11 @@ import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.system.Indexer -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.MainNavigationAction import org.oxycblt.auxio.ui.NavigationViewModel diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt index 94b5364b8..9238af08f 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt @@ -26,10 +26,10 @@ import org.oxycblt.auxio.home.tabs.Tab import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.util.application import org.oxycblt.auxio.util.logD 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 2722abe33..3ff5a0058 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 @@ -24,11 +24,11 @@ import android.view.ViewGroup import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.music.Album +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.formatDurationMs import org.oxycblt.auxio.music.secsToMs -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.ui.recycler.AlbumViewHolder import org.oxycblt.auxio.ui.recycler.IndicatorAdapter import org.oxycblt.auxio.ui.recycler.Item 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 b18c0b479..ec77ca008 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 @@ -23,10 +23,10 @@ import android.view.ViewGroup import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.music.Artist +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.formatDurationMs -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.ui.recycler.ArtistViewHolder import org.oxycblt.auxio.ui.recycler.IndicatorAdapter import org.oxycblt.auxio.ui.recycler.Item 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 f246c0a59..f64b19204 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 @@ -23,10 +23,10 @@ import android.view.ViewGroup import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.music.Genre +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.formatDurationMs -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.ui.recycler.GenreViewHolder import org.oxycblt.auxio.ui.recycler.IndicatorAdapter import org.oxycblt.auxio.ui.recycler.Item 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 3f4e11059..986c6a70d 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 @@ -21,15 +21,18 @@ import android.os.Bundle import android.text.format.DateUtils import android.view.View import android.view.ViewGroup +import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.formatDurationMs +import org.oxycblt.auxio.music.picker.PickerMode import org.oxycblt.auxio.music.secsToMs -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.settings.Settings +import org.oxycblt.auxio.ui.MainNavigationAction import org.oxycblt.auxio.ui.recycler.IndicatorAdapter import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener @@ -109,7 +112,20 @@ class SongListFragment : HomeListFragment() { override fun onItemClick(item: Item) { check(item is Song) { "Unexpected datatype: ${item::class.java}" } - playbackModel.play(item, settings.libPlaybackMode) + when (settings.libPlaybackMode) { + MusicMode.SONGS -> playbackModel.play(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> if (item.genres.size > 1) { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.showGenrePickerDialog(item.uid, PickerMode.PLAY) + ) + ) + } else { + playbackModel.playFromGenre(item, item.genres[0]) + } + } } override fun onOpenMenu(item: Item, anchor: View) { 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 733afca7f..e0726e3ff 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 @@ -21,7 +21,7 @@ import org.oxycblt.auxio.home.tabs.Tab.Companion.fromSequence import org.oxycblt.auxio.home.tabs.Tab.Companion.toSequence import org.oxycblt.auxio.home.tabs.Tab.Invisible import org.oxycblt.auxio.home.tabs.Tab.Visible -import org.oxycblt.auxio.music.ui.MusicMode +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.util.logE /** 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 256a914a8..89e0cf9ed 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 @@ -24,7 +24,7 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.ItemTabBinding -import org.oxycblt.auxio.music.ui.MusicMode +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.ui.recycler.DialogViewHolder import org.oxycblt.auxio.util.inflater 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 b3a3aaac1..6ec8780c9 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 @@ -25,7 +25,7 @@ import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogTabsBinding -import org.oxycblt.auxio.music.ui.MusicMode +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.fragment.ViewBindingDialogFragment import org.oxycblt.auxio.util.context diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt index 20d4ad4ee..c7ba9fddb 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt @@ -34,7 +34,7 @@ import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.ui.Sort +import org.oxycblt.auxio.music.Sort import kotlin.math.min /** A basic keyer for music data. */ diff --git a/app/src/main/java/org/oxycblt/auxio/music/Music.kt b/app/src/main/java/org/oxycblt/auxio/music/Music.kt index 6db26418a..b22766bcb 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Music.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Music.kt @@ -26,8 +26,6 @@ import kotlinx.parcelize.Parcelize import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.music.Date.Companion.from -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.util.inRangeOrNull import org.oxycblt.auxio.util.nonZeroOrNull @@ -105,43 +103,34 @@ sealed class Music : Item { */ @Parcelize class UID private constructor( - private val isMusicBrainz: Boolean, + private val format: Format, private val mode: MusicMode, private val uuid: UUID ) : Parcelable { // Cache the hashCode for speed - @IgnoredOnParcel private val hashCode: Int + @IgnoredOnParcel private var hashCode = format.hashCode() init { - var result = isMusicBrainz.hashCode() - result = 31 * result + mode.hashCode() - result = 31 * result + uuid.hashCode() - hashCode = result + hashCode = 31 * hashCode + mode.hashCode() + hashCode = 31 * hashCode + uuid.hashCode() } override fun hashCode() = hashCode override fun equals(other: Any?) = other is UID && - isMusicBrainz == other.isMusicBrainz && + format == other.format && mode == other.mode && uuid == other.uuid - override fun toString(): String { - // Format comes first, delimited by a ":". - val format = if (isMusicBrainz) { - FORMAT_MUSICBRAINZ - } else { - FORMAT_AUXIO - } + // UID string format is roughly: + // format_namespace:music_mode_int-uuid + override fun toString() = "${format.namespace}:${mode.intCode.toString(16)}-$uuid" - // Instead of making new string values for the mode, be lazy and just append it's - // intCode in front of the UUID. - return "$format:${mode.intCode.toString(16)}-$uuid" + private enum class Format(val namespace: String) { + AUXIO("org.oxycblt.auxio"), + MUSICBRAINZ("org.musicbrainz") } companion object { - private const val FORMAT_AUXIO = "org.oxycblt.auxio" - private const val FORMAT_MUSICBRAINZ = "org.musicbrainz" - /** Parse a [UID] from the string [uid]. Returns null if not valid. */ fun fromString(uid: String): UID? { val split = uid.split(':', limit = 2) @@ -149,9 +138,9 @@ sealed class Music : Item { return null } - val isMusicBrainz = when (split[0]) { - FORMAT_MUSICBRAINZ -> true - FORMAT_AUXIO -> false + val format = when (split[0]) { + Format.AUXIO.namespace -> Format.AUXIO + Format.MUSICBRAINZ.namespace -> Format.MUSICBRAINZ else -> return null } @@ -163,7 +152,7 @@ sealed class Music : Item { val mode = MusicMode.fromInt(ids[0].toIntOrNull(16) ?: return null) ?: return null val uuid = UUID.fromString(ids[1]) - return UID(isMusicBrainz, mode, uuid) + return UID(format, mode, uuid) } /** @@ -178,7 +167,7 @@ sealed class Music : Item { val digest = MessageDigest.getInstance("MD5") updates(digest) val uuid = digest.digest().toUuid() - return UID(false, mode, uuid) + return UID(Format.AUXIO, mode, uuid) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/ui/MusicMode.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicMode.kt similarity index 97% rename from app/src/main/java/org/oxycblt/auxio/music/ui/MusicMode.kt rename to app/src/main/java/org/oxycblt/auxio/music/MusicMode.kt index 90663d641..9cbabd80d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/ui/MusicMode.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicMode.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.ui +package org.oxycblt.auxio.music import org.oxycblt.auxio.IntegerTable diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt index cbf859da3..aa9160871 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt @@ -26,7 +26,6 @@ import android.provider.MediaStore import android.text.format.DateUtils import org.oxycblt.auxio.R import org.oxycblt.auxio.util.logD -import java.util.UUID /** Shortcut for making a [ContentResolver] query with less superfluous arguments. */ fun ContentResolver.queryCursor( diff --git a/app/src/main/java/org/oxycblt/auxio/music/ui/Sort.kt b/app/src/main/java/org/oxycblt/auxio/music/Sort.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/ui/Sort.kt rename to app/src/main/java/org/oxycblt/auxio/music/Sort.kt index 9f4105fce..35ba7c4c2 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/ui/Sort.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Sort.kt @@ -15,18 +15,12 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.ui +package org.oxycblt.auxio.music import androidx.annotation.IdRes import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Date -import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Music -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.ui.Sort.Mode +import org.oxycblt.auxio.music.Sort.Mode /** * Represents the sort modes used in Auxio. diff --git a/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt b/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt rename to app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt index f39b64fad..8b3156dab 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.settings +package org.oxycblt.auxio.music.dirs import android.view.View import android.view.ViewGroup diff --git a/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt b/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt similarity index 95% rename from app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt rename to app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt index 61db8e10c..748bd43c1 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.settings +package org.oxycblt.auxio.music.dirs import org.oxycblt.auxio.music.Directory diff --git a/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt similarity index 99% rename from app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt rename to app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt index 74ac2c280..582183487 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.settings +package org.oxycblt.auxio.music.dirs import android.net.Uri import android.os.Bundle 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 new file mode 100644 index 000000000..90e3b9aac --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/GenreChoiceAdapter.kt @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022 Auxio Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.music.picker + +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.oxycblt.auxio.databinding.ItemPickerChoiceBinding +import org.oxycblt.auxio.music.Genre +import org.oxycblt.auxio.ui.recycler.DialogViewHolder +import org.oxycblt.auxio.ui.recycler.ItemClickListener +import org.oxycblt.auxio.util.context +import org.oxycblt.auxio.util.inflater + +/** + * The adapter that displays a list of genre choices in the picker UI. + */ +class GenreChoiceAdapter(private val listener: ItemClickListener) : RecyclerView.Adapter() { + private var genres = listOf() + + override fun getItemCount() = genres.size + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = + GenreChoiceViewHolder.new(parent) + + override fun onBindViewHolder(holder: GenreChoiceViewHolder, position: Int) = + holder.bind(genres[position], listener) + + fun submitList(newGenres: List) { + if (newGenres != genres) { + genres = newGenres + + @Suppress("NotifyDataSetChanged") + notifyDataSetChanged() + } + } +} + +/** + * The ViewHolder that displays a genre choice. Smaller than other parent items due to dialog + * constraints. + */ +class GenreChoiceViewHolder(private val binding: ItemPickerChoiceBinding) : DialogViewHolder(binding.root) { + fun bind(genre: Genre, listener: ItemClickListener) { + binding.pickerImage.bind(genre) + binding.pickerName.text = genre.resolveName(binding.context) + binding.root.setOnClickListener { + listener.onItemClick(genre) + } + } + + companion object { + fun new(parent: View) = + GenreChoiceViewHolder(ItemPickerChoiceBinding.inflate(parent.context.inflater)) + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePickerDialog.kt new file mode 100644 index 000000000..59aa87d64 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/GenrePickerDialog.kt @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022 Auxio Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.music.picker + +import android.os.Bundle +import android.view.LayoutInflater +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs +import org.oxycblt.auxio.R +import org.oxycblt.auxio.databinding.DialogMusicPickerBinding +import org.oxycblt.auxio.music.Genre +import org.oxycblt.auxio.playback.PlaybackViewModel +import org.oxycblt.auxio.ui.NavigationViewModel +import org.oxycblt.auxio.ui.fragment.ViewBindingDialogFragment +import org.oxycblt.auxio.ui.recycler.Item +import org.oxycblt.auxio.ui.recycler.ItemClickListener +import org.oxycblt.auxio.util.androidActivityViewModels +import org.oxycblt.auxio.util.collectImmediately +import org.oxycblt.auxio.util.unlikelyToBeNull + +/** + * A dialog that shows several genre options if the result of an genre-reliant operation is + * ambiguous. + * @author OxygenCobalt + */ +class GenrePickerDialog : ViewBindingDialogFragment(), ItemClickListener { + private val pickerModel: PickerViewModel by viewModels() + private val playbackModel: PlaybackViewModel by androidActivityViewModels() + private val navModel: NavigationViewModel by activityViewModels() + + private val args: GenrePickerDialogArgs by navArgs() + private val adapter = GenreChoiceAdapter(this) + + override fun onCreateBinding(inflater: LayoutInflater) = + DialogMusicPickerBinding.inflate(inflater) + + override fun onConfigDialog(builder: AlertDialog.Builder) { + builder + .setTitle( + when (args.pickerMode) { + PickerMode.GO -> R.string.lbl_go_genre + PickerMode.PLAY -> R.string.lbl_play_genre + } + ) + .setNegativeButton(R.string.lbl_cancel, null) + } + + override fun onBindingCreated(binding: DialogMusicPickerBinding, savedInstanceState: Bundle?) { + pickerModel.setSongUid(args.songUid) + + binding.pickerRecycler.adapter = adapter + + collectImmediately(pickerModel.currentSong) { song -> + if (song != null) { + adapter.submitList(song.genres) + } else { + findNavController().navigateUp() + } + } + } + + override fun onDestroyBinding(binding: DialogMusicPickerBinding) { + binding.pickerRecycler.adapter = null + } + + override fun onItemClick(item: Item) { + check(item is Genre) { "Unexpected datatype: ${item::class.simpleName}" } + findNavController().navigateUp() + when (args.pickerMode) { + PickerMode.GO -> navModel.exploreNavigateTo(item) + PickerMode.PLAY -> { + val song = unlikelyToBeNull(pickerModel.currentSong.value) + playbackModel.playFromGenre(song, item) + } + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/PickerMode.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/PickerMode.kt new file mode 100644 index 000000000..03cb26234 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/PickerMode.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Auxio Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.music.picker + +/** + * Represents the actions available to the picker UI. + */ +enum class PickerMode { + PLAY, + GO +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/PickerViewModel.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/PickerViewModel.kt new file mode 100644 index 000000000..9dd32a185 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/PickerViewModel.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 Auxio Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.music.picker + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicStore +import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.util.unlikelyToBeNull + +/** + * A small ViewModel holding and updating the current song being shown in the picker UI. + * @author OxygenCobalt + */ +class PickerViewModel : ViewModel(), MusicStore.Callback { + private val musicStore = MusicStore.getInstance() + + private val _currentSong = MutableStateFlow(null) + val currentSong: StateFlow get() = _currentSong + + fun setSongUid(uid: Music.UID) { + if (_currentSong.value?.uid == uid) return + val library = unlikelyToBeNull(musicStore.library) + _currentSong.value = requireNotNull(library.find(uid)) { "Invalid song id provided" } + } + + override fun onLibraryChanged(library: MusicStore.Library?) { + if (library != null) { + val song = _currentSong.value + if (song != null) { + _currentSong.value = library.sanitize(song) + } + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/separators/SeparatorsDialog.kt similarity index 97% rename from app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt rename to app/src/main/java/org/oxycblt/auxio/music/separators/SeparatorsDialog.kt index 5782c337c..28a706352 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/separators/SeparatorsDialog.kt @@ -15,14 +15,13 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.settings +package org.oxycblt.auxio.music.separators import android.os.Bundle import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog import androidx.core.view.children import com.google.android.material.checkbox.MaterialCheckBox -import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogSeparatorsBinding import org.oxycblt.auxio.settings.Settings 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 5395b3e66..e97c28388 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 @@ -32,12 +32,12 @@ import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.music.extractor.Api21MediaStoreLayer import org.oxycblt.auxio.music.extractor.Api29MediaStoreLayer import org.oxycblt.auxio.music.extractor.Api30MediaStoreLayer import org.oxycblt.auxio.music.extractor.CacheLayer import org.oxycblt.auxio.music.extractor.MetadataLayer -import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logE import org.oxycblt.auxio.util.logW diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt index 474f5968e..d31f28152 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt @@ -32,7 +32,6 @@ import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.dsToMs import org.oxycblt.auxio.music.msToDs -import org.oxycblt.auxio.music.ui.MusicMode import org.oxycblt.auxio.playback.state.InternalPlayer import org.oxycblt.auxio.playback.state.PlaybackStateDatabase import org.oxycblt.auxio.playback.state.PlaybackStateManager @@ -92,19 +91,9 @@ class PlaybackViewModel(application: Application) : // --- PLAYING FUNCTIONS --- - /** Play a [song] with the [mode] specified, */ - fun play(song: Song, mode: MusicMode) { - // TODO: Remove this function when selection is implemented - - val parent = - when (mode) { - MusicMode.GENRES -> song.album - MusicMode.ARTISTS -> song.album.artist - MusicMode.ALBUMS -> song.genres.maxBy { it.songs.size } - MusicMode.SONGS -> null - } - - playbackManager.play(song, parent, settings) + /** Play a [song] from all songs. */ + fun play(song: Song) { + playbackManager.play(song, null, settings) } /** Play a song from it's album. */ diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt index 4b65090c9..db99fddeb 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt @@ -21,7 +21,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.widget.TextView import androidx.appcompat.app.AlertDialog -import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogPreAmpBinding import org.oxycblt.auxio.settings.Settings 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 996c716c6..ddf26ddc7 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -29,16 +29,19 @@ 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 import org.oxycblt.auxio.music.Artist 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.Song -import org.oxycblt.auxio.music.ui.MusicMode +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.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener @@ -147,7 +150,20 @@ class SearchFragment : override fun onItemClick(item: Item) { when (item) { - is Song -> playbackModel.play(item, settings.libPlaybackMode) + is Song -> when (settings.libPlaybackMode) { + MusicMode.SONGS -> playbackModel.play(item) + MusicMode.ALBUMS -> playbackModel.playFromAlbum(item) + MusicMode.ARTISTS -> playbackModel.playFromArtist(item) + MusicMode.GENRES -> if (item.genres.size > 1) { + navModel.mainNavigateTo( + MainNavigationAction.Directions( + MainFragmentDirections.showGenrePickerDialog(item.uid, PickerMode.PLAY) + ) + ) + } else { + playbackModel.playFromGenre(item, item.genres[0]) + } + } is MusicParent -> navModel.exploreNavigateTo(item) } } diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt index 17b28c5fa..5eb802480 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt @@ -33,10 +33,10 @@ import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicMode import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort +import org.oxycblt.auxio.music.Sort import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.recycler.Header import org.oxycblt.auxio.ui.recycler.Item diff --git a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt index 5195cf60e..da5ee7ee8 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt @@ -28,9 +28,9 @@ import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R import org.oxycblt.auxio.home.tabs.Tab import org.oxycblt.auxio.music.Directory -import org.oxycblt.auxio.music.settings.MusicDirs -import org.oxycblt.auxio.music.ui.MusicMode -import org.oxycblt.auxio.music.ui.Sort +import org.oxycblt.auxio.music.MusicMode +import org.oxycblt.auxio.music.Sort +import org.oxycblt.auxio.music.dirs.MusicDirs import org.oxycblt.auxio.playback.BarAction import org.oxycblt.auxio.playback.replaygain.ReplayGainMode import org.oxycblt.auxio.playback.replaygain.ReplayGainPreAmp diff --git a/app/src/main/res/layout/dialog_music_picker.xml b/app/src/main/res/layout/dialog_music_picker.xml new file mode 100644 index 000000000..b358ea46b --- /dev/null +++ b/app/src/main/res/layout/dialog_music_picker.xml @@ -0,0 +1,9 @@ + + diff --git a/app/src/main/res/layout/item_picker_choice.xml b/app/src/main/res/layout/item_picker_choice.xml new file mode 100644 index 000000000..3aa25d851 --- /dev/null +++ b/app/src/main/res/layout/item_picker_choice.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index 147eadaa3..56b22133e 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -17,8 +17,24 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ecf10f570..b9aa4809a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -102,8 +102,11 @@ Play next Add to queue + Go to genre Go to artist Go to album + Play from genre + Play from artist View properties Song properties @@ -203,8 +206,8 @@ Play from shown item Play from all songs Play from album - Play from artist - Play from genre + @string/lbl_play_artist + @string/lbl_play_genre Remember shuffle Keep shuffle on when playing a new song Rewind before skipping back