Update sorting
Make some changes to the sorting system.
This commit is contained in:
parent
119078fc77
commit
fcc6a7e8d7
8 changed files with 72 additions and 65 deletions
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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">
|
||||
|
|
Loading…
Reference in a new issue