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