diff --git a/app/src/main/java/code/name/monkey/retromusic/Constants.kt b/app/src/main/java/code/name/monkey/retromusic/Constants.kt index a8e96d211..bab9ec6d6 100644 --- a/app/src/main/java/code/name/monkey/retromusic/Constants.kt +++ b/app/src/main/java/code/name/monkey/retromusic/Constants.kt @@ -135,6 +135,7 @@ const val LOCK_SCREEN = "lock_screen" const val ALBUM_ARTISTS_ONLY = "album_artists_only" const val ALBUM_ARTIST = "album_artist" const val ALBUM_DETAIL_SONG_SORT_ORDER = "album_detail_song_sort_order" +const val ARTIST_DETAIL_SONG_SORT_ORDER = "artist_detail_song_sort_order" const val LYRICS_OPTIONS = "lyrics_tab_position" const val CHOOSE_EQUALIZER = "choose_equalizer" const val EQUALIZER = "equalizer" diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt index 39c092e69..750e79133 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt @@ -5,11 +5,9 @@ import android.content.Intent import android.graphics.Color import android.os.Bundle import android.text.Spanned -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem -import android.view.View +import android.view.* import androidx.activity.addCallback +import androidx.appcompat.widget.PopupMenu import androidx.core.os.bundleOf import androidx.core.text.HtmlCompat import androidx.core.view.ViewCompat @@ -32,6 +30,7 @@ import code.name.monkey.retromusic.glide.GlideApp import code.name.monkey.retromusic.glide.RetroGlideExtension import code.name.monkey.retromusic.glide.SingleColorTarget import code.name.monkey.retromusic.helper.MusicPlayerRemote +import code.name.monkey.retromusic.helper.SortOrder import code.name.monkey.retromusic.interfaces.IAlbumClickListener import code.name.monkey.retromusic.interfaces.ICabCallback import code.name.monkey.retromusic.interfaces.ICabHolder @@ -39,10 +38,7 @@ import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.network.Result import code.name.monkey.retromusic.network.model.LastFmArtist import code.name.monkey.retromusic.repository.RealRepository -import code.name.monkey.retromusic.util.CustomArtistImageUtil -import code.name.monkey.retromusic.util.MusicUtil -import code.name.monkey.retromusic.util.RetroColorUtil -import code.name.monkey.retromusic.util.RetroUtil +import code.name.monkey.retromusic.util.* import com.afollestad.materialcab.attached.AttachedCab import com.afollestad.materialcab.attached.destroy import com.afollestad.materialcab.attached.isActive @@ -71,6 +67,9 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm private var lang: String? = null private var biography: Spanned? = null + private val savedSongSortOrder: String + get() = PreferenceUtil.artistDetailSongSortOrder + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) sharedElementEnterTransition = MaterialContainerTransform().apply { @@ -101,7 +100,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm setupRecyclerView() binding.fragmentArtistContent.playAction.apply { - setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) } + setOnClickListener { MusicPlayerRemote.openQueue(artist.sortedSongs, 0, true) } } binding.fragmentArtistContent.shuffleAction.apply { setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) } @@ -121,6 +120,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm requireActivity().onBackPressed() } } + setupSongSortButton() binding.appBarLayout?.statusBarForeground = MaterialShapeDrawable.createWithElevationOverlay(requireContext()) } @@ -168,7 +168,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm ) binding.fragmentArtistContent.songTitle.text = songText binding.fragmentArtistContent.albumTitle.text = albumText - songAdapter.swapDataSet(artist.songs.sortedBy { it.trackNumber }) + songAdapter.swapDataSet(artist.sortedSongs) albumAdapter.swapDataSet(artist.albums) } @@ -289,6 +289,53 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm return true } + private fun setupSongSortButton() { + binding.fragmentArtistContent.songSortOrder.setOnClickListener { + PopupMenu(requireContext(), binding.fragmentArtistContent.songSortOrder).apply { + inflate(R.menu.menu_artist_song_sort_order) + setUpSortOrderMenu(menu) + setOnMenuItemClickListener { menuItem -> + val sortOrder = when (menuItem.itemId) { + R.id.action_sort_order_title -> SortOrder.ArtistSongSortOrder.SONG_A_Z + R.id.action_sort_order_title_desc -> SortOrder.ArtistSongSortOrder.SONG_Z_A + R.id.action_sort_order_album -> SortOrder.ArtistSongSortOrder.SONG_ALBUM + R.id.action_sort_order_year -> SortOrder.ArtistSongSortOrder.SONG_YEAR + R.id.action_sort_order_song_duration -> SortOrder.ArtistSongSortOrder.SONG_DURATION + else -> { + throw IllegalArgumentException("invalid ${menuItem.title}") + } + } + menuItem.isChecked = true + setSaveSortOrder(sortOrder) + return@setOnMenuItemClickListener true + } + show() + } + } + } + + private fun setSaveSortOrder(sortOrder: String) { + PreferenceUtil.artistDetailSongSortOrder = sortOrder + songAdapter.swapDataSet(artist.sortedSongs) + } + + private fun setUpSortOrderMenu(sortOrder: Menu) { + when (savedSongSortOrder) { + SortOrder.ArtistSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_ALBUM -> + sortOrder.findItem(R.id.action_sort_order_album).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_YEAR -> + sortOrder.findItem(R.id.action_sort_order_year).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_DURATION -> + sortOrder.findItem(R.id.action_sort_order_song_duration).isChecked = true + else-> { + throw IllegalArgumentException("invalid $savedSongSortOrder") + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/SortOrder.kt b/app/src/main/java/code/name/monkey/retromusic/helper/SortOrder.kt index 0771b2936..b77e39d09 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/SortOrder.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/SortOrder.kt @@ -134,7 +134,7 @@ class SortOrder { companion object { /* Artist song sort order A-Z */ - private const val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER + const val SONG_A_Z = MediaStore.Audio.Media.DEFAULT_SORT_ORDER /* Artist song sort order Z-A */ const val SONG_Z_A = "$SONG_A_Z DESC" diff --git a/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt b/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt index faf133986..c9d7e42dc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt +++ b/app/src/main/java/code/name/monkey/retromusic/model/Artist.kt @@ -14,7 +14,9 @@ package code.name.monkey.retromusic.model +import code.name.monkey.retromusic.helper.SortOrder import code.name.monkey.retromusic.util.MusicUtil +import code.name.monkey.retromusic.util.PreferenceUtil data class Artist( val id: Long, @@ -29,7 +31,7 @@ data class Artist( name = artistName } - var name: String = "" + var name: String = "-" get() { val name = if (isAlbumArtist) getAlbumArtistName() else getArtistName() @@ -57,6 +59,39 @@ data class Artist( val songs: List get() = albums.flatMap { it.songs } + val sortedSongs: List + get() = songs.sortedWith( + when (PreferenceUtil.artistDetailSongSortOrder) { + SortOrder.ArtistSongSortOrder.SONG_A_Z -> { o1, o2 -> + o1.title.compareTo( + o2.title + ) + } + SortOrder.ArtistSongSortOrder.SONG_Z_A -> { o1, o2 -> + o2.title.compareTo( + o1.title + ) + } + SortOrder.ArtistSongSortOrder.SONG_ALBUM -> { o1, o2 -> + o1.albumName.compareTo( + o2.albumName + ) + } + SortOrder.ArtistSongSortOrder.SONG_YEAR -> { o1, o2 -> + o2.year.compareTo( + o1.year + ) + } + SortOrder.ArtistSongSortOrder.SONG_DURATION -> { o1, o2 -> + o1.duration.compareTo( + o2.duration + ) + } + else -> { + throw IllegalArgumentException("invalid ${PreferenceUtil.artistDetailSongSortOrder}") + } + }) + fun safeGetFirstAlbum(): Album { return albums.firstOrNull() ?: Album.empty } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt index 6aca8cde7..ab72dfa15 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt @@ -130,6 +130,13 @@ object PreferenceUtil { ) set(value) = sharedPreferences.edit { putString(ALBUM_DETAIL_SONG_SORT_ORDER, value) } + var artistDetailSongSortOrder + get() = sharedPreferences.getStringOrDefault( + ARTIST_DETAIL_SONG_SORT_ORDER, + ArtistSongSortOrder.SONG_A_Z + ) + set(value) = sharedPreferences.edit { putString(ARTIST_DETAIL_SONG_SORT_ORDER, value) } + var songSortOrder get() = sharedPreferences.getStringOrDefault( SONG_SORT_ORDER, diff --git a/app/src/main/res/layout/fragment_artist_content.xml b/app/src/main/res/layout/fragment_artist_content.xml index 6c3fb06d9..e727ed704 100644 --- a/app/src/main/res/layout/fragment_artist_content.xml +++ b/app/src/main/res/layout/fragment_artist_content.xml @@ -1,5 +1,5 @@ - + app:layout_constraintTop_toBottomOf="@id/albumRecyclerView"/> + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_artist_song_sort_order.xml b/app/src/main/res/menu/menu_artist_song_sort_order.xml new file mode 100644 index 000000000..71bace116 --- /dev/null +++ b/app/src/main/res/menu/menu_artist_song_sort_order.xml @@ -0,0 +1,20 @@ + + + + + + + + + + \ No newline at end of file