From 35814c5b4064366deb193cff12513c96863ccabd Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Thu, 24 Sep 2020 16:15:34 -0600 Subject: [PATCH] Add sorting to AlbumDetailFragment Add sorting to AlbumDetailFragment. Ignore the other commit. --- .../java/org/oxycblt/auxio/MainFragment.kt | 21 +++-------- .../auxio/detail/AlbumDetailFragment.kt | 19 +++++++++- .../auxio/detail/ArtistDetailFragment.kt | 20 +++++++++- .../oxycblt/auxio/detail/DetailViewModel.kt | 27 ++++++++++++++ .../detail/adapters/DetailAlbumAdapter.kt | 9 ++--- .../detail/adapters/DetailSongAdapter.kt | 9 ++--- .../auxio/music/processing/MusicSorter.kt | 12 ++---- .../oxycblt/auxio/recycler/RecyclerUtils.kt | 37 +++++++++---------- .../main/res/layout/fragment_album_detail.xml | 17 +++++++++ .../res/layout/fragment_artist_detail.xml | 21 +++++++++++ 10 files changed, 137 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index d7ba48875..8de267f57 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -21,8 +21,8 @@ import org.oxycblt.auxio.theme.toColor class MainFragment : Fragment() { private val shownFragments = listOf(0, 1) - private lateinit var libraryFragment: LibraryFragment - private lateinit var songsFragment: SongsFragment + private val libraryFragment: LibraryFragment by lazy { LibraryFragment() } + private val songsFragment: SongsFragment by lazy { SongsFragment() } private val tabIcons = listOf( R.drawable.ic_library, @@ -81,21 +81,10 @@ class MainFragment : Fragment() { private fun fragmentAt(position: Int): Fragment { return when (position) { - 0 -> { - if (!::libraryFragment.isInitialized) { - libraryFragment = LibraryFragment() - } + 0 -> libraryFragment + 1 -> songsFragment - libraryFragment - } - - else -> { - if (!::songsFragment.isInitialized) { - songsFragment = SongsFragment() - } - - songsFragment - } + else -> libraryFragment } } 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 b2dd8847f..291350ea8 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -14,6 +14,7 @@ import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding import org.oxycblt.auxio.detail.adapters.DetailSongAdapter import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.recycler.ClickListener +import org.oxycblt.auxio.recycler.SortMode import org.oxycblt.auxio.theme.applyDivider class AlbumDetailFragment : Fragment() { @@ -39,7 +40,6 @@ class AlbumDetailFragment : Fragment() { } val songAdapter = DetailSongAdapter( - detailModel.currentAlbum!!.songs, ClickListener { Log.d(this::class.simpleName, it.name) } @@ -73,6 +73,23 @@ class AlbumDetailFragment : Fragment() { binding.artistName.setBackgroundResource(R.drawable.ripple) } + detailModel.albumSortMode.observe(viewLifecycleOwner) { mode -> + // Update the current sort icon + binding.sortButton.setImageResource(mode.iconRes) + + // Then update the sort mode of the album adapter. + songAdapter.submitList( + detailModel.currentAlbum!!.songs.sortedWith( + SortMode.songSortComparators.getOrDefault( + mode, + + // If any invalid value is given, just default to the normal sort order. + compareByDescending { it.track } + ) + ) + ) + } + Log.d(this::class.simpleName, "Fragment created.") return binding.root 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 478812fc1..f2c0c1706 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -14,6 +14,7 @@ import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.models.Album import org.oxycblt.auxio.recycler.ClickListener +import org.oxycblt.auxio.recycler.SortMode import org.oxycblt.auxio.theme.applyDivider class ArtistDetailFragment : Fragment() { @@ -38,19 +39,36 @@ class ArtistDetailFragment : Fragment() { } val albumAdapter = DetailAlbumAdapter( - detailModel.currentArtist!!.albums, ClickListener { navToAlbum(it) } ) binding.lifecycleOwner = this + binding.detailModel = detailModel binding.artist = detailModel.currentArtist!! binding.albumRecycler.adapter = albumAdapter binding.albumRecycler.applyDivider() binding.albumRecycler.setHasFixedSize(true) + detailModel.artistSortMode.observe(viewLifecycleOwner) { mode -> + // Update the current sort icon + binding.sortButton.setImageResource(mode.iconRes) + + // Then update the sort mode of the album adapter. + albumAdapter.submitList( + detailModel.currentArtist!!.albums.sortedWith( + SortMode.albumSortComparators.getOrDefault( + mode, + + // If any invalid value is given, just default to the normal sort order. + compareByDescending { it.year } + ) + ) + ) + } + Log.d(this::class.simpleName, "Fragment created.") return binding.root 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 cbf21235e..edcbe3707 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.oxycblt.auxio.music.models.Album import org.oxycblt.auxio.music.models.Artist +import org.oxycblt.auxio.recycler.SortMode class DetailViewModel : ViewModel() { var isAlreadyNavigating = false @@ -12,6 +13,12 @@ class DetailViewModel : ViewModel() { private val mNavToParentArtist = MutableLiveData() val navToParentArtist: LiveData get() = mNavToParentArtist + private val mArtistSortMode = MutableLiveData(SortMode.NUMERIC_DOWN) + val artistSortMode: LiveData get() = mArtistSortMode + + private val mAlbumSortMode = MutableLiveData(SortMode.NUMERIC_DOWN) + val albumSortMode: LiveData get() = mAlbumSortMode + var currentArtist: Artist? = null var currentAlbum: Album? = null @@ -22,4 +29,24 @@ class DetailViewModel : ViewModel() { fun doneWithNavToParent() { mNavToParentArtist.value = false } + + fun incrementArtistSortMode() { + mArtistSortMode.value = when (mArtistSortMode.value) { + SortMode.NUMERIC_DOWN -> SortMode.NUMERIC_UP + SortMode.NUMERIC_UP -> SortMode.ALPHA_DOWN + SortMode.ALPHA_DOWN -> SortMode.ALPHA_UP + SortMode.ALPHA_UP -> SortMode.NUMERIC_DOWN + + else -> SortMode.NUMERIC_DOWN + } + } + + fun incrementAlbumSortMode() { + mAlbumSortMode.value = when (mAlbumSortMode.value) { + SortMode.NUMERIC_DOWN -> SortMode.NUMERIC_UP + SortMode.NUMERIC_UP -> SortMode.NUMERIC_DOWN + + else -> SortMode.NUMERIC_DOWN + } + } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt index 7f56f09f8..17f5d65a1 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailAlbumAdapter.kt @@ -2,17 +2,16 @@ package org.oxycblt.auxio.detail.adapters import android.view.LayoutInflater import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.ItemAlbumBinding import org.oxycblt.auxio.music.models.Album +import org.oxycblt.auxio.recycler.AlbumDiffCallback import org.oxycblt.auxio.recycler.ClickListener class DetailAlbumAdapter( - private val data: List, private val listener: ClickListener -) : RecyclerView.Adapter() { - - override fun getItemCount(): Int = data.size +) : ListAdapter(AlbumDiffCallback()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( @@ -21,7 +20,7 @@ class DetailAlbumAdapter( } override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.bind(data[position]) + holder.bind(getItem(position)) } // Generic ViewHolder for an album diff --git a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailSongAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailSongAdapter.kt index 18345a7eb..4eeb4a81c 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailSongAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/adapters/DetailSongAdapter.kt @@ -2,17 +2,16 @@ package org.oxycblt.auxio.detail.adapters import android.view.LayoutInflater import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.ItemAlbumSongBinding import org.oxycblt.auxio.music.models.Song import org.oxycblt.auxio.recycler.ClickListener +import org.oxycblt.auxio.recycler.SongDiffCallback class DetailSongAdapter( - private val data: List, private val listener: ClickListener -) : RecyclerView.Adapter() { - - override fun getItemCount(): Int = data.size +) : ListAdapter(SongDiffCallback()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( @@ -21,7 +20,7 @@ class DetailSongAdapter( } override fun onBindViewHolder(holder: ViewHolder, position: Int) { - holder.bind(data[position]) + holder.bind(getItem(position)) } // Generic ViewHolder for a song diff --git a/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt b/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt index 3ea7dc3e8..a87f1c7b8 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/processing/MusicSorter.kt @@ -31,10 +31,8 @@ class MusicSorter( for (album in albums) { // Find all songs that match the current album ID to prevent any bugs w/comparing names. - // Also sort them by their track number. - val albumSongs = songs.filter { - it.albumId == album.id - }.sortedBy { it.track } + // This cant be done with artists/genres sadly. + val albumSongs = songs.filter { it.albumId == album.id } // Then add them to the album for (song in albumSongs) { @@ -74,10 +72,8 @@ class MusicSorter( val unknownAlbums = albums.toMutableList() for (artist in artists) { - // Find all albums that match the current artist name, and then sort them by year - val artistAlbums = albums.filter { - it.artistName == artist.name - }.sortedByDescending { it.year } + // Find all albums that match the current artist name + val artistAlbums = albums.filter { it.artistName == artist.name } // Then add them to the artist, along with refreshing the amount of albums for (album in artistAlbums) { diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt b/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt index 206cc79c0..423c5ff46 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/recycler/RecyclerUtils.kt @@ -8,18 +8,7 @@ import org.oxycblt.auxio.music.models.Song // RecyclerView click listener class ClickListener(val onClick: (T) -> Unit) -// Diff callback for albums -class AlbumDiffCallback : DiffUtil.ItemCallback() { - override fun areContentsTheSame(oldItem: Album, newItem: Album): Boolean { - return oldItem.id == newItem.id - } - - override fun areItemsTheSame(oldItem: Album, newItem: Album): Boolean { - return oldItem == newItem - } -} - -// Diff callback for songs +// Song Diff callback class SongDiffCallback : DiffUtil.ItemCallback() { override fun areContentsTheSame(oldItem: Song, newItem: Song): Boolean { return oldItem.id == newItem.id @@ -30,6 +19,17 @@ class SongDiffCallback : DiffUtil.ItemCallback() { } } +// Album Diff callback +class AlbumDiffCallback : DiffUtil.ItemCallback() { + override fun areContentsTheSame(oldItem: Album, newItem: Album): Boolean { + return oldItem.id == newItem.id + } + + override fun areItemsTheSame(oldItem: Album, newItem: Album): Boolean { + return oldItem == newItem + } +} + // Sorting modes enum class SortMode(val iconRes: Int) { // Icons for each mode are assigned to the enums themselves @@ -40,8 +40,12 @@ enum class SortMode(val iconRes: Int) { NUMERIC_DOWN(R.drawable.ic_sort_numeric_down); companion object { - // Sort comparators are different for each music model, so they are - // static maps instead. + // Sort comparators are different for each music model, so they are static maps instead. + val songSortComparators = mapOf>( + NUMERIC_DOWN to compareBy { it.track }, + NUMERIC_UP to compareByDescending { it.track } + ) + val albumSortComparators = mapOf>( NUMERIC_DOWN to compareByDescending { it.year }, NUMERIC_UP to compareBy { it.year }, @@ -54,10 +58,5 @@ enum class SortMode(val iconRes: Int) { String.CASE_INSENSITIVE_ORDER ) { it.name }, ) - - val songSortComparators = mapOf>( - NUMERIC_DOWN to compareBy { it.track }, - NUMERIC_UP to compareByDescending { it.track } - ) } } diff --git a/app/src/main/res/layout/fragment_album_detail.xml b/app/src/main/res/layout/fragment_album_detail.xml index 1c8732d0d..d57837a7e 100644 --- a/app/src/main/res/layout/fragment_album_detail.xml +++ b/app/src/main/res/layout/fragment_album_detail.xml @@ -112,6 +112,23 @@ android:textSize="16sp" app:layout_constraintTop_toBottomOf="@+id/album_year" /> + + + + + +