Update sorting

Make some changes to the sorting system.
This commit is contained in:
OxygenCobalt 2021-01-04 15:38:10 -07:00
parent 119078fc77
commit fcc6a7e8d7
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 72 additions and 65 deletions

View file

@ -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()

View file

@ -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<QueueItem> {
val unified = mutableListOf<QueueItem>()
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<QueueItem> {
val unified = mutableListOf<QueueItem>()
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<Song> {
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<Song> {
val final = mutableListOf<Song>()
artist.albums.sortedByDescending { it.year }.forEach { album ->
final.addAll(album.songs.sortedBy { it.track })
}
return final
return SortMode.NUMERIC_DOWN.getSortedArtistSongList(artist.songs).toMutableList()
}
/**

View file

@ -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<Song>): List<Song> {
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.

View file

@ -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

View file

@ -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 {

View file

@ -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 <T : ViewBinding> Fragment.memberBinding(
bindingFactory: (LayoutInflater) -> T,

View file

@ -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.")
}
}

View file

@ -9,6 +9,7 @@
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/detail_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">