From fcc6a7e8d7a6ecdb4332cdf6deca1c9729cbc65b Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Mon, 4 Jan 2021 15:38:10 -0700 Subject: [PATCH] Update sorting Make some changes to the sorting system. --- .../auxio/detail/AlbumDetailFragment.kt | 12 +++- .../playback/state/PlaybackStateManager.kt | 57 +++++++++---------- .../org/oxycblt/auxio/recycler/SortMode.kt | 23 ++++++++ .../java/org/oxycblt/auxio/ui/ActionMenu.kt | 30 +++------- .../java/org/oxycblt/auxio/ui/EdgeUtils.kt | 2 +- .../auxio/ui/FragmentBinderDelegate.kt | 2 +- .../org/oxycblt/auxio/ui/InterfaceUtils.kt | 10 +--- app/src/main/res/layout/fragment_detail.xml | 1 + 8 files changed, 72 insertions(+), 65 deletions(-) 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 ee99fc2ad..89209a94f 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -137,19 +137,27 @@ class AlbumDetailFragment : DetailFragment() { } /** - * Calculate the position and and scroll to a currently playing item. + * Scroll to the currently playing item. */ private fun scrollToPlayingItem() { - // Calculate where the item for the currently played song is, and scroll to there + // Calculate where the item for the currently played song is, -1 if it isnt here val pos = detailModel.albumSortMode.value!!.getSortedSongList( detailModel.currentAlbum.value!!.songs ).indexOf(playbackModel.song.value) if (pos != -1) { binding.detailRecycler.post { + // Make sure to increment the position to make up for the detail header binding.detailRecycler.layoutManager?.startSmoothScroll( CenterSmoothScroller(requireContext(), pos.inc()) ) + + // If the recyclerview can scroll, its certain that it will have to scroll to + // correctly center the playing item, so make sure that the Toolbar is lifted in + // that case. + if (binding.detailRecycler.computeVerticalScrollRange() > binding.detailRecycler.height) { + binding.detailAppbar.isLifted = true + } } detailModel.doneWithNavToItem() diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index d1ba9866a..c58d81160 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -27,6 +27,7 @@ import kotlin.random.Random * * All access should be done with [PlaybackStateManager.getInstance]. * @author OxygenCobalt + * // TODO: Sort queues */ class PlaybackStateManager private constructor() { // Playback @@ -675,7 +676,7 @@ class PlaybackStateManager private constructor() { } /** - * Back the current state into a [PlaybackState] to be saved. + * Pack the current state into a [PlaybackState] to be saved. * @return A [PlaybackState] reflecting the current state. */ private fun packToPlaybackState(): PlaybackState { @@ -696,28 +697,6 @@ class PlaybackStateManager private constructor() { ) } - /** - * Pack the queue into a list of [QueueItem]s to be saved. - * @return A list of packed queue items. - */ - private fun packQueue(): List { - val unified = mutableListOf() - - var queueItemId = 0L - - mUserQueue.forEach { - unified.add(QueueItem(queueItemId, it.name, it.album.name, true)) - queueItemId++ - } - - mQueue.forEach { - unified.add(QueueItem(queueItemId, it.name, it.album.name, false)) - queueItemId++ - } - - return unified - } - /** * Unpack the state from a [PlaybackState] * @param playbackState The state to unpack. @@ -742,6 +721,28 @@ class PlaybackStateManager private constructor() { } } + /** + * Pack the queue into a list of [QueueItem]s to be saved. + * @return A list of packed queue items. + */ + private fun packQueue(): List { + val unified = mutableListOf() + + var queueItemId = 0L + + mUserQueue.forEach { + unified.add(QueueItem(queueItemId, it.name, it.album.name, true)) + queueItemId++ + } + + mQueue.forEach { + unified.add(QueueItem(queueItemId, it.name, it.album.name, false)) + queueItemId++ + } + + return unified + } + /** * Unpack a list of queue items into a queue & user queue. * @param queueItems The list of [QueueItem]s to unpack. @@ -810,20 +811,14 @@ class PlaybackStateManager private constructor() { * Create an ordered queue based on an [Album]. */ private fun orderSongsInAlbum(album: Album): MutableList { - return album.songs.sortedBy { it.track }.toMutableList() + return SortMode.NUMERIC_DOWN.getSortedSongList(album.songs).toMutableList() } /** * Create an ordered queue based on an [Artist]. */ private fun orderSongsInArtist(artist: Artist): MutableList { - val final = mutableListOf() - - artist.albums.sortedByDescending { it.year }.forEach { album -> - final.addAll(album.songs.sortedBy { it.track }) - } - - return final + return SortMode.NUMERIC_DOWN.getSortedArtistSongList(artist.songs).toMutableList() } /** diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt b/app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt index 0249e1148..058df649a 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt +++ b/app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt @@ -11,6 +11,7 @@ import org.oxycblt.auxio.music.Song /** * An enum for the current sorting mode. Contains helper functions to sort lists based * off the given sorting mode. + * TODO: Improve sorting by separating UP/DOWN from what should be sorted (Names, Tracks, etc) * @property iconRes The icon for this [SortMode] * @author OxygenCobalt */ @@ -85,6 +86,28 @@ enum class SortMode(@DrawableRes val iconRes: Int) { } } + /** + * Get a sorted list of songs with regards to an artist. + * @param songs An unsorted list of songs + * @return The sorted list of songs + */ + fun getSortedArtistSongList(songs: List): List { + return when (this) { + ALPHA_UP -> songs.sortedWith( + compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name } + ) + + ALPHA_DOWN -> songs.sortedWith( + compareBy(String.CASE_INSENSITIVE_ORDER) { it.name } + ) + + NUMERIC_UP -> songs.sortedWith(compareBy { it.album.year }) + NUMERIC_DOWN -> songs.sortedWith(compareByDescending { it.album.year }) + + else -> songs + } + } + /** * Get a sorted list of BaseModels. Supports alpha + numeric sorting. * @param baseModels An unsorted list of BaseModels. diff --git a/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt b/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt index 8e2505935..b0c955498 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt @@ -21,7 +21,8 @@ import org.oxycblt.auxio.playback.state.PlaybackMode * @param activity [AppCompatActivity] required as both a context and ViewModelStore owner. * @param anchor [View] This should be centered around * @param data [BaseModel] this menu corresponds to - * @param flag Any extra flags to accompany the data. See [Companion] for more details. + * @param flag Any extra flags to accompany the data. + * See [FLAG_NONE], [FLAG_IN_ALBUM], [FLAG_IN_ARTIST] and [FLAG_IN_GENRE] for more details. */ class ActionMenu( activity: AppCompatActivity, @@ -84,11 +85,13 @@ class ActionMenu( } } + /** + * Determine what to do when a MenuItem is clicked. + */ private fun onMenuClick(@IdRes id: Int) { when (id) { R.id.action_play -> { when (data) { - is Song -> playbackModel.playSong(data, getPlaybackModeFromFlag()) is Album -> playbackModel.playAlbum(data, false) is Artist -> playbackModel.playArtist(data, false) is Genre -> playbackModel.playGenre(data, false) @@ -114,21 +117,17 @@ class ActionMenu( } R.id.action_queue_add -> { - val success = when (data) { + when (data) { is Song -> { playbackModel.addToUserQueue(data) - true + context.getString(R.string.label_queue_added).createToast(context) } is Album -> { playbackModel.addToUserQueue(data) - true + context.getString(R.string.label_queue_added).createToast(context) } - else -> false - } - - if (success) { - context.getString(R.string.label_queue_added).createToast(context) + else -> {} } } @@ -156,17 +155,6 @@ class ActionMenu( } } - private fun getPlaybackModeFromFlag(): PlaybackMode { - return when (flag) { - FLAG_NONE -> PlaybackMode.ALL_SONGS - FLAG_IN_ALBUM -> PlaybackMode.IN_ALBUM - FLAG_IN_ARTIST -> PlaybackMode.IN_ARTIST - FLAG_IN_GENRE -> PlaybackMode.IN_GENRE - - else -> PlaybackMode.ALL_SONGS - } - } - companion object { /** No Flags **/ const val FLAG_NONE = -1 diff --git a/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt index 8a9e11983..ce36a5f9b 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/EdgeUtils.kt @@ -13,7 +13,7 @@ import android.view.WindowManager /** * Check if we are in the "Irregular" landscape mode [e.g landscape, but nav bar is on the sides] - * Used to disable most of edge-to-edge if that's the case, as I cant get it to work on this mode yet. + * Used to disable most of edge-to-edge if that's the case, as I cant get it to work on this mode. * @return True if we are in the irregular landscape mode, false if not. */ fun Activity.isIrregularLandscape(): Boolean { diff --git a/app/src/main/java/org/oxycblt/auxio/ui/FragmentBinderDelegate.kt b/app/src/main/java/org/oxycblt/auxio/ui/FragmentBinderDelegate.kt index bdbe23e74..5c5df8aac 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/FragmentBinderDelegate.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/FragmentBinderDelegate.kt @@ -16,7 +16,7 @@ import kotlin.reflect.KProperty * A delegate that creates a binding that can be used as a member variable without nullability or * memory leaks. * @param bindingFactory The ViewBinding inflation method that should be used - * @param onDestroy Any code that should be run when the binding is destroyed. + * @param onDestroy Any code that should be run when the binding is destroyed */ fun Fragment.memberBinding( bindingFactory: (LayoutInflater) -> T, diff --git a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt index 2d4d43972..48c90bdce 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt @@ -13,19 +13,11 @@ import android.widget.TextView import android.widget.Toast import androidx.annotation.ColorInt import androidx.annotation.ColorRes -import androidx.annotation.MenuRes import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.PopupMenu import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import com.google.android.material.button.MaterialButton import org.oxycblt.auxio.R -import org.oxycblt.auxio.detail.DetailViewModel -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.playback.PlaybackViewModel /** * Apply a text color to a [MenuItem] @@ -116,6 +108,6 @@ fun Fragment.requireCompatActivity(): AppCompatActivity { if (activity is AppCompatActivity) { return activity } else { - error("Required activity to be AppCompatActivity, however it wasn't.") + error("Required AppCompatActivity, got ${activity::class.simpleName} instead.") } } diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml index 628ff2eca..e8d6cfdae 100644 --- a/app/src/main/res/layout/fragment_detail.xml +++ b/app/src/main/res/layout/fragment_detail.xml @@ -9,6 +9,7 @@ android:layout_height="match_parent">